K2: don't make T = Type! substitutions for constructors, including SAM
Without this commit we get some ABI changes and it looks bad. Related to KT-65596
This commit is contained in:
committed by
Space Team
parent
81414d758d
commit
78b6432ced
+54
-1
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.toConeType
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeTypeParameterLookupTag
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.lazyResolveToPhase
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.name.StandardClassIds
|
||||
@@ -82,12 +83,64 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This function provides a type for a newly created EQUALS constraint on a fresh type variable,
|
||||
* for a situation when we have an explicit type argument and type parameter is a Java type parameter without known nullability.
|
||||
*
|
||||
* For a normal function call, like foo<T = SomeType>, we create a constraint T = SomeType!.
|
||||
* This is an unsafe solution, however yet we have to keep it, otherwise a lot of code becomes red.
|
||||
* Typical "strange" example:
|
||||
*
|
||||
* ```
|
||||
* // Java
|
||||
* public class Foo {
|
||||
* static <T> T id(T foo) {
|
||||
* return null;
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // Kotlin
|
||||
* fun test(): String {
|
||||
* return Foo.id<String?>(null) // OK...
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* We keep more sound constraint T = SomeType for regular and SAM constructor calls. Typical examples are:
|
||||
*
|
||||
* ```
|
||||
* fun test1() = J1<Int>() // type should be J1<Int>, not J1<Int!>
|
||||
* // J1.java
|
||||
* public class J1<T1> {}
|
||||
* ```
|
||||
*
|
||||
* or
|
||||
*
|
||||
* ```
|
||||
* // Again, type should be J<String> and not J<String!>
|
||||
* fun test1() = J<String> { x -> x }
|
||||
*
|
||||
*
|
||||
* // FILE: J.java
|
||||
* public interface J<T> {
|
||||
* T foo(T x);
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* @return type which is chosen for EQUALS constraint
|
||||
*/
|
||||
private fun getTypePreservingFlexibilityWrtTypeVariable(
|
||||
type: ConeKotlinType,
|
||||
typeParameter: FirTypeParameterRef,
|
||||
session: FirSession,
|
||||
): ConeKotlinType {
|
||||
return if (typeParameter.shouldBeFlexible(session.typeContext)) {
|
||||
val containingDeclarationSymbol = typeParameter.symbol.containingDeclarationSymbol
|
||||
// To remove constructors (they use class type parameters)
|
||||
return if (
|
||||
containingDeclarationSymbol is FirCallableSymbol &&
|
||||
// To remove SAMs
|
||||
containingDeclarationSymbol !is FirSyntheticFunctionSymbol &&
|
||||
typeParameter.shouldBeFlexible(session.typeContext)
|
||||
) {
|
||||
val notNullType = type.withNullability(ConeNullability.NOT_NULL, session.typeContext) as ConeSimpleKotlinType
|
||||
ConeFlexibleType(notNullType, notNullType.withNullability(ConeNullability.NULLABLE, session.typeContext))
|
||||
} else {
|
||||
|
||||
Reference in New Issue
Block a user