Report warnings or errors for violated type parameter's upper bounds from Java annotated with nullability annotations

^KT-43262 Fixed
This commit is contained in:
Victor Petukhov
2021-02-01 16:52:23 +03:00
parent cf4e61bebb
commit befe8599c4
14 changed files with 202 additions and 64 deletions
@@ -0,0 +1,46 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.UpperBoundChecker
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
import org.jetbrains.kotlin.types.*
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
class EnhancedUpperBoundChecker(override val languageVersionSettings: LanguageVersionSettings) : UpperBoundChecker {
override fun checkBound(
bound: KotlinType,
substitutor: TypeSubstitutor,
trace: BindingTrace,
jetTypeArgument: KtTypeReference,
typeArgument: KotlinType
): Boolean {
val isCheckPassed = super.checkBound(bound, substitutor, trace, jetTypeArgument, typeArgument)
// The error is already reported, it's unnecessary to do more checks
if (!isCheckPassed) return false
val enhancedBound = bound.getEnhancement() ?: return false
val isTypeEnhancementImprovementsEnabled =
languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement)
val substitutedBound = substitutor.safeSubstitute(enhancedBound, Variance.INVARIANT)
if (!KotlinTypeChecker.DEFAULT.isSubtypeOf(typeArgument, substitutedBound)) {
if (isTypeEnhancementImprovementsEnabled) {
trace.report(Errors.UPPER_BOUND_VIOLATED.on(jetTypeArgument, substitutedBound, typeArgument))
} else {
trace.report(ErrorsJvm.UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS.on(jetTypeArgument, substitutedBound, typeArgument))
}
return false
}
return true
}
}
@@ -85,6 +85,7 @@ public class DefaultErrorMessagesJvm implements DefaultErrorMessages.Extension {
MAP.put(SUBCLASS_CANT_CALL_COMPANION_PROTECTED_NON_STATIC, "Using non-JVM static members protected in the superclass companion is unsupported yet");
MAP.put(NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS, "Type mismatch: inferred type is {1} but {0} was expected", RENDER_TYPE, RENDER_TYPE);
MAP.put(UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS, "Type argument is not within its bounds: should be subtype of ''{0}''", RENDER_TYPE, RENDER_TYPE);
MAP.put(NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER,
"Type mismatch: value of a nullable type {0} is used where non-nullable type is expected. " +
"This warning will become an error soon. " +
@@ -137,6 +137,9 @@ public interface ErrorsJvm {
DiagnosticFactory2<KtElement, KotlinType, KotlinType> NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS
= DiagnosticFactory2.create(WARNING);
DiagnosticFactory2<KtTypeReference, KotlinType, KotlinType> UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS
= DiagnosticFactory2.create(WARNING);
DiagnosticFactory1<KtElement, KotlinType> NULLABLE_TYPE_PARAMETER_AGAINST_NOT_NULL_TYPE_PARAMETER
= DiagnosticFactory1.create(WARNING);
@@ -97,6 +97,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
) {
override fun configureModuleComponents(container: StorageComponentContainer) {
container.useImpl<JvmStaticChecker>()
container.useImpl<EnhancedUpperBoundChecker>()
container.useImpl<JvmReflectionAPICallChecker>()
container.useImpl<JavaSyntheticScopes>()
container.useImpl<SamConversionResolverImpl>()