Skip to content

Commit

Permalink
FE: implement specific T & Any vs T! type checker mode for overrides
Browse files Browse the repository at this point in the history
This commit allows type checker to consider T! <: T & Any
during type checks, and uses this mode during various overriding checks

#KT-58933 Fixed
#KT-74049 Fixed
  • Loading branch information
mglukhikh authored and Space Team committed Jan 11, 2025
1 parent 4e5c07e commit bd517e6
Show file tree
Hide file tree
Showing 35 changed files with 577 additions and 49 deletions.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.analysis.checkers.declaration

import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.diagnostics.impl.deduplicating
Expand Down Expand Up @@ -69,7 +70,8 @@ sealed class FirImplementationMismatchChecker(mppKind: MppCheckerKind) : FirClas

val typeCheckerState = context.session.typeContext.newTypeCheckerState(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
stubTypesEqualToAnything = false,
dnnTypesEqualToFlexible = context.languageVersionSettings.supportsFeature(LanguageFeature.AllowDnnTypeOverridingFlexibleType)
)
val classScope = declaration.unsubstitutedScope(context)
val dedupReporter = reporter.deduplicating()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import org.jetbrains.kotlin.KtFakeSourceElementKind
import org.jetbrains.kotlin.KtRealSourceElementKind
import org.jetbrains.kotlin.KtSourceElement
import org.jetbrains.kotlin.builtins.StandardNames
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.DiagnosticReporter
Expand Down Expand Up @@ -122,7 +123,8 @@ sealed class FirOverrideChecker(mppKind: MppCheckerKind) : FirAbstractOverrideCh
override fun check(declaration: FirClass, context: CheckerContext, reporter: DiagnosticReporter) {
val typeCheckerState = context.session.typeContext.newTypeCheckerState(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
stubTypesEqualToAnything = false,
dnnTypesEqualToFlexible = context.languageVersionSettings.supportsFeature(LanguageFeature.AllowDnnTypeOverridingFlexibleType)
)

val firTypeScope = declaration.unsubstitutedScope(context)
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.fir.declarations.FirSimpleFunction
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.scopes.impl.FirTypeIntersectionScopeContext.ResultOfIntersection
import org.jetbrains.kotlin.fir.scopes.impl.buildSubstitutorForOverridesCheck
import org.jetbrains.kotlin.fir.scopes.impl.similarFunctionsOrBothProperties
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
Expand Down Expand Up @@ -120,7 +121,17 @@ class FirOverrideService(val session: FirSession) : FirSessionComponent {

val typeCheckerState = session.typeContext.newTypeCheckerState(
errorTypesEqualToAnything = false,
stubTypesEqualToAnything = false
stubTypesEqualToAnything = false,
/**
* Type checking here influence only selecting of most specific members
* Having foo(param: T & Any) and Java foo(param: T!) and dnnTypesEqualToFlexible = true,
* we can achieve 0 result here, instead of 1/-1 with dnnTypesEqualToFlexible = false.
* The list in [selectMostSpecificMembers] can change size because of this,
* and we can build [ResultOfIntersection.NonTrivial] instead of [ResultOfIntersection.SingleMember].
* But in fact, it does not influence resolve significantly, so it's better to keep behavior
* with dnnTypesEqualToFlexible = false
*/
dnnTypesEqualToFlexible = false
)
val aSubtypesB = AbstractTypeChecker.isSubtypeOf(typeCheckerState, aReturnType, bReturnType)
val bSubtypesA = AbstractTypeChecker.isSubtypeOf(typeCheckerState, bReturnType, aReturnType)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

package org.jetbrains.kotlin.fir.scopes.impl

import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isSuspend
import org.jetbrains.kotlin.fir.declarations.utils.visibility
import org.jetbrains.kotlin.fir.languageVersionSettings
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ensureResolvedTypeDeclaration
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
Expand All @@ -25,7 +27,10 @@ class FirStandardOverrideChecker(private val session: FirSession) : FirAbstractO
private fun isEqualTypes(candidateType: ConeKotlinType, baseType: ConeKotlinType, substitutor: ConeSubstitutor): Boolean {
val substitutedCandidateType = substitutor.substituteOrSelf(candidateType)
val substitutedBaseType = substitutor.substituteOrSelf(baseType)
return AbstractTypeChecker.equalTypes(context, substitutedCandidateType, substitutedBaseType)
return AbstractTypeChecker.equalTypes(
context, substitutedCandidateType, substitutedBaseType,
dnnTypesEqualToFlexible = session.languageVersionSettings.supportsFeature(LanguageFeature.AllowDnnTypeOverridingFlexibleType)
)
}

fun isEqualTypes(candidateTypeRef: FirTypeRef, baseTypeRef: FirTypeRef, substitutor: ConeSubstitutor): Boolean {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -131,10 +131,12 @@ interface ConeInferenceContext : TypeSystemInferenceExtensionContext, ConeTypeCo

override fun newTypeCheckerState(
errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean
stubTypesEqualToAnything: Boolean,
dnnTypesEqualToFlexible: Boolean,
): TypeCheckerState = TypeCheckerState(
errorTypesEqualToAnything,
stubTypesEqualToAnything,
dnnTypesEqualToFlexible,
allowedTypeVariable = true,
typeSystemContext = this,
kotlinTypePreparator = ConeTypePreparator(session),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ fun createIrTypeCheckerState(typeSystemContext: IrTypeSystemContext): TypeChecke
return TypeCheckerState(
isErrorTypeEqualsToAnything = false,
isStubTypeEqualsToAnything = false,
isDnnTypesEqualToFlexible = false,
allowedTypeVariable = false,
typeSystemContext = typeSystemContext,
kotlinTypePreparator = AbstractTypePreparator.Default,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -534,7 +534,8 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon

override fun newTypeCheckerState(
errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean
stubTypesEqualToAnything: Boolean,
dnnTypesEqualToFlexible: Boolean,
): TypeCheckerState = createIrTypeCheckerState(this)

override fun KotlinTypeMarker.isUninferredParameter(): Boolean = false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ abstract class TypeCheckerStateForConstraintSystem(
) : TypeCheckerState(
isErrorTypeEqualsToAnything = true,
isStubTypeEqualsToAnything = true,
isDnnTypesEqualToFlexible = false,
allowedTypeVariable = false,
typeSystemContext = extensionTypeContext,
kotlinTypePreparator,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,11 @@ class ClassicTypeSystemContextForCS(
return isContainedInInvariantOrContravariantPositions
}

override fun newTypeCheckerState(errorTypesEqualToAnything: Boolean, stubTypesEqualToAnything: Boolean): TypeCheckerState {
override fun newTypeCheckerState(
errorTypesEqualToAnything: Boolean,
stubTypesEqualToAnything: Boolean,
dnnTypesEqualToFlexible: Boolean,
): TypeCheckerState {
return createClassicTypeCheckerState(
errorTypesEqualToAnything,
stubTypesEqualToAnything,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
// RUN_PIPELINE_TILL: FRONTEND
// FIR_IDENTICAL
// LATEST_LV_DIFFERENCE
// LANGUAGE: +DefinitelyNonNullableTypes +ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated

// FILE: A.java
Expand Down
Loading

0 comments on commit bd517e6

Please sign in to comment.