Add reporting of the warnings based on Java annotations for expanded type aliases

Before that, such warnings weren't reported as the corresponding errors were reported during type inference (only original types took part there)
This commit is contained in:
Victor Petukhov
2021-02-04 11:42:52 +03:00
parent d783d99443
commit 0d40022d6d
22 changed files with 186 additions and 114 deletions
@@ -29,6 +29,10 @@ inline fun <reified T : Any> StorageComponentContainer.useImpl() {
registerSingleton(T::class.java)
}
inline fun <reified T : Any> StorageComponentContainer.useImplIf(cond: Boolean) {
if (cond) useImpl<T>()
}
inline fun <reified T : Any> ComponentProvider.get(): T {
return getService(T::class.java)
}
@@ -5,10 +5,11 @@
package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
interface PlatformConfigurator {
val platformSpecificContainer: StorageComponentContainer
fun configureModuleComponents(container: StorageComponentContainer)
fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings)
fun configureModuleDependentCheckers(container: StorageComponentContainer)
}
@@ -21,11 +21,9 @@ import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtPostfixExpression
import org.jetbrains.kotlin.psi.KtWhenExpression
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.CallResolutionContext
import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext
@@ -43,14 +41,17 @@ import org.jetbrains.kotlin.types.model.KotlinTypeMarker
import org.jetbrains.kotlin.types.typeUtil.contains
import org.jetbrains.kotlin.types.typeUtil.makeNotNullable
class JavaNullabilityChecker : AdditionalTypeChecker {
class JavaNullabilityChecker(val upperBoundChecker: UpperBoundChecker) : AdditionalTypeChecker {
override fun checkType(
expression: KtExpression,
expressionType: KotlinType,
expressionTypeWithSmartCast: KotlinType,
c: ResolutionContext<*>
) {
if (expressionType is AbbreviatedType) {
upperBoundChecker.checkBoundsOfExpandedTypeAlias(expressionType.expandedType, expression, c.trace)
}
val dataFlowValue by lazy(LazyThreadSafetyMode.NONE) {
c.dataFlowValueFactory.createDataFlowValue(expression, expressionType, c)
}
@@ -5,10 +5,9 @@
package org.jetbrains.kotlin.resolve.jvm.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.resolve.BindingTrace
import org.jetbrains.kotlin.resolve.UpperBoundChecker
@@ -18,8 +17,17 @@ import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm.UPPER_BOUND_VIOLAT
import org.jetbrains.kotlin.types.*
// TODO: remove this checker after removing support LV < 1.6
class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings) : UpperBoundChecker(languageVersionSettings) {
val isTypeEnhancementImprovementsEnabled = languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement)
class WarningAwareUpperBoundChecker : UpperBoundChecker() {
override fun checkBoundsOfExpandedTypeAlias(type: KotlinType, expression: KtExpression, trace: BindingTrace) {
val typeParameters = type.constructor.parameters
for ((index, arg) in type.arguments.withIndex()) {
checkBounds(
null, arg.type, typeParameters[index], TypeSubstitutor.create(type), trace, expression,
withOnlyCheckForWarning = true
)
}
}
override fun checkBounds(
argumentReference: KtTypeReference?,
@@ -28,6 +36,21 @@ class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings
substitutor: TypeSubstitutor,
trace: BindingTrace,
typeAliasUsageElement: KtElement?
) {
checkBounds(
argumentReference, argumentType, typeParameterDescriptor, substitutor, trace, typeAliasUsageElement,
withOnlyCheckForWarning = false
)
}
fun checkBounds(
argumentReference: KtTypeReference?,
argumentType: KotlinType,
typeParameterDescriptor: TypeParameterDescriptor,
substitutor: TypeSubstitutor,
trace: BindingTrace,
typeAliasUsageElement: KtElement?,
withOnlyCheckForWarning: Boolean = false
) {
if (typeParameterDescriptor.upperBounds.isEmpty()) return
@@ -39,13 +62,13 @@ class EnhancedUpperBoundChecker(languageVersionSettings: LanguageVersionSettings
)
for (bound in typeParameterDescriptor.upperBounds) {
val isCheckPassed = checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter)
if (!withOnlyCheckForWarning) {
val isBaseCheckPassed =
checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter)
// The error is already reported, it's unnecessary to do more checks
if (!isCheckPassed) continue
// If improvements are enabled, then type parameter's upper bounds will already enhanced, and the error will reported inside the first check
if (isTypeEnhancementImprovementsEnabled) continue
// The error is already reported, it's unnecessary to do more checks
if (!isBaseCheckPassed) continue
}
val enhancedBound = bound.getEnhancementDeeply() ?: continue
@@ -6,10 +6,9 @@
package org.jetbrains.kotlin.resolve.jvm.platform
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMapper
import org.jetbrains.kotlin.container.PlatformExtensionsClashResolver
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.*
import org.jetbrains.kotlin.load.java.sam.JvmSamConversionOracle
import org.jetbrains.kotlin.resolve.PlatformConfiguratorBase
import org.jetbrains.kotlin.resolve.checkers.BigFunctionTypeAvailabilityChecker
@@ -61,7 +60,6 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
),
additionalTypeCheckers = listOf(
JavaNullabilityChecker(),
RuntimeAssertionsTypeChecker,
JavaGenericVarianceViolationTypeChecker,
JavaTypeAccessibilityChecker(),
@@ -95,9 +93,13 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
declarationReturnTypeSanitizer = JvmDeclarationReturnTypeSanitizer
) {
override fun configureModuleComponents(container: StorageComponentContainer) {
override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {
container.useImplIf<WarningAwareUpperBoundChecker>(
!languageVersionSettings.supportsFeature(LanguageFeature.ImprovementsAroundTypeEnhancement)
)
container.useImpl<JavaNullabilityChecker>()
container.useImpl<JvmStaticChecker>()
container.useImpl<EnhancedUpperBoundChecker>()
container.useImpl<JvmReflectionAPICallChecker>()
container.useImpl<JavaSyntheticScopes>()
container.useImpl<SamConversionResolverImpl>()
@@ -112,6 +114,7 @@ object JvmPlatformConfigurator : PlatformConfiguratorBase(
container.useImpl<JvmSamConversionOracle>()
container.useImpl<JvmAdditionalClassPartsProvider>()
container.useImpl<JvmRecordApplicabilityChecker>()
container.useInstance(FunctionWithBigAritySupport.LanguageVersionDependent)
container.useInstance(GenericArrayClassLiteralSupport.Enabled)
container.useInstance(JavaActualAnnotationArgumentExtractor())
@@ -6,12 +6,13 @@
package org.jetbrains.kotlin.analyzer.common
import org.jetbrains.kotlin.analyzer.ModuleInfo
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.resolve.*
import org.jetbrains.kotlin.storage.StorageManager
private object CommonPlatformConfigurator : PlatformConfiguratorBase() {
override fun configureModuleComponents(container: StorageComponentContainer) {}
override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {}
}
object CommonPlatformAnalyzerServices : PlatformDependentAnalyzerServices() {
@@ -73,7 +73,7 @@ fun StorageComponentContainer.configureModule(
useInstance(nonTrivialPlatformVersion ?: TargetPlatformVersion.NoVersion)
analyzerServices.platformConfigurator.configureModuleComponents(this)
analyzerServices.platformConfigurator.configureModuleComponents(this, languageVersionSettings)
analyzerServices.platformConfigurator.configureModuleDependentCheckers(this)
for (extension in StorageComponentContainerContributor.getInstances(moduleContext.project)) {
@@ -5,7 +5,6 @@
package org.jetbrains.kotlin.resolve
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.DefaultImplementation
import org.jetbrains.kotlin.descriptors.ClassifierDescriptor
import org.jetbrains.kotlin.descriptors.TypeParameterDescriptor
@@ -13,7 +12,9 @@ import org.jetbrains.kotlin.diagnostics.DiagnosticFactory2
import org.jetbrains.kotlin.diagnostics.DiagnosticFactory3
import org.jetbrains.kotlin.diagnostics.Errors.UPPER_BOUND_VIOLATED
import org.jetbrains.kotlin.diagnostics.Errors.UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION
import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtTypeReference
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
import org.jetbrains.kotlin.types.*
@@ -21,7 +22,28 @@ import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
import org.jetbrains.kotlin.types.typeUtil.containsTypeAliasParameters
@DefaultImplementation(impl = UpperBoundChecker::class)
open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSettings) {
open class UpperBoundChecker {
open fun checkBoundsOfExpandedTypeAlias(type: KotlinType, expression: KtExpression, trace: BindingTrace) {
// do nothing in the strict mode as the errors are already reported in the type inference if necessary
}
open fun checkBounds(
argumentReference: KtTypeReference?,
argumentType: KotlinType,
typeParameterDescriptor: TypeParameterDescriptor,
substitutor: TypeSubstitutor,
trace: BindingTrace,
typeAliasUsageElement: KtElement? = null,
) {
if (typeParameterDescriptor.upperBounds.isEmpty()) return
val diagnosticsReporter = UpperBoundViolatedReporter(trace, argumentType, typeParameterDescriptor)
for (bound in typeParameterDescriptor.upperBounds) {
checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter)
}
}
fun checkBounds(typeReference: KtTypeReference, type: KotlinType, trace: BindingTrace) {
if (type.isError) return
@@ -58,23 +80,6 @@ open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSetting
}
}
open fun checkBounds(
argumentReference: KtTypeReference?,
argumentType: KotlinType,
typeParameterDescriptor: TypeParameterDescriptor,
substitutor: TypeSubstitutor,
trace: BindingTrace,
typeAliasUsageElement: KtElement? = null,
) {
if (typeParameterDescriptor.upperBounds.isEmpty()) return
val diagnosticsReporter = UpperBoundViolatedReporter(trace, argumentType, typeParameterDescriptor)
for (bound in typeParameterDescriptor.upperBounds) {
checkBound(bound, argumentType, argumentReference, substitutor, typeAliasUsageElement, diagnosticsReporter)
}
}
protected fun checkBound(
bound: KotlinType,
argumentType: KotlinType,
@@ -99,18 +104,17 @@ open class UpperBoundChecker(val languageVersionSettings: LanguageVersionSetting
}
class UpperBoundViolatedReporter(
val trace: BindingTrace,
val argumentType: KotlinType,
val typeParameterDescriptor: TypeParameterDescriptor? = null,
val baseDiagnostic: DiagnosticFactory2<KtTypeReference, KotlinType, KotlinType> = UPPER_BOUND_VIOLATED,
val diagnosticForTypeAliases: DiagnosticFactory3<KtElement, KotlinType, KotlinType, ClassifierDescriptor> = UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION
private val trace: BindingTrace,
private val argumentType: KotlinType,
private val typeParameterDescriptor: TypeParameterDescriptor,
private val baseDiagnostic: DiagnosticFactory2<KtTypeReference, KotlinType, KotlinType> = UPPER_BOUND_VIOLATED,
private val diagnosticForTypeAliases: DiagnosticFactory3<KtElement, KotlinType, KotlinType, ClassifierDescriptor> = UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION
) {
fun report(typeArgumentReference: KtTypeReference, substitutedBound: KotlinType) {
trace.report(baseDiagnostic.on(typeArgumentReference, substitutedBound, argumentType))
trace.reportDiagnosticOnce(baseDiagnostic.on(typeArgumentReference, substitutedBound, argumentType))
}
fun reportForTypeAliasExpansion(callElement: KtElement, substitutedBound: KotlinType) {
if (typeParameterDescriptor == null) return
trace.report(diagnosticForTypeAliases.on(callElement, substitutedBound, argumentType, typeParameterDescriptor))
trace.reportDiagnosticOnce(diagnosticForTypeAliases.on(callElement, substitutedBound, argumentType, typeParameterDescriptor))
}
}
@@ -15,8 +15,6 @@ import org.jetbrains.kotlin.diagnostics.reportDiagnosticOnce
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isNull
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.UpperBoundChecker
import org.jetbrains.kotlin.resolve.UpperBoundViolatedReporter
import org.jetbrains.kotlin.resolve.calls.callUtil.getCalleeExpressionIfAny
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.reportTrailingLambdaErrorOr
@@ -395,8 +393,8 @@ class DiagnosticReporterByTrackingStrategy(
}
(position as? ExplicitTypeParameterConstraintPositionImpl)?.let {
UpperBoundViolatedReporter(trace, error.upperKotlinType)
.report((it.typeArgument as SimpleTypeArgumentImpl).typeReference, error.lowerKotlinType)
val typeArgumentReference = (it.typeArgument as SimpleTypeArgumentImpl).typeReference
trace.report(UPPER_BOUND_VIOLATED.on(typeArgumentReference, error.upperKotlinType, error.lowerKotlinType))
}
(position as? FixVariableConstraintPositionImpl)?.let {
@@ -13,6 +13,6 @@ class TColl<T, C : Collection<T>>
typealias TC<T, C> = TColl<T, C>
typealias TC2<T, C> = TC<T, C>
val y1 = TColl<Any, <!UPPER_BOUND_VIOLATED{NI}, UPPER_BOUND_VIOLATED!>Any<!>>()
val y2 = TC<Any, <!UPPER_BOUND_VIOLATED{NI}, UPPER_BOUND_VIOLATED!>Any<!>>()
val y3 = TC2<Any, <!UPPER_BOUND_VIOLATED{NI}, UPPER_BOUND_VIOLATED!>Any<!>>()
val y1 = TColl<Any, <!UPPER_BOUND_VIOLATED, UPPER_BOUND_VIOLATED!>Any<!>>()
val y2 = TC<Any, <!UPPER_BOUND_VIOLATED, UPPER_BOUND_VIOLATED!>Any<!>>()
val y3 = TC2<Any, <!UPPER_BOUND_VIOLATED, UPPER_BOUND_VIOLATED!>Any<!>>()
@@ -1,8 +1,18 @@
// !WITH_NEW_INFERENCE
// NI_EXPECTED_FILE
// FULL_JDK
// FILE: MapLike.java
import java.util.Map;
public class MapLike<@org.jetbrains.annotations.NotNull K> {
MapLike(K x) { }
}
// FILE: main.kt
class Cons<T : Number>(val head: T, val tail: Cons<T>?)
typealias C<T> = Cons<T>
typealias C2<T> = MapLike<T>
val test1 = C(1, C(2, null))
val test2 = C(1, C("", null))
val test23 = C2(if (true) 1 else null)
val test234 = C2(C2(if (true) 1 else null))
@@ -1,8 +1,18 @@
// !WITH_NEW_INFERENCE
// NI_EXPECTED_FILE
// FULL_JDK
// FILE: MapLike.java
import java.util.Map;
public class MapLike<@org.jetbrains.annotations.NotNull K> {
MapLike(K x) { }
}
// FILE: main.kt
class Cons<T : Number>(val head: T, val tail: Cons<T>?)
typealias C<T> = Cons<T>
typealias C2<T> = MapLike<T>
val test1 = C(1, C(2, null))
val test2 = C(1, <!TYPE_MISMATCH{NI}, TYPE_MISMATCH{NI}, TYPE_MISMATCH{NI}!><!TYPE_INFERENCE_CONFLICTING_SUBSTITUTIONS{OI}!>C<!>(<!TYPE_MISMATCH{NI}, TYPE_MISMATCH{NI}!>""<!>, null)<!>)
val test2 = C(1, <!TYPE_MISMATCH, TYPE_MISMATCH, TYPE_MISMATCH!>C(<!TYPE_MISMATCH, TYPE_MISMATCH!>""<!>, null)<!>)
val test23 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>C2(if (true) 1 else null)<!>
val test234 = C2(<!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>C2(if (true) 1 else null)<!>)
@@ -1,14 +0,0 @@
package
public val test1: C<kotlin.Int> /* = Cons<kotlin.Int> */
public val test2: Cons<out kotlin.Any?>
public final class Cons</*0*/ T : kotlin.Number> {
public constructor Cons</*0*/ T : kotlin.Number>(/*0*/ head: T, /*1*/ tail: Cons<T>?)
public final val head: T
public final val tail: Cons<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 typealias C</*0*/ T> = Cons<T>
@@ -1,7 +1,9 @@
package
public val test1: C<kotlin.Int> /* = Cons<kotlin.Int> */
public val test2: C<kotlin.Int> /* = Cons<kotlin.Int> */
public val test2: Cons<out kotlin.Any?>
public val test23: C2<kotlin.Int?> /* = MapLike<kotlin.Int?> */
public val test234: C2<(C2<kotlin.Int?> /* = MapLike<kotlin.Int?> */..C2<kotlin.Int?>? /* = MapLike<kotlin.Int?>? */)> /* = MapLike<(C2<kotlin.Int?> /* = MapLike<kotlin.Int?> */..C2<kotlin.Int?>? /* = MapLike<kotlin.Int?>? */)> */
public final class Cons</*0*/ T : kotlin.Number> {
public constructor Cons</*0*/ T : kotlin.Number>(/*0*/ head: T, /*1*/ tail: Cons<T>?)
@@ -11,4 +13,13 @@ public final class Cons</*0*/ T : kotlin.Number> {
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public open class MapLike</*0*/ @org.jetbrains.annotations.NotNull K : kotlin.Any!> {
public/*package*/ constructor MapLike</*0*/ @org.jetbrains.annotations.NotNull K : kotlin.Any!>(/*0*/ x: K!)
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 typealias C</*0*/ T> = Cons<T>
public typealias C2</*0*/ T> = MapLike<T>
@@ -14,11 +14,11 @@ import java.util.Collection;
public class ListLike<K extends Collection<@org.jetbrains.annotations.NotNull Object>> {}
// FILE: main.kt
fun test0(map : MapLike<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Int?<!>, Int>) {}
fun <K> test11(map : MapLike<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>K<!>, K>) {}
fun <K> test12(map : MapLike<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>K?<!>, K>) {}
fun test0(map : MapLike<Int?, Int>) {}
fun <K> test11(map : MapLike<K, K>) {}
fun <K> test12(map : MapLike<K?, K>) {}
fun <K : Any> test13(map : MapLike<K, K>) {}
fun <K : Any> test14(map : MapLike<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>K?<!>, K>) {}
fun <K : Any> test14(map : MapLike<K?, K>) {}
class Foo<K>
@@ -26,11 +26,11 @@ typealias A<A> = MapLike<A, Int>
typealias A2<B> = Foo<MapLike<B, Int>>
typealias A3<C> = ListLike<List<C>>
fun main1(x: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Int?<!>>) {}
fun main2(x: A2<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Int?<!>>) {}
fun main3(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?><!>) {}
fun main1(x: A<Int?>) {}
fun main2(x: A2<Int?>) {}
fun main3(x: A3<Int?>) {}
fun main3() {
val x = A3<Int?>() // TODO: support reporting errors on typealias constructor calls
val x2 = A<Int?>() // TODO: support reporting errors on typealias constructor calls
val y: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?><!> = A3<Int?>()
val y: A3<Int?> = A3<Int?>()
}
@@ -30,7 +30,7 @@ fun main1(x: A<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Int?<!>>) {}
fun main2(x: A2<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>Int?<!>>) {}
fun main3(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?><!>) {}
fun main3() {
val x = A3<Int?>() // TODO: support reporting errors on typealias constructor calls
val x2 = A<Int?>() // TODO: support reporting errors on typealias constructor calls
val y: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?><!> = A3<Int?>()
val x = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?>()<!> // TODO: support reporting errors on typealias constructor calls
val x2 = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A<Int?>()<!> // TODO: support reporting errors on typealias constructor calls
val y: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?><!> = <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION_BASED_ON_JAVA_ANNOTATIONS!>A3<Int?>()<!>
}
@@ -15,11 +15,11 @@ import java.util.Collection;
public class ListLike<K extends Collection<@org.jetbrains.annotations.NotNull Object>> {}
// FILE: main.kt
fun test0(map : MapLike<<!UPPER_BOUND_VIOLATED!>Int?<!>, Int>) {}
fun <K> test11(map : MapLike<<!UPPER_BOUND_VIOLATED!>K<!>, K>) {}
fun <K> test12(map : MapLike<<!UPPER_BOUND_VIOLATED!>K?<!>, K>) {}
fun test0(map : MapLike<Int?, Int>) {}
fun <K> test11(map : MapLike<K, K>) {}
fun <K> test12(map : MapLike<K?, K>) {}
fun <K : Any> test13(map : MapLike<K, K>) {}
fun <K : Any> test14(map : MapLike<<!UPPER_BOUND_VIOLATED!>K?<!>, K>) {}
fun <K : Any> test14(map : MapLike<K?, K>) {}
class Foo<K>
@@ -27,11 +27,11 @@ typealias A<A> = MapLike<A, Int>
typealias A2<B> = Foo<MapLike<B, Int>>
typealias A3<C> = ListLike<List<C>>
fun main1(x: A<<!UPPER_BOUND_VIOLATED!>Int?<!>>) {}
fun main2(x: A2<<!UPPER_BOUND_VIOLATED!>Int?<!>>) {}
fun main3(x: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>A3<Int?><!>) {}
fun main1(x: A<Int?>) {}
fun main2(x: A2<Int?>) {}
fun main3(x: A3<Int?>) {}
fun main3() {
val x = A3<Int?>() // TODO: support reporting errors on typealias constructor calls
val x2 = A<Int?>()
val y: <!UPPER_BOUND_VIOLATED_IN_TYPEALIAS_EXPANSION!>A3<Int?><!> = A3<Int?>()
val y: A3<Int?> = A3<Int?>()
}
@@ -3,13 +3,13 @@
// SKIP_TXT
// TODO: report warnings "UPPER_BOUND_VIOLATED"
fun main(x: ClassTypeParameterBoundWithWarnings<String?>, y: ClassTypeParameterBoundWithWarnings<String>, a: String?, b: String) {
fun main(x: ClassTypeParameterBoundWithWarnings<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>String?<!>>, y: ClassTypeParameterBoundWithWarnings<String>, a: String?, b: String) {
val x2 = ClassTypeParameterBoundWithWarnings<String?>()
val y2 = ClassTypeParameterBoundWithWarnings<String>()
val x3 = ClassTypeParameterBoundWithWarnings(a)
val y3 = ClassTypeParameterBoundWithWarnings(b)
val x4: ClassTypeParameterBoundWithWarnings<String?> = ClassTypeParameterBoundWithWarnings()
val x4: ClassTypeParameterBoundWithWarnings<<!UPPER_BOUND_VIOLATED_BASED_ON_JAVA_ANNOTATIONS!>String?<!>> = ClassTypeParameterBoundWithWarnings()
val y4: ClassTypeParameterBoundWithWarnings<String> = ClassTypeParameterBoundWithWarnings()
}
@@ -88,7 +88,7 @@ fun KotlinType.getEnhancement(): KotlinType? = when (this) {
else -> null
}
private fun List<TypeProjection>.enhanceTypeArguments(depth: Int) =
private fun List<TypeProjection>.enhanceTypeArguments() =
map { argument ->
// TODO: think about star projections with enhancement (e.g. came from Java: Foo<@NotNull ?>)
if (argument.isStarProjection) {
@@ -96,15 +96,34 @@ private fun List<TypeProjection>.enhanceTypeArguments(depth: Int) =
}
val argumentType = argument.type
val enhancedArgumentType = if (argumentType is TypeWithEnhancement) argumentType.enhancement else argumentType
val enhancedDeeplyArgumentType = enhancedArgumentType.getEnhancementDeeply(depth + 1)
val enhancedDeeplyArgumentType = enhancedArgumentType.getEnhancementDeeplyInternal()
if (argumentType === enhancedDeeplyArgumentType) return@map argument
argument.replaceType(enhancedDeeplyArgumentType)
}
private fun KotlinType.getEnhancementDeeply(depth: Int): KotlinType {
val newArguments = arguments.enhanceTypeArguments(depth)
val newArgumentsForUpperBound = if (this is FlexibleType) upperBound.arguments.enhanceTypeArguments(depth) else newArguments
private fun List<TypeProjection>.wereTypeArgumentsChanged(newArguments: List<TypeProjection>) =
newArguments.size != this.size || !this.withIndex().all { (i, arg) -> newArguments[i] === arg }
private fun KotlinType.wereTypeArgumentsChanged(newArguments: List<TypeProjection>, newArgumentsForUpperBound: List<TypeProjection>) =
when (val type = unwrap()) {
is FlexibleType -> {
type.lowerBound.arguments.wereTypeArgumentsChanged(newArguments) ||
type.upperBound.arguments.wereTypeArgumentsChanged(newArgumentsForUpperBound)
}
else -> {
type.arguments.wereTypeArgumentsChanged(newArguments)
}
}
private fun KotlinType.getEnhancementDeeplyInternal(): KotlinType {
val newArguments = arguments.enhanceTypeArguments()
val newArgumentsForUpperBound = if (this is FlexibleType) upperBound.arguments.enhanceTypeArguments() else newArguments
val enhancedType = if (this is TypeWithEnhancement) enhancement else this
val areArgumentsChanged = enhancedType.wereTypeArgumentsChanged(newArguments, newArgumentsForUpperBound)
if (!areArgumentsChanged) return enhancedType
return enhancedType.replace(
newArguments = newArguments,
@@ -113,7 +132,7 @@ private fun KotlinType.getEnhancementDeeply(depth: Int): KotlinType {
}
fun KotlinType.getEnhancementDeeply(): KotlinType? {
val enhancedTypeWithArguments = getEnhancementDeeply(depth = 0)
val enhancedTypeWithArguments = getEnhancementDeeplyInternal()
if (enhancedTypeWithArguments === this) return null
@@ -224,7 +224,7 @@ class CompositeResolverForModuleFactory(
}
class CompositeAnalyzerServices(val services: List<PlatformDependentAnalyzerServices>) : PlatformDependentAnalyzerServices() {
override val platformConfigurator: PlatformConfigurator = CompositePlatformConigurator(services.map { it.platformConfigurator })
override val platformConfigurator: PlatformConfigurator = CompositePlatformConfigurator(services.map { it.platformConfigurator })
override fun computePlatformSpecificDefaultImports(storageManager: StorageManager, result: MutableList<ImportPath>) {
val intersectionOfDefaultImports = services.map { service ->
@@ -247,7 +247,7 @@ class CompositeAnalyzerServices(val services: List<PlatformDependentAnalyzerServ
if (isEmpty()) emptyList() else reduce { first, second -> first.intersect(second) }.toList()
}
class CompositePlatformConigurator(private val componentConfigurators: List<PlatformConfigurator>) : PlatformConfigurator {
class CompositePlatformConfigurator(private val componentConfigurators: List<PlatformConfigurator>) : PlatformConfigurator {
override val platformSpecificContainer: StorageComponentContainer
get() = composeContainer(this::class.java.simpleName) {
configureDefaultCheckers()
@@ -256,8 +256,8 @@ class CompositePlatformConigurator(private val componentConfigurators: List<Plat
}
}
override fun configureModuleComponents(container: StorageComponentContainer) {
componentConfigurators.forEach { it.configureModuleComponents(container) }
override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {
componentConfigurators.forEach { it.configureModuleComponents(container, languageVersionSettings) }
}
override fun configureModuleDependentCheckers(container: StorageComponentContainer) {
@@ -266,6 +266,5 @@ class CompositePlatformConigurator(private val componentConfigurators: List<Plat
// Unfortunately, it is declared in base class, so repeating call to 'configureModuleDependentCheckers' will lead
// to multiple registrrations.
container.useImpl<ExperimentalMarkerDeclarationAnnotationChecker>()
container.useImpl<UpperBoundChecker>()
}
}
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.js.resolve
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
@@ -34,7 +35,7 @@ object JsPlatformConfigurator : PlatformConfiguratorBase(
),
identifierChecker = JsIdentifierChecker
) {
override fun configureModuleComponents(container: StorageComponentContainer) {
override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {
container.useInstance(NameSuggestion())
container.useImpl<JsCallChecker>()
container.useImpl<JsTypeSpecificityComparator>()
@@ -5,6 +5,7 @@
package org.jetbrains.kotlin.resolve.konan.platform
import org.jetbrains.kotlin.config.LanguageVersionSettings
import org.jetbrains.kotlin.container.StorageComponentContainer
import org.jetbrains.kotlin.container.useImpl
import org.jetbrains.kotlin.container.useInstance
@@ -30,7 +31,7 @@ object NativePlatformConfigurator : PlatformConfiguratorBase(
NativeTopLevelSingletonChecker, NativeThreadLocalChecker
)
) {
override fun configureModuleComponents(container: StorageComponentContainer) {
override fun configureModuleComponents(container: StorageComponentContainer, languageVersionSettings: LanguageVersionSettings) {
container.useInstance(NativeInliningRule)
}