[NI] Remove Nothing result type restriction in most cases
Make Nothing as result type not suitable only for if, when, try and ?: special functions.
This commit is contained in:
@@ -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.ResultTypeResolver
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle
|
import org.jetbrains.kotlin.resolve.calls.inference.components.TrivialConstraintTypeInferenceOracle
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewConstraintSystemImpl
|
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.AbstractTypeApproximator
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
import org.jetbrains.kotlin.types.checker.KotlinTypeRefiner
|
||||||
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
import org.jetbrains.kotlin.types.model.SimpleTypeMarker
|
||||||
@@ -53,7 +54,7 @@ class InferenceComponents(
|
|||||||
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)
|
val trivialConstraintTypeInferenceOracle = TrivialConstraintTypeInferenceOracle.create(ctx)
|
||||||
private val incorporator = ConstraintIncorporator(approximator, trivialConstraintTypeInferenceOracle)
|
private val incorporator = ConstraintIncorporator(approximator, trivialConstraintTypeInferenceOracle)
|
||||||
private val injector = ConstraintInjector(incorporator, approximator, KotlinTypeRefiner.Default)
|
private val injector = ConstraintInjector(incorporator, approximator, KotlinTypeRefiner.Default)
|
||||||
val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle)
|
val resultTypeResolver = ResultTypeResolver(approximator, trivialConstraintTypeInferenceOracle, null)
|
||||||
|
|
||||||
fun createConstraintSystem(): NewConstraintSystemImpl {
|
fun createConstraintSystem(): NewConstraintSystemImpl {
|
||||||
return NewConstraintSystemImpl(injector, ctx)
|
return NewConstraintSystemImpl(injector, ctx)
|
||||||
|
|||||||
Generated
+10
@@ -10595,6 +10595,11 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirOldFronte
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/implicitNothingConstraintFromReturn.kt");
|
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")
|
@TestMetadata("kt24490.kt")
|
||||||
public void testKt24490() throws Exception {
|
public void testKt24490() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/nothingType/kt24490.kt");
|
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");
|
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")
|
@TestMetadata("kt32250.kt")
|
||||||
public void testKt32250() throws Exception {
|
public void testKt32250() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
||||||
|
|||||||
+1
-1
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.types.expressions.ExpressionTypingUtils
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
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(
|
class GenericCandidateResolver(
|
||||||
private val argumentTypeResolver: ArgumentTypeResolver,
|
private val argumentTypeResolver: ArgumentTypeResolver,
|
||||||
|
|||||||
+1
-2
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
|||||||
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
import org.jetbrains.kotlin.builtins.isBuiltinFunctionalType
|
||||||
import org.jetbrains.kotlin.builtins.isFunctionType
|
import org.jetbrains.kotlin.builtins.isFunctionType
|
||||||
import org.jetbrains.kotlin.diagnostics.Errors
|
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.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.types.DeferredType
|
import org.jetbrains.kotlin.types.DeferredType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
import org.jetbrains.kotlin.types.TypeUtils
|
||||||
@@ -17,8 +18,6 @@ import org.jetbrains.kotlin.types.typeUtil.isNothing
|
|||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
|
|
||||||
object ImplicitNothingAsTypeParameterCallChecker : CallChecker {
|
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 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.
|
* the return type of which is a type variable, that was inferred to Nothing.
|
||||||
|
|||||||
+1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.psi.psiUtil.getBinaryWithTypeParent
|
|||||||
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
import org.jetbrains.kotlin.psi.psiUtil.lastBlockStatementOrThis
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.ArgumentTypeResolver
|
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.InferenceSession
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
import org.jetbrains.kotlin.resolve.calls.components.KotlinResolutionCallbacks
|
||||||
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
|
||||||
|
|||||||
+10
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.config.LanguageVersionSettings
|
|||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtSuperExpression
|
import org.jetbrains.kotlin.psi.KtSuperExpression
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||||
import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isConventionCall
|
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.model.SimpleKotlinCallArgument
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
import org.jetbrains.kotlin.resolve.deprecation.DeprecationResolver
|
||||||
|
import org.jetbrains.kotlin.types.expressions.ControlStructureTypingUtils
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
||||||
|
|
||||||
class KotlinResolutionStatelessCallbacksImpl(
|
class KotlinResolutionStatelessCallbacksImpl(
|
||||||
@@ -95,4 +97,12 @@ class KotlinResolutionStatelessCallbacksImpl(
|
|||||||
else
|
else
|
||||||
ConstraintSystemBuilderImpl.forSpecificity()
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+5
-1
@@ -12,12 +12,12 @@ import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
|||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
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.components.ConstraintInjector
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
import org.jetbrains.kotlin.resolve.calls.inference.model.NewTypeVariable
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.*
|
import org.jetbrains.kotlin.resolve.calls.model.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
import org.jetbrains.kotlin.resolve.calls.results.SimpleConstraintSystem
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.ImplicitScopeTower
|
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.StubType
|
||||||
import org.jetbrains.kotlin.types.UnwrappedType
|
import org.jetbrains.kotlin.types.UnwrappedType
|
||||||
|
|
||||||
@@ -40,6 +40,10 @@ interface KotlinResolutionStatelessCallbacks {
|
|||||||
fun createConstraintSystemForOverloadResolution(
|
fun createConstraintSystemForOverloadResolution(
|
||||||
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns
|
constraintInjector: ConstraintInjector, builtIns: KotlinBuiltIns
|
||||||
): SimpleConstraintSystem
|
): SimpleConstraintSystem
|
||||||
|
|
||||||
|
fun isSpecialFunctionTypeParameterName(name: Name): Boolean
|
||||||
|
|
||||||
|
fun isExclExclTypeParameterName(name: Name): Boolean
|
||||||
}
|
}
|
||||||
|
|
||||||
// This components hold state (trace). Work with this carefully.
|
// This components hold state (trace). Work with this carefully.
|
||||||
|
|||||||
+3
-1
@@ -5,6 +5,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
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.NotEnoughInformationForTypeParameter
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
import org.jetbrains.kotlin.resolve.calls.inference.model.TypeVariableFromCallableDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
import org.jetbrains.kotlin.resolve.calls.inference.model.VariableWithConstraints
|
||||||
@@ -21,7 +22,8 @@ import org.jetbrains.kotlin.utils.addToStdlib.safeAs
|
|||||||
|
|
||||||
class KotlinConstraintSystemCompleter(
|
class KotlinConstraintSystemCompleter(
|
||||||
private val resultTypeResolver: ResultTypeResolver,
|
private val resultTypeResolver: ResultTypeResolver,
|
||||||
private val variableFixationFinder: VariableFixationFinder
|
private val variableFixationFinder: VariableFixationFinder,
|
||||||
|
private val statelessCallbacks: KotlinResolutionStatelessCallbacks
|
||||||
) {
|
) {
|
||||||
enum class ConstraintSystemCompletionMode {
|
enum class ConstraintSystemCompletionMode {
|
||||||
FULL,
|
FULL,
|
||||||
|
|||||||
+36
-24
@@ -17,17 +17,21 @@
|
|||||||
package org.jetbrains.kotlin.resolve.calls.inference.components
|
package org.jetbrains.kotlin.resolve.calls.inference.components
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.calls.NewCommonSuperTypeCalculator
|
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.components.TypeVariableDirectionCalculator.ResolveDirection
|
||||||
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
import org.jetbrains.kotlin.resolve.calls.inference.model.*
|
||||||
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
import org.jetbrains.kotlin.types.AbstractTypeApproximator
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
import org.jetbrains.kotlin.types.model.KotlinTypeMarker
|
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.TypeSubstitutorMarker
|
||||||
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
import org.jetbrains.kotlin.types.model.TypeSystemInferenceExtensionContext
|
||||||
|
|
||||||
class ResultTypeResolver(
|
class ResultTypeResolver(
|
||||||
val typeApproximator: AbstractTypeApproximator,
|
val typeApproximator: AbstractTypeApproximator,
|
||||||
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle
|
val trivialConstraintTypeInferenceOracle: TrivialConstraintTypeInferenceOracle,
|
||||||
|
private val statelessCallbacks: KotlinResolutionStatelessCallbacks? // TODO injection in FIR
|
||||||
) {
|
) {
|
||||||
interface Context : TypeSystemInferenceExtensionContext {
|
interface Context : TypeSystemInferenceExtensionContext {
|
||||||
fun isProperType(type: KotlinTypeMarker): Boolean
|
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 }
|
findResultIfThereIsEqualsConstraint(c, variableWithConstraints)?.let { return it }
|
||||||
|
|
||||||
val subType = c.findSubType(variableWithConstraints)
|
val subType = c.findSubType(variableWithConstraints)
|
||||||
val superType = c.findSuperType(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)
|
c.resultType(subType, superType, variableWithConstraints)
|
||||||
} else {
|
} else {
|
||||||
c.resultType(superType, subType, variableWithConstraints)
|
c.resultType(superType, subType, variableWithConstraints)
|
||||||
}
|
}
|
||||||
|
|
||||||
return result
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.resultType(
|
private fun Context.resultType(
|
||||||
@@ -66,10 +72,10 @@ class ResultTypeResolver(
|
|||||||
|
|
||||||
if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate
|
if (isSuitableType(firstCandidate, variableWithConstraints)) return firstCandidate
|
||||||
|
|
||||||
if (isSuitableType(secondCandidate, variableWithConstraints)) {
|
return if (isSuitableType(secondCandidate, variableWithConstraints)) {
|
||||||
return secondCandidate
|
secondCandidate
|
||||||
} else {
|
} else {
|
||||||
return firstCandidate
|
firstCandidate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,20 +84,21 @@ class ResultTypeResolver(
|
|||||||
if (!isProperType(constraint.type)) continue
|
if (!isProperType(constraint.type)) continue
|
||||||
if (!checkConstraint(this, constraint.type, constraint.kind, resultType)) return false
|
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 (
|
if (
|
||||||
variableWithConstraints.constraints.any {
|
!trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)
|
||||||
it.kind == ConstraintKind.UPPER && it.position.from !is DeclaredUpperBoundConstraintPosition
|
&& isNothingNotSuitableFor(variableWithConstraints.typeVariable)
|
||||||
} && !trivialConstraintTypeInferenceOracle.isSuitableResultedType(resultType)
|
|
||||||
) return false
|
) return false
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun isNothingNotSuitableFor(variable: TypeVariableMarker): Boolean {
|
||||||
|
val parameterName = variable.safeAs<TypeVariableFromCallableDescriptor>()?.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? {
|
private fun Context.findSubType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
||||||
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints)
|
val lowerConstraintTypes = prepareLowerConstraints(variableWithConstraints.constraints)
|
||||||
|
|
||||||
@@ -163,22 +170,27 @@ class ResultTypeResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun Context.findSuperType(variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? {
|
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()) {
|
if (upperConstraints.isNotEmpty()) {
|
||||||
val upperType = intersectTypes(upperConstraints.map { it.type })
|
val upperType = intersectTypes(upperConstraints.map { it.type })
|
||||||
|
|
||||||
return typeApproximator.approximateToSubType(upperType, TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation) ?: upperType
|
return typeApproximator.approximateToSubType(
|
||||||
|
upperType,
|
||||||
|
TypeApproximatorConfiguration.CapturedAndIntegerLiteralsTypesApproximation
|
||||||
|
) ?: upperType
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? = with(c) {
|
private fun findResultIfThereIsEqualsConstraint(c: Context, variableWithConstraints: VariableWithConstraints): KotlinTypeMarker? =
|
||||||
val properEqualityConstraints = variableWithConstraints.constraints.filter {
|
with(c) {
|
||||||
it.kind == ConstraintKind.EQUALITY && c.isProperType(it.type)
|
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...)
|
// Discriminate integer literal types as they are less specific than separate integer types (Int, Short...)
|
||||||
private fun Context.representativeFromEqualityConstraints(constraints: List<Constraint>): KotlinTypeMarker? {
|
private fun Context.representativeFromEqualityConstraints(constraints: List<Constraint>): KotlinTypeMarker? {
|
||||||
|
|||||||
+9
@@ -23,6 +23,15 @@ class TrivialConstraintTypeInferenceOracle private constructor(context: TypeSyst
|
|||||||
return constraint.kind == ConstraintKind.LOWER && constraint.type.typeConstructor().isNothingConstructor()
|
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:
|
// 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
|
// 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
|
// there will be constraint `approximation(out K) <: K` => `Nothing <: K`, which is innocent
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
|
||||||
// See KT-10913 Bogus unreachable code warning
|
// See KT-10913 Bogus unreachable code warning
|
||||||
|
|
||||||
fun fn() : String? = null
|
fun fn() : String? = null
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
|
||||||
// See KT-10913 Bogus unreachable code warning
|
// See KT-10913 Bogus unreachable code warning
|
||||||
|
|
||||||
fun fn() : String? = null
|
fun fn() : String? = null
|
||||||
@@ -8,6 +7,6 @@ fun foo(): String {
|
|||||||
}
|
}
|
||||||
fun bar(): String {
|
fun bar(): String {
|
||||||
val x = fn() ?: return ""
|
val x = fn() ?: return ""
|
||||||
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>y<!> =<!> x<!UNNECESSARY_SAFE_CALL!>?.<!>let { throw Exception() } <!NI;UNREACHABLE_CODE, NI;USELESS_ELVIS, OI;UNREACHABLE_CODE, OI;USELESS_ELVIS!>?: "unreachable"<!>
|
<!UNREACHABLE_CODE!>val <!UNUSED_VARIABLE!>y<!> =<!> x<!UNNECESSARY_SAFE_CALL!>?.<!>let { throw Exception() } <!UNREACHABLE_CODE, USELESS_ELVIS!>?: "unreachable"<!>
|
||||||
<!UNREACHABLE_CODE!>return y<!>
|
<!UNREACHABLE_CODE!>return y<!>
|
||||||
}
|
}
|
||||||
Vendored
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
// !LANGUAGE: +NewInference
|
// !WITH_NEW_INFERENCE
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
// !DIAGNOSTICS: -UNUSED_PARAMETER -UNUSED_VARIABLE
|
||||||
|
|
||||||
fun <K> select2(x: K, y: K): K = TODO()
|
fun <K> select2(x: K, y: K): K = TODO()
|
||||||
|
|||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
|
||||||
|
class Query<out T : Any> 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 <T : Any> forResult(result: T) = Query(result, null, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutableLiveData<T> {
|
||||||
|
var value: Query<Int> = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val liveData = MutableLiveData<Query<Int>>()
|
||||||
|
liveData.value = Query.inProgress // Type mismatch: inferred type is Query<Any> but Query<Int> was expected
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
// !LANGUAGE: +NewInference
|
||||||
|
|
||||||
|
class Query<out T : Any> 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 <T : Any> forResult(result: T) = Query(result, null, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class MutableLiveData<T> {
|
||||||
|
var value: Query<Int> = null!!
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main() {
|
||||||
|
val liveData = MutableLiveData<Query<Int>>()
|
||||||
|
liveData.value = Query.inProgress // Type mismatch: inferred type is Query<Any> but Query<Int> was expected
|
||||||
|
}
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
package
|
||||||
|
|
||||||
|
public fun main(): kotlin.Unit
|
||||||
|
|
||||||
|
public final class MutableLiveData</*0*/ T> {
|
||||||
|
public constructor MutableLiveData</*0*/ T>()
|
||||||
|
public final var value: Query<kotlin.Int>
|
||||||
|
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</*0*/ out T : kotlin.Any> {
|
||||||
|
private constructor Query</*0*/ out T : kotlin.Any>(/*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<kotlin.Nothing>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final fun forError(/*0*/ e: kotlin.Throwable): Query<kotlin.Nothing>
|
||||||
|
public final fun </*0*/ T : kotlin.Any> forResult(/*0*/ result: T): Query<T>
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
// !WITH_NEW_INFERENCE
|
// !WITH_NEW_INFERENCE
|
||||||
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
|
val test: Int = <!NI;TYPE_MISMATCH, NI;TYPE_MISMATCH, NI;TYPE_MISMATCH!>if (true) {
|
||||||
when (2) {
|
when (2) {
|
||||||
1 -> 1
|
1 -> 1
|
||||||
else -> <!OI;NULL_FOR_NONNULL_TYPE!>null<!>
|
else -> <!OI;NULL_FOR_NONNULL_TYPE!>null<!>
|
||||||
|
|||||||
@@ -7,19 +7,19 @@ val test1: (String) -> Boolean =
|
|||||||
|
|
||||||
val test2: (String) -> Boolean =
|
val test2: (String) -> Boolean =
|
||||||
when {
|
when {
|
||||||
true -> <!NI;TYPE_MISMATCH!>{{ true }}<!>
|
true -> {{ true }}
|
||||||
else -> null!!
|
else -> null!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val test3: (String) -> Boolean =
|
val test3: (String) -> Boolean =
|
||||||
when {
|
when {
|
||||||
true -> <!NI;TYPE_MISMATCH!>{ <!UNUSED_ANONYMOUS_PARAMETER!>s<!> -> true }<!>
|
true -> { <!UNUSED_ANONYMOUS_PARAMETER!>s<!> -> true }
|
||||||
else -> null!!
|
else -> null!!
|
||||||
}
|
}
|
||||||
|
|
||||||
val test4: (String) -> Boolean =
|
val test4: (String) -> Boolean =
|
||||||
when {
|
when {
|
||||||
true -> <!NI;TYPE_MISMATCH!>{ <!OI;EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!UNUSED_ANONYMOUS_PARAMETER!>s1<!>, <!OI;CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>s2<!><!> -> true }<!>
|
true -> <!NI;TYPE_MISMATCH!>{ <!EXPECTED_PARAMETERS_NUMBER_MISMATCH!><!UNUSED_ANONYMOUS_PARAMETER!>s1<!>, <!CANNOT_INFER_PARAMETER_TYPE, UNUSED_ANONYMOUS_PARAMETER!>s2<!><!> -> true }<!>
|
||||||
else -> null!!
|
else -> null!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ val <!OI;IMPLICIT_NOTHING_PROPERTY_TYPE!>test1<!> = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val test1a: () -> Boolean = when {
|
val test1a: () -> Boolean = when {
|
||||||
true -> <!NI;TYPE_MISMATCH!>{ { true } }<!>
|
true -> { { true } }
|
||||||
else -> TODO()
|
else -> TODO()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ val <!OI;IMPLICIT_NOTHING_PROPERTY_TYPE!>test3<!> = when {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val test3a: () -> Boolean = when {
|
val test3a: () -> Boolean = when {
|
||||||
true -> <!NI;TYPE_MISMATCH!>{ { true } }<!>
|
true -> { { true } }
|
||||||
true -> <!NI;TYPE_MISMATCH!>{ { true } }<!>
|
true -> { { true } }
|
||||||
else -> TODO()
|
else -> TODO()
|
||||||
}
|
}
|
||||||
@@ -10901,6 +10901,11 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt3174.kt");
|
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")
|
@TestMetadata("kt32250.kt")
|
||||||
public void testKt32250() throws Exception {
|
public void testKt32250() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
||||||
|
|||||||
Generated
+5
@@ -10896,6 +10896,11 @@ public class DiagnosticsUsingJavacTestGenerated extends AbstractDiagnosticsUsing
|
|||||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt3174.kt");
|
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")
|
@TestMetadata("kt32250.kt")
|
||||||
public void testKt32250() throws Exception {
|
public void testKt32250() throws Exception {
|
||||||
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
runTest("compiler/testData/diagnostics/tests/inference/regressions/kt32250.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user