Use upper bound aware type approximator for intersection types inside sam types in contravariant positions to build proper types in terms of subtyping
This commit is contained in:
committed by
TeamCityServer
parent
6a78e0a10c
commit
4aeabb6b0f
@@ -6,14 +6,17 @@
|
|||||||
package org.jetbrains.kotlin.backend.common
|
package org.jetbrains.kotlin.backend.common
|
||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
|
||||||
import org.jetbrains.kotlin.resolve.sam.getAbstractMembers
|
import org.jetbrains.kotlin.resolve.sam.getAbstractMembers
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
|
import org.jetbrains.kotlin.types.checker.intersectWrappedTypes
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.builtIns
|
||||||
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing
|
import org.jetbrains.kotlin.types.typeUtil.replaceArgumentsWithNothing
|
||||||
|
|
||||||
class SamType constructor(val type: KotlinType) {
|
class SamType constructor(val type: KotlinType, val hasUnapproximatableArguments: Boolean = false) {
|
||||||
|
|
||||||
val classDescriptor: ClassDescriptor
|
val classDescriptor: ClassDescriptor
|
||||||
get() = type.constructor.declarationDescriptor as? ClassDescriptor ?: error("Sam/Fun interface not a class descriptor: $type")
|
get() = type.constructor.declarationDescriptor as? ClassDescriptor ?: error("Sam/Fun interface not a class descriptor: $type")
|
||||||
@@ -38,7 +41,9 @@ class SamType constructor(val type: KotlinType) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
open class SamTypeFactory {
|
open class SamTypeFactory {
|
||||||
fun createByValueParameter(valueParameter: ValueParameterDescriptor): SamType? {
|
private lateinit var typeApproximator: TypeApproximator
|
||||||
|
|
||||||
|
fun createByValueParameter(valueParameter: ValueParameterDescriptor, languageVersionSettings: LanguageVersionSettings): SamType? {
|
||||||
val singleArgumentType: KotlinType
|
val singleArgumentType: KotlinType
|
||||||
val originalSingleArgumentType: KotlinType?
|
val originalSingleArgumentType: KotlinType?
|
||||||
val varargElementType = valueParameter.varargElementType
|
val varargElementType = valueParameter.varargElementType
|
||||||
@@ -56,6 +61,11 @@ open class SamTypeFactory {
|
|||||||
if (singleArgumentType.isError || originalSingleArgumentType!!.isError) {
|
if (singleArgumentType.isError || originalSingleArgumentType!!.isError) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!::typeApproximator.isInitialized) {
|
||||||
|
typeApproximator = TypeApproximator(singleArgumentType.builtIns, languageVersionSettings)
|
||||||
|
}
|
||||||
|
|
||||||
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
|
// This can be true in case when the value parameter is in the method of a generic type with out-projection.
|
||||||
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
|
// We approximate Inv<Captured#1> to Nothing, while Inv itself can be a SAM interface safe to call here
|
||||||
// (see testData genericSamProjectedOut.kt for details)
|
// (see testData genericSamProjectedOut.kt for details)
|
||||||
@@ -63,20 +73,41 @@ open class SamTypeFactory {
|
|||||||
// so we use Nothing arguments instead that leads to a raw type used for a SAM wrapper.
|
// so we use Nothing arguments instead that leads to a raw type used for a SAM wrapper.
|
||||||
// See org.jetbrains.kotlin.codegen.state.KotlinTypeMapper#writeGenericType to understand how
|
// See org.jetbrains.kotlin.codegen.state.KotlinTypeMapper#writeGenericType to understand how
|
||||||
// raw types and Nothing arguments relate.
|
// raw types and Nothing arguments relate.
|
||||||
val originalTypeToUse =
|
val originalTypeToUse = if (KotlinBuiltIns.isNothing(singleArgumentType))
|
||||||
if (KotlinBuiltIns.isNothing(singleArgumentType))
|
originalSingleArgumentType.replaceArgumentsWithNothing()
|
||||||
originalSingleArgumentType.replaceArgumentsWithNothing()
|
else singleArgumentType
|
||||||
else singleArgumentType
|
val approximatedOriginalTypeToUse = typeApproximator.approximateToSubType(
|
||||||
return create(originalTypeToUse.removeExternalProjections())
|
originalTypeToUse,
|
||||||
|
TypeApproximatorConfiguration.UpperBoundAwareIntersectionTypeApproximator
|
||||||
|
) ?: originalTypeToUse
|
||||||
|
approximatedOriginalTypeToUse as KotlinType
|
||||||
|
val hasUnapproximatableArguments = hasUnapproximatableArguments(approximatedOriginalTypeToUse)
|
||||||
|
|
||||||
|
return create((approximatedOriginalTypeToUse).removeExternalProjections(), hasUnapproximatableArguments)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* declaration site: `class Foo<T> where T: X, T: Y {}`, X and Y aren't related by subtyping
|
||||||
|
* use site: Foo<in {X & Y}>
|
||||||
|
* => `in {X & Y}` is unapproximatable type argument
|
||||||
|
*/
|
||||||
|
fun hasUnapproximatableArguments(type: KotlinType) =
|
||||||
|
type.arguments.isNotEmpty() && type.arguments.withIndex().any { (i, argument) ->
|
||||||
|
if (argument.projectionKind != Variance.IN_VARIANCE) return@any false
|
||||||
|
if (argument.type.constructor !is IntersectionTypeConstructor) return@any false
|
||||||
|
val typeParameter = type.constructor.parameters.getOrNull(i) ?: return@any false
|
||||||
|
// we have really intersection type as the result => at least there are two upper bounds which aren't related by subtyping
|
||||||
|
intersectWrappedTypes(typeParameter.upperBounds).constructor is IntersectionTypeConstructor
|
||||||
|
}
|
||||||
|
|
||||||
open fun isSamType(type: KotlinType): Boolean {
|
open fun isSamType(type: KotlinType): Boolean {
|
||||||
val descriptor = type.constructor.declarationDescriptor
|
val descriptor = type.constructor.declarationDescriptor
|
||||||
return descriptor is ClassDescriptor && descriptor.isFun
|
return descriptor is ClassDescriptor && descriptor.isFun
|
||||||
}
|
}
|
||||||
|
|
||||||
fun create(originalType: KotlinType): SamType? {
|
@JvmOverloads
|
||||||
return if (isSamType(originalType)) SamType(originalType) else null
|
fun create(originalType: KotlinType, hasUnapproximatableArguments: Boolean = false): SamType? {
|
||||||
|
return if (isSamType(originalType)) SamType(originalType, hasUnapproximatableArguments) else null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.removeExternalProjections(): KotlinType {
|
private fun KotlinType.removeExternalProjections(): KotlinType {
|
||||||
|
|||||||
+4
-4
@@ -862,7 +862,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
if (valueArguments == null) return;
|
if (valueArguments == null) return;
|
||||||
|
|
||||||
for (ValueParameterDescriptor valueParameter : valueParametersWithSAMConversion) {
|
for (ValueParameterDescriptor valueParameter : valueParametersWithSAMConversion) {
|
||||||
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
|
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter, this.languageVersionSettings);
|
||||||
if (samType == null) continue;
|
if (samType == null) continue;
|
||||||
|
|
||||||
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
||||||
@@ -874,7 +874,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void recordSamTypeOnArgumentExpression(ValueParameterDescriptor valueParameter, ValueArgument valueArgument) {
|
private void recordSamTypeOnArgumentExpression(ValueParameterDescriptor valueParameter, ValueArgument valueArgument) {
|
||||||
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
|
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter, this.languageVersionSettings);
|
||||||
if (samType == null) return;
|
if (samType == null) return;
|
||||||
|
|
||||||
recordSamTypeOnArgumentExpression(samType, valueArgument);
|
recordSamTypeOnArgumentExpression(samType, valueArgument);
|
||||||
@@ -973,7 +973,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor);
|
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter((FunctionDescriptor) operationDescriptor);
|
||||||
if (original == null) return;
|
if (original == null) return;
|
||||||
|
|
||||||
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(original.getValueParameters().get(0));
|
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(original.getValueParameters().get(0), this.languageVersionSettings);
|
||||||
if (samType == null) return;
|
if (samType == null) return;
|
||||||
|
|
||||||
IElementType token = expression.getOperationToken();
|
IElementType token = expression.getOperationToken();
|
||||||
@@ -1002,7 +1002,7 @@ class CodegenAnnotatingVisitor extends KtVisitorVoid {
|
|||||||
List<KtExpression> indexExpressions = expression.getIndexExpressions();
|
List<KtExpression> indexExpressions = expression.getIndexExpressions();
|
||||||
List<ValueParameterDescriptor> parameters = original.getValueParameters();
|
List<ValueParameterDescriptor> parameters = original.getValueParameters();
|
||||||
for (ValueParameterDescriptor valueParameter : parameters) {
|
for (ValueParameterDescriptor valueParameter : parameters) {
|
||||||
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter);
|
SamType samType = JvmSamTypeFactory.INSTANCE.createByValueParameter(valueParameter, this.languageVersionSettings);
|
||||||
if (samType == null) continue;
|
if (samType == null) continue;
|
||||||
|
|
||||||
if (isSetter && valueParameter.getIndex() == parameters.size() - 1) {
|
if (isSetter && valueParameter.getIndex() == parameters.size() - 1) {
|
||||||
|
|||||||
+34
@@ -39182,6 +39182,40 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Approximation {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
@@ -284,6 +284,11 @@ interface ConeTypeContext : TypeSystemContext, TypeSystemOptimizationContext, Ty
|
|||||||
return this.symbol.fir.bounds[index].coneType
|
return this.symbol.fir.bounds[index].coneType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun TypeParameterMarker.getUpperBounds(): List<KotlinTypeMarker> {
|
||||||
|
require(this is ConeTypeParameterLookupTag)
|
||||||
|
return this.symbol.fir.bounds.map { it.coneType }
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
||||||
require(this is ConeTypeParameterLookupTag)
|
require(this is ConeTypeParameterLookupTag)
|
||||||
return this
|
return this
|
||||||
|
|||||||
+5
-2
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.backend.jvm
|
|||||||
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
import org.jetbrains.kotlin.backend.common.ir.createImplicitParameterDeclarationWithWrappedDescriptor
|
||||||
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
|
import org.jetbrains.kotlin.backend.common.ir.createParameterDeclarations
|
||||||
import org.jetbrains.kotlin.codegen.JvmSamTypeFactory
|
import org.jetbrains.kotlin.codegen.JvmSamTypeFactory
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
import org.jetbrains.kotlin.descriptors.annotations.FilteredAnnotations
|
||||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||||
@@ -59,8 +60,10 @@ open class JvmGeneratorExtensionsImpl(private val generateFacades: Boolean = tru
|
|||||||
override fun isPlatformSamType(type: KotlinType): Boolean =
|
override fun isPlatformSamType(type: KotlinType): Boolean =
|
||||||
JavaSingleAbstractMethodUtils.isSamType(type)
|
JavaSingleAbstractMethodUtils.isSamType(type)
|
||||||
|
|
||||||
override fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? =
|
override fun getSamTypeForValueParameter(
|
||||||
JvmSamTypeFactory.createByValueParameter(valueParameter)?.type
|
valueParameter: ValueParameterDescriptor,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
|
): KotlinType? = JvmSamTypeFactory.createByValueParameter(valueParameter, languageVersionSettings)?.type
|
||||||
|
|
||||||
companion object Instance : JvmSamConversion()
|
companion object Instance : JvmSamConversion()
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -585,7 +585,7 @@ fun StatementGenerator.generateSamConversionForValueArgumentsIfRequired(call: Ca
|
|||||||
if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue
|
if (!originalValueParameters[i].type.isFunctionTypeOrSubtype) continue
|
||||||
}
|
}
|
||||||
|
|
||||||
val samKotlinType = samConversion.getSamTypeForValueParameter(underlyingValueParameter)
|
val samKotlinType = samConversion.getSamTypeForValueParameter(underlyingValueParameter, context.languageVersionSettings)
|
||||||
?: underlyingValueParameter.varargElementType // If we have a vararg, vararg element type will be taken
|
?: underlyingValueParameter.varargElementType // If we have a vararg, vararg element type will be taken
|
||||||
?: underlyingValueParameter.type
|
?: underlyingValueParameter.type
|
||||||
|
|
||||||
|
|||||||
+5
-2
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.psi.KtPureClassOrObject
|
|||||||
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
import org.jetbrains.kotlin.resolve.scopes.MemberScope
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.backend.common.SamTypeFactory
|
import org.jetbrains.kotlin.backend.common.SamTypeFactory
|
||||||
|
import org.jetbrains.kotlin.config.LanguageVersionSettings
|
||||||
|
|
||||||
open class GeneratorExtensions : StubGeneratorExtensions() {
|
open class GeneratorExtensions : StubGeneratorExtensions() {
|
||||||
open val samConversion: SamConversion
|
open val samConversion: SamConversion
|
||||||
@@ -24,8 +25,10 @@ open class GeneratorExtensions : StubGeneratorExtensions() {
|
|||||||
open class SamConversion {
|
open class SamConversion {
|
||||||
open fun isPlatformSamType(type: KotlinType): Boolean = false
|
open fun isPlatformSamType(type: KotlinType): Boolean = false
|
||||||
|
|
||||||
open fun getSamTypeForValueParameter(valueParameter: ValueParameterDescriptor): KotlinType? =
|
open fun getSamTypeForValueParameter(
|
||||||
SamTypeFactory.INSTANCE.createByValueParameter(valueParameter)?.type
|
valueParameter: ValueParameterDescriptor,
|
||||||
|
languageVersionSettings: LanguageVersionSettings
|
||||||
|
): KotlinType? = SamTypeFactory.INSTANCE.createByValueParameter(valueParameter, languageVersionSettings)?.type
|
||||||
|
|
||||||
companion object Instance : SamConversion()
|
companion object Instance : SamConversion()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -176,6 +176,8 @@ interface IrTypeSystemContext : TypeSystemContext, TypeSystemCommonSuperTypesCon
|
|||||||
|
|
||||||
override fun TypeParameterMarker.getUpperBound(index: Int) = getSuperTypes(this)[index] as KotlinTypeMarker
|
override fun TypeParameterMarker.getUpperBound(index: Int) = getSuperTypes(this)[index] as KotlinTypeMarker
|
||||||
|
|
||||||
|
override fun TypeParameterMarker.getUpperBounds() = getSuperTypes(this) as List<KotlinTypeMarker>
|
||||||
|
|
||||||
override fun TypeParameterMarker.getTypeConstructor() = this as IrTypeParameterSymbol
|
override fun TypeParameterMarker.getTypeConstructor() = this as IrTypeParameterSymbol
|
||||||
|
|
||||||
private fun KotlinTypeMarker.containsTypeConstructor(constructor: TypeConstructorMarker): Boolean {
|
private fun KotlinTypeMarker.containsTypeConstructor(constructor: TypeConstructorMarker): Boolean {
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
interface X
|
||||||
|
interface Z
|
||||||
|
|
||||||
|
interface W : X, Z
|
||||||
|
|
||||||
|
interface A : W
|
||||||
|
interface B : W
|
||||||
|
|
||||||
|
fun interface IFoo<T> where T : X, T : Z {
|
||||||
|
fun accept(t: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> sel(x: T, y: T) = x
|
||||||
|
|
||||||
|
class G<T> where T: X, T: Z {
|
||||||
|
fun check(x: IFoo<in T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val g = sel(G<A>(), G<B>()) // g: G<out { X & Z }>
|
||||||
|
g.check {} // target SAM type: IFoo<W>
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
interface X
|
||||||
|
interface Z
|
||||||
|
|
||||||
|
interface A : X, Z
|
||||||
|
interface B : X, Z
|
||||||
|
|
||||||
|
fun interface IFoo<T: X> {
|
||||||
|
fun accept(t: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> sel(x: T, y: T) = x
|
||||||
|
|
||||||
|
class G<T: X> {
|
||||||
|
fun check(x: IFoo<in T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val g = sel(G<A>(), G<B>()) // g: G<out { X & Z }>
|
||||||
|
g.check {} // (*) target SAM type: IFoo<X>
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
interface X
|
||||||
|
interface Z
|
||||||
|
|
||||||
|
interface A : X, Z
|
||||||
|
interface B : X, Z
|
||||||
|
|
||||||
|
fun interface IFoo<T> where T : X, T : Z {
|
||||||
|
fun accept(t: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> sel(x: T, y: T) = x
|
||||||
|
|
||||||
|
class G<T> where T: X, T: Z {
|
||||||
|
fun check(x: IFoo<in T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val g = sel(G<A>(), G<B>()) // g: G<out { X & Z }>
|
||||||
|
g.check {} // (*) target SAM type: IFoo<{ X & Z }> (TODO: report a compile time error for this case)
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+24
@@ -0,0 +1,24 @@
|
|||||||
|
interface X: U, W
|
||||||
|
interface Z: U, W
|
||||||
|
|
||||||
|
interface U
|
||||||
|
interface W
|
||||||
|
|
||||||
|
interface A : X, Z
|
||||||
|
interface B : X, Z
|
||||||
|
|
||||||
|
fun interface IFoo<T> where T : U, T : W {
|
||||||
|
fun accept(t: T)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> sel(x: T, y: T) = x
|
||||||
|
|
||||||
|
class G<T> where T: U, T: W {
|
||||||
|
fun check(x: IFoo<in T>) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
val g = sel(G<A>(), G<B>())
|
||||||
|
g.check {} // TODO: report a compile time error for this case
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
+34
@@ -39140,6 +39140,40 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Approximation {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+34
@@ -39182,6 +39182,40 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nested
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
public class Approximation {
|
||||||
|
@Test
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Nested
|
@Nested
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
|||||||
+33
@@ -31285,6 +31285,39 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Approximation extends AbstractLightAnalysisModeTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest(this::doTest, TargetBackend.JVM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JVM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
@@ -325,6 +325,7 @@ interface TypeSystemContext : TypeSystemOptimizationContext {
|
|||||||
fun TypeParameterMarker.getVariance(): TypeVariance
|
fun TypeParameterMarker.getVariance(): TypeVariance
|
||||||
fun TypeParameterMarker.upperBoundCount(): Int
|
fun TypeParameterMarker.upperBoundCount(): Int
|
||||||
fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker
|
fun TypeParameterMarker.getUpperBound(index: Int): KotlinTypeMarker
|
||||||
|
fun TypeParameterMarker.getUpperBounds(): List<KotlinTypeMarker>
|
||||||
fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker
|
fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker
|
||||||
fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean
|
fun TypeParameterMarker.hasRecursiveBounds(selfConstructor: TypeConstructorMarker): Boolean
|
||||||
|
|
||||||
|
|||||||
@@ -230,6 +230,11 @@ interface ClassicTypeSystemContext : TypeSystemInferenceExtensionContext, TypeSy
|
|||||||
return this.upperBounds[index]
|
return this.upperBounds[index]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun TypeParameterMarker.getUpperBounds(): List<KotlinTypeMarker> {
|
||||||
|
require(this is TypeParameterDescriptor, this::errorMessage)
|
||||||
|
return this.upperBounds
|
||||||
|
}
|
||||||
|
|
||||||
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
override fun TypeParameterMarker.getTypeConstructor(): TypeConstructorMarker {
|
||||||
require(this is TypeParameterDescriptor, this::errorMessage)
|
require(this is TypeParameterDescriptor, this::errorMessage)
|
||||||
return this.typeConstructor
|
return this.typeConstructor
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/es6/semantics/IrJsCodegenBoxES6TestGenerated.java
Generated
+33
@@ -26285,6 +26285,39 @@ public class IrJsCodegenBoxES6TestGenerated extends AbstractIrJsCodegenBoxES6Tes
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Approximation extends AbstractIrJsCodegenBoxES6Test {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR_ES6, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR_ES6, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+33
@@ -25691,6 +25691,39 @@ public class IrJsCodegenBoxTestGenerated extends AbstractIrJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Approximation extends AbstractIrJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS_IR, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS_IR, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Generated
+33
@@ -25651,6 +25651,39 @@ public class JsCodegenBoxTestGenerated extends AbstractJsCodegenBoxTest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Approximation extends AbstractJsCodegenBoxTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.JS, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^(.+)\\.kt$"), null, TargetBackend.JS, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/wasm/semantics/IrCodegenBoxWasmTestGenerated.java
Generated
+33
@@ -14022,6 +14022,39 @@ public class IrCodegenBoxWasmTestGenerated extends AbstractIrCodegenBoxWasmTest
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("compiler/testData/codegen/box/sam/approximation")
|
||||||
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
public static class Approximation extends AbstractIrCodegenBoxWasmTest {
|
||||||
|
private void runTest(String testDataFilePath) throws Exception {
|
||||||
|
KotlinTestUtils.runTest0(this::doTest, TargetBackend.WASM, testDataFilePath);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void testAllFilesPresentInApproximation() throws Exception {
|
||||||
|
KtTestUtil.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/codegen/box/sam/approximation"), Pattern.compile("^([^_](.+))\\.kt$"), null, TargetBackend.WASM, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToIntermediateType.kt")
|
||||||
|
public void testApproxToIntermediateType() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToIntermediateType.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("approxToSingleUpperBound.kt")
|
||||||
|
public void testApproxToSingleUpperBound() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/approxToSingleUpperBound.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable.kt");
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("impossibleToApproxToRepresentable2.kt")
|
||||||
|
public void testImpossibleToApproxToRepresentable2() throws Exception {
|
||||||
|
runTest("compiler/testData/codegen/box/sam/approximation/impossibleToApproxToRepresentable2.kt");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
@TestMetadata("compiler/testData/codegen/box/sam/constructors")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user