[Jspecify] Report warnings on violated bounds of method type parameters

This commit is contained in:
Victor Petukhov
2021-05-12 19:06:57 +03:00
parent 0d6764efc5
commit 937e82db46
4 changed files with 47 additions and 21 deletions
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.UpperBoundChecker
import org.jetbrains.kotlin.resolve.calls.checkers.AdditionalTypeChecker
import org.jetbrains.kotlin.resolve.calls.context.BasicCallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.CallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
@@ -48,9 +49,7 @@ class JavaNullabilityChecker(val upperBoundChecker: UpperBoundChecker) : Additio
expressionTypeWithSmartCast: KotlinType,
c: ResolutionContext<*>
) {
if (expressionType is AbbreviatedType) {
upperBoundChecker.checkBoundsOfExpandedTypeAlias(expressionType.expandedType, expression, c.trace)
}
checkTypeParameterBounds(expression, expressionType, c)
val dataFlowValue by lazy(LazyThreadSafetyMode.NONE) {
c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
@@ -122,6 +121,29 @@ class JavaNullabilityChecker(val upperBoundChecker: UpperBoundChecker) : Additio
}
}
private fun checkTypeParameterBounds(
expression: KtExpression,
expressionType: KotlinType,
c: ResolutionContext<*>
) {
if (expressionType is AbbreviatedType) {
upperBoundChecker.checkBoundsOfExpandedTypeAlias(expressionType.expandedType, expression, c.trace)
}
if (c !is BasicCallResolutionContext || upperBoundChecker !is WarningAwareUpperBoundChecker) return
val resolvedCall = c.trace.bindingContext[BindingContext.RESOLVED_CALL, c.call] ?: return
for ((typeParameter, typeArgument) in resolvedCall.typeArguments) {
// continue if we don't have explicit type arguments
val typeReference = c.call.typeArguments.getOrNull(typeParameter.index)?.typeReference ?: continue
upperBoundChecker.checkBounds(
typeReference, typeArgument, typeParameter, TypeSubstitutor.create(typeArgument), c.trace, withOnlyCheckForWarning = true
)
}
}
private fun isWrongTypeParameterNullabilityForSubtyping(
expressionType: KotlinType,
c: ResolutionContext<*>,
@@ -49,7 +49,7 @@ class WarningAwareUpperBoundChecker : UpperBoundChecker() {
typeParameterDescriptor: TypeParameterDescriptor,
substitutor: TypeSubstitutor,
trace: BindingTrace,
typeAliasUsageElement: KtElement?,
typeAliasUsageElement: KtElement? = null,
withOnlyCheckForWarning: Boolean = false
) {
if (typeParameterDescriptor.upperBounds.isEmpty()) return
@@ -71,8 +71,12 @@ class WarningAwareUpperBoundChecker : UpperBoundChecker() {
}
val enhancedBound = bound.getEnhancementDeeply() ?: continue
val argumentTypeEnhancement = argumentType.getEnhancementDeeply() ?: argumentType
checkBound(enhancedBound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporterForWarnings)
checkBound(
enhancedBound, argumentTypeEnhancement, argumentReference,
substitutor, typeAliasUsageElement, diagnosticsReporterForWarnings
)
}
}
}