Allow passing non-spread arrays into a vararg parameter after sam properly, through propagating vararg element type to a sam adapter from the original parameter descriptor

This commit is contained in:
Victor Petukhov
2021-01-19 12:11:09 +03:00
committed by Dmitriy Novozhilov
parent af3eaf5d71
commit 670f029bdf
15 changed files with 70 additions and 126 deletions
@@ -34236,12 +34236,6 @@ public class FirBlackBoxCodegenTestGenerated extends AbstractFirBlackBoxCodegenT
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
}
@Test
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
}
@Test
@TestMetadata("castFromAny.kt")
public void testCastFromAny() throws Exception {
@@ -63,7 +63,8 @@ public class JavaSingleAbstractMethodUtils {
public static SamAdapterDescriptor<JavaMethodDescriptor> createSamAdapterFunction(
@NotNull JavaMethodDescriptor original,
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
@NotNull SamConversionOracle samConversionOracle,
boolean allowNonSpreadArraysForVarargAfterSam
) {
SamAdapterFunctionDescriptor result = new SamAdapterFunctionDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@@ -83,14 +84,15 @@ public class JavaSingleAbstractMethodUtils {
original.getVisibility()
);
}
}, samResolver, samConversionOracle);
}, samResolver, samConversionOracle, allowNonSpreadArraysForVarargAfterSam);
}
@NotNull
public static SamAdapterDescriptor<JavaClassConstructorDescriptor> createSamAdapterConstructor(
@NotNull JavaClassConstructorDescriptor original,
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
@NotNull SamConversionOracle samConversionOracle,
boolean allowNonSpreadArraysForVarargAfterSam
) {
SamAdapterClassConstructorDescriptor result = new SamAdapterClassConstructorDescriptor(original);
return initSamAdapter(original, result, new FunctionInitializer() {
@@ -103,7 +105,7 @@ public class JavaSingleAbstractMethodUtils {
result.initialize(valueParameters, original.getVisibility());
result.setReturnType(returnType);
}
}, samResolver, samConversionOracle);
}, samResolver, samConversionOracle, allowNonSpreadArraysForVarargAfterSam);
}
@NotNull
@@ -112,7 +114,8 @@ public class JavaSingleAbstractMethodUtils {
@NotNull SamAdapterDescriptor<F> adapter,
@NotNull FunctionInitializer initializer,
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
@NotNull SamConversionOracle samConversionOracle,
boolean allowNonSpreadArraysForVarargAfterSam
) {
SamConstructorTypeParameters typeParameters;
if (adapter instanceof SamAdapterClassConstructorDescriptor) {
@@ -131,7 +134,7 @@ public class JavaSingleAbstractMethodUtils {
List<ValueParameterDescriptor> valueParameters =
createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle);
createValueParametersForSamAdapter(original, adapter, substitutor, samResolver, samConversionOracle, allowNonSpreadArraysForVarargAfterSam);
initializer.initialize(typeParameters.getDescriptors(), valueParameters, returnType);
@@ -143,7 +146,8 @@ public class JavaSingleAbstractMethodUtils {
@NotNull FunctionDescriptor samAdapter,
@NotNull TypeSubstitutor substitutor,
@NotNull SamConversionResolver samResolver,
@NotNull SamConversionOracle samConversionOracle
@NotNull SamConversionOracle samConversionOracle,
boolean allowNonSpreadArraysForVarargAfterSam
) {
List<ValueParameterDescriptor> originalValueParameters = original.getValueParameters();
List<ValueParameterDescriptor> valueParameters = new ArrayList<>(originalValueParameters.size());
@@ -154,13 +158,22 @@ public class JavaSingleAbstractMethodUtils {
KotlinType newType = substitutor.substitute(newTypeUnsubstituted, Variance.IN_VARIANCE);
assert newType != null : "couldn't substitute type: " + newTypeUnsubstituted + ", substitutor = " + substitutor;
/*
* Before 1.5 we allowed passing non-spread arrays into vararg parameter, after sam conversion like:
* public static String foo1(Runnable r, String... strs) { }
* ...
* Test.foo1({}, arrayOf())
* For that, we don't pass `varargElementType` from the original parameter descriptor.
*/
KotlinType varargElementType = allowNonSpreadArraysForVarargAfterSam ? null : originalParam.getVarargElementType();
ValueParameterDescriptor newParam = new ValueParameterDescriptorImpl(
samAdapter, null, originalParam.getIndex(), originalParam.getAnnotations(),
originalParam.getName(), newType,
/* declaresDefaultValue = */ false,
/* isCrossinline = */ false,
/* isNoinline = */ false,
null, SourceElement.NO_SOURCE
varargElementType, SourceElement.NO_SOURCE
);
valueParameters.add(newParam);
}
@@ -69,7 +69,7 @@ class JavaSyntheticScopes(
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = samConversionPerArgumentIsEnabled,
shouldGenerateCandidateForVarargAfterSam = !languageVersionSettings.supportsFeature(
allowNonSpreadArraysForVarargAfterSam = !languageVersionSettings.supportsFeature(
LanguageFeature.ProhibitVarargAsArrayAfterSamArgument
)
)
@@ -87,7 +87,7 @@ class JavaSyntheticScopes(
deprecationResolver,
lookupTracker,
samViaSyntheticScopeDisabled = false,
shouldGenerateCandidateForVarargAfterSam = false
allowNonSpreadArraysForVarargAfterSam = false
)
scopesWithForceEnabledSamAdapters =
@@ -59,10 +59,8 @@ class SamAdapterFunctionsScope(
private val deprecationResolver: DeprecationResolver,
private val lookupTracker: LookupTracker,
private val samViaSyntheticScopeDisabled: Boolean,
private val shouldGenerateCandidateForVarargAfterSam: Boolean
private val allowNonSpreadArraysForVarargAfterSam: Boolean
) : SyntheticScope.Default() {
private val shouldGenerateAdditionalSamCandidate = !samViaSyntheticScopeDisabled || shouldGenerateCandidateForVarargAfterSam
private val extensionForFunction =
storageManager.createMemoizedFunctionWithNullableValues<FunctionDescriptor, FunctionDescriptor> { function ->
extensionForFunctionNotCached(function)
@@ -70,8 +68,12 @@ class SamAdapterFunctionsScope(
private val samAdapterForStaticFunction =
storageManager.createMemoizedFunction<JavaMethodDescriptor, SamAdapterDescriptor<JavaMethodDescriptor>> { function ->
JavaSingleAbstractMethodUtils
.createSamAdapterFunction(function, samResolver, samConversionOracle)
JavaSingleAbstractMethodUtils.createSamAdapterFunction(
function,
samResolver,
samConversionOracle,
allowNonSpreadArraysForVarargAfterSam
)
}
private val samConstructorForClassifier =
@@ -81,8 +83,12 @@ class SamAdapterFunctionsScope(
private val samConstructorForJavaConstructor =
storageManager.createMemoizedFunction<JavaClassConstructorDescriptor, ClassConstructorDescriptor> { constructor ->
JavaSingleAbstractMethodUtils
.createSamAdapterConstructor(constructor, samResolver, samConversionOracle) as ClassConstructorDescriptor
JavaSingleAbstractMethodUtils.createSamAdapterConstructor(
constructor,
samResolver,
samConversionOracle,
allowNonSpreadArraysForVarargAfterSam
) as ClassConstructorDescriptor
}
private val samConstructorForTypeAliasConstructor =
@@ -96,7 +102,12 @@ class SamAdapterFunctionsScope(
if (!JavaSingleAbstractMethodUtils.isSamAdapterNecessary(function)) return null
if (function.returnType == null) return null
if (deprecationResolver.isHiddenInResolution(function)) return null
return SamAdapterExtensionFunctionDescriptorImpl.create(function, samResolver, samConversionOracle)
return SamAdapterExtensionFunctionDescriptorImpl.create(
function,
samResolver,
samConversionOracle,
allowNonSpreadArraysForVarargAfterSam
)
}
override fun getSyntheticMemberFunctions(
@@ -104,8 +115,6 @@ class SamAdapterFunctionsScope(
name: Name,
location: LookupLocation
): Collection<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
var result: SmartList<FunctionDescriptor>? = null
for (type in receiverTypes) {
for (function in type.memberScope.getContributedFunctions(name, location)) {
@@ -143,7 +152,7 @@ class SamAdapterFunctionsScope(
}
private val FunctionDescriptor.shouldGenerateCandidateForVarargAfterSamAndHasVararg
get() = shouldGenerateCandidateForVarargAfterSam && valueParameters.lastOrNull()?.isVararg == true
get() = allowNonSpreadArraysForVarargAfterSam && valueParameters.lastOrNull()?.isVararg == true
private val FunctionDescriptor.hasNothingTypeInParameters
get() = valueParameters.any { it.type.isNothing() && !it.original.type.isNothing() }
@@ -161,8 +170,6 @@ class SamAdapterFunctionsScope(
}
override fun getSyntheticMemberFunctions(receiverTypes: Collection<KotlinType>): Collection<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
return receiverTypes.flatMapTo(LinkedHashSet<FunctionDescriptor>()) { type ->
type.memberScope.getContributedDescriptors(DescriptorKindFilter.FUNCTIONS)
.filterIsInstance<FunctionDescriptor>()
@@ -179,8 +186,6 @@ class SamAdapterFunctionsScope(
contributedFunctions: Collection<FunctionDescriptor>,
location: LookupLocation
): Collection<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
return getSamFunctions(contributedFunctions, location)
}
@@ -190,8 +195,6 @@ class SamAdapterFunctionsScope(
): Collection<FunctionDescriptor> {
recordSamLookupsToClassifier(contributedClassifier, location)
if (!shouldGenerateAdditionalSamCandidate) return listOfNotNull(getSamConstructor(contributedClassifier))
return getAllSamConstructors(contributedClassifier)
}
@@ -204,16 +207,12 @@ class SamAdapterFunctionsScope(
}
override fun getSyntheticStaticFunctions(functionDescriptors: Collection<DeclarationDescriptor>): Collection<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
return getSamFunctions(functionDescriptors, location = null)
}
override fun getSyntheticConstructors(classifierDescriptors: Collection<DeclarationDescriptor>): Collection<FunctionDescriptor> {
val classifiers = classifierDescriptors.filterIsInstance<ClassifierDescriptor>()
if (!shouldGenerateAdditionalSamCandidate) return classifiers.mapNotNull { getSamConstructor(it) }
return classifiers.flatMap { getAllSamConstructors(it) }
}
@@ -242,8 +241,6 @@ class SamAdapterFunctionsScope(
functions: Collection<DeclarationDescriptor>,
location: LookupLocation?
): List<SamAdapterDescriptor<JavaMethodDescriptor>> {
if (!shouldGenerateAdditionalSamCandidate) return emptyList()
return functions.mapNotNull { function ->
if (function !is JavaMethodDescriptor) return@mapNotNull null
if (function.dispatchReceiverParameter != null) return@mapNotNull null // consider only statics
@@ -263,7 +260,7 @@ class SamAdapterFunctionsScope(
}
private fun getSamAdaptersFromConstructors(classifier: ClassifierDescriptor): MutableList<FunctionDescriptor> {
if (!shouldGenerateAdditionalSamCandidate || classifier !is JavaClassDescriptor) return SmartList()
if (classifier !is JavaClassDescriptor) return SmartList()
return SmartList<FunctionDescriptor>().apply {
for (constructor in classifier.constructors) {
@@ -313,7 +310,8 @@ class SamAdapterFunctionsScope(
fun create(
sourceFunction: FunctionDescriptor,
samResolver: SamConversionResolver,
samConversionOracle: SamConversionOracle
samConversionOracle: SamConversionOracle,
allowNonSpreadArraysForVarargAfterSam: Boolean
): SamAdapterExtensionFunctionDescriptorImpl {
val descriptor = SamAdapterExtensionFunctionDescriptorImpl(
sourceFunction.containingDeclaration,
@@ -334,7 +332,7 @@ class SamAdapterFunctionsScope(
val returnType = typeSubstitutor.safeSubstitute(sourceFunction.returnType!!, Variance.INVARIANT)
val valueParameters = JavaSingleAbstractMethodUtils.createValueParametersForSamAdapter(
sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle
sourceFunction, descriptor, typeSubstitutor, samResolver, samConversionOracle, allowNonSpreadArraysForVarargAfterSam
)
val visibility = syntheticVisibility(sourceFunction, isUsedForExtension = false)
@@ -24,11 +24,8 @@ object SamTypeConversions : ParameterTypeConversion {
expectedParameterType: UnwrappedType
): Boolean {
val callComponents = candidate.callComponents
val generatingAdditionalSamCandidateIsEnabled =
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument) &&
!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.ProhibitVarargAsArrayAfterSamArgument)
if (generatingAdditionalSamCandidateIsEnabled) return true
if (!callComponents.languageVersionSettings.supportsFeature(LanguageFeature.SamConversionPerArgument)) return true
if (expectedParameterType.isNothing()) return true
if (expectedParameterType.isFunctionType) return true
@@ -1,41 +0,0 @@
// !LANGUAGE: +NewInference +SamConversionForKotlinFunctions -SamConversionPerArgument
// IGNORE_BACKEND_FIR: JVM_IR
// TARGET_BACKEND: JVM
// FILE: Test.java
public class Test {
public static String foo1(Runnable r, String... strs) {
return null;
}
public String foo2(Runnable r1, Runnable r2, String... strs) {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
fun box(): String {
val x1 = {}
val x2: Runnable = Runnable { }
val x3 = arrayOf<String>()
Test.foo1({}, arrayOf())
Test.foo1({}, arrayOf(""))
Test.foo1(x1, arrayOf())
Test.foo1(x2, *arrayOf())
Test.foo1(x1, x3)
Test.foo1(x2, *arrayOf(""))
val i1 = Test({}, arrayOf())
val i3 = Test({}, x3)
val i4 = Test({}, arrayOf(""))
val i6 = Test({}, {}, arrayOf())
i1.foo2({}, {}, arrayOf())
i1.foo2({}, {}, arrayOf(""))
return "OK"
}
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -42,13 +42,13 @@ fun main(x2: Runnable) {
val i5 = Test({}, {}, *arrayOf(""))
val i6 = <!NONE_APPLICABLE!>Test<!>({}, {}, arrayOf())
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, {}, arrayOf())
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, {}, *arrayOf())
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, x2, arrayOf())
i1.<!UNRESOLVED_REFERENCE!>foo2<!>(x2, {}, *arrayOf())
i2.<!INAPPLICABLE_CANDIDATE!>foo2<!>({}, {}, arrayOf())
i2.foo2({}, {}, *arrayOf())
i2.<!INAPPLICABLE_CANDIDATE!>foo2<!>({}, x2, arrayOf())
i2.foo2(x2, {}, *arrayOf())
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, {}, arrayOf(""))
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, {}, *x3)
i1.<!UNRESOLVED_REFERENCE!>foo2<!>({}, x2, x3)
i1.<!UNRESOLVED_REFERENCE!>foo2<!>(x2, {}, *arrayOf(""))
i2.<!INAPPLICABLE_CANDIDATE!>foo2<!>({}, {}, arrayOf(""))
i2.foo2({}, {}, *x3)
i2.<!INAPPLICABLE_CANDIDATE!>foo2<!>({}, x2, x3)
i2.foo2(x2, {}, *arrayOf(""))
}
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -42,13 +42,13 @@ fun main(x2: Runnable) {
val i5 = Test({}, {}, *arrayOf(""))
val i6 = Test({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
i1.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
i1.foo2({}, {}, *arrayOf())
i1.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
i1.foo2(x2, {}, *arrayOf())
i2.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
i2.foo2({}, {}, *arrayOf())
i2.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf()<!>)
i2.foo2(x2, {}, *arrayOf())
i1.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf("")<!>)
i1.foo2({}, {}, *x3)
i1.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
i1.foo2(x2, {}, *arrayOf(""))
i2.foo2({}, {}, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>arrayOf("")<!>)
i2.foo2({}, {}, *x3)
i2.foo2({}, <!TYPE_MISMATCH!>x2<!>, <!TYPE_INFERENCE_CANDIDATE_WITH_SAM_AND_VARARG!>x3<!>)
i2.foo2(x2, {}, *arrayOf(""))
}
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -12,7 +12,7 @@ public class Test {
return null;
}
public Test(Runnable r, String... strs) {}
public Test(Runnable r, Runnable r, String... strs) {}
public Test(Runnable r1, Runnable r2, String... strs) {}
}
// FILE: main.kt
@@ -34436,12 +34436,6 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
}
@Test
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
}
@Test
@TestMetadata("castFromAny.kt")
public void testCastFromAny() throws Exception {
@@ -34236,12 +34236,6 @@ public class IrBlackBoxCodegenTestGenerated extends AbstractIrBlackBoxCodegenTes
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
}
@Test
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
}
@Test
@TestMetadata("castFromAny.kt")
public void testCastFromAny() throws Exception {
@@ -28085,11 +28085,6 @@ public class LightAnalysisModeTestGenerated extends AbstractLightAnalysisModeTes
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgument.kt");
}
@TestMetadata("arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt")
public void testArrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument() throws Exception {
runTest("compiler/testData/codegen/box/sam/arrayAsVarargAfterSamArgumentWithoutSamConversionsPerArgument.kt");
}
@TestMetadata("castFromAny.kt")
public void testCastFromAny() throws Exception {
runTest("compiler/testData/codegen/box/sam/castFromAny.kt");