FIR: Support SAM constructors
This commit is contained in:
@@ -10,18 +10,29 @@ import org.jetbrains.kotlin.descriptors.Modality
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.FirSessionComponent
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirTypeParameterImpl
|
||||
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.FirSyntheticFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.resolve.calls.SAM_PARAMETER_NAME
|
||||
import org.jetbrains.kotlin.fir.resolve.substitution.substitutorByMap
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.CallableId
|
||||
import org.jetbrains.kotlin.fir.symbols.StandardClassIds
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.ConeClassLikeLookupTagImpl
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.types.Variance
|
||||
|
||||
interface FirSamResolver : FirSessionComponent {
|
||||
fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType?
|
||||
fun shouldRunSamConversionForFunction(firNamedFunction: FirNamedFunction): Boolean
|
||||
fun getSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction?
|
||||
}
|
||||
|
||||
private val NULL_STUB = Any()
|
||||
@@ -31,7 +42,8 @@ class FirSamResolverImpl(
|
||||
private val scopeSession: ScopeSession
|
||||
) : FirSamResolver {
|
||||
|
||||
private val cache: MutableMap<FirRegularClass, Any> = mutableMapOf()
|
||||
private val resolvedFunctionType: MutableMap<FirRegularClass, Any> = mutableMapOf()
|
||||
private val samConstructor: MutableMap<FirRegularClass, Any> = mutableMapOf()
|
||||
|
||||
override fun getFunctionTypeForPossibleSamType(type: ConeKotlinType): ConeKotlinType? {
|
||||
return when (type) {
|
||||
@@ -80,8 +92,85 @@ class FirSamResolverImpl(
|
||||
return result
|
||||
}
|
||||
|
||||
override fun getSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction? {
|
||||
return samConstructor.getOrPut(firRegularClass) {
|
||||
buildSamConstructor(firRegularClass) ?: return@getOrPut NULL_STUB
|
||||
} as? FirNamedFunction
|
||||
}
|
||||
|
||||
private fun buildSamConstructor(firRegularClass: FirRegularClass): FirNamedFunction? {
|
||||
val functionType = resolveFunctionTypeIfSamInterface(firRegularClass) ?: return null
|
||||
|
||||
val classId = firRegularClass.classId
|
||||
val symbol = FirSyntheticFunctionSymbol(
|
||||
CallableId(
|
||||
classId.packageFqName,
|
||||
classId.relativeClassName.parent().takeIf { !it.isRoot },
|
||||
classId.shortClassName
|
||||
)
|
||||
)
|
||||
|
||||
val newTypeParameters = firRegularClass.typeParameters.map { typeParameter ->
|
||||
FirTypeParameterImpl(
|
||||
firSession, typeParameter.psi, FirTypeParameterSymbol(), typeParameter.name, Variance.INVARIANT,
|
||||
isReified = false
|
||||
).apply {
|
||||
annotations += typeParameter.annotations
|
||||
}
|
||||
}
|
||||
|
||||
val newTypeParameterTypes =
|
||||
newTypeParameters
|
||||
.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), isNullable = false) }
|
||||
|
||||
val substitutor = substitutorByMap(
|
||||
firRegularClass.typeParameters
|
||||
.map { it.symbol }
|
||||
.zip(newTypeParameterTypes).toMap()
|
||||
)
|
||||
|
||||
for ((newTypeParameter, oldTypeParameter) in newTypeParameters.zip(firRegularClass.typeParameters)) {
|
||||
newTypeParameter.bounds += oldTypeParameter.bounds.mapNotNull { typeRef ->
|
||||
FirResolvedTypeRefImpl(typeRef.psi, substitutor.substituteOrSelf(typeRef.coneTypeSafe() ?: return@mapNotNull null))
|
||||
}
|
||||
}
|
||||
|
||||
val substitutedFunctionType = substitutor.substituteOrSelf(functionType)
|
||||
val substitutedReturnType =
|
||||
ConeClassTypeImpl(
|
||||
firRegularClass.symbol.toLookupTag(), newTypeParameterTypes.toTypedArray(), isNullable = false
|
||||
)
|
||||
|
||||
return FirMemberFunctionImpl(
|
||||
firSession, null, symbol, classId.shortClassName,
|
||||
firRegularClass.visibility, Modality.FINAL,
|
||||
isExpect = firRegularClass.isExpect,
|
||||
isActual = firRegularClass.isActual,
|
||||
isOverride = false,
|
||||
isOperator = false,
|
||||
isInfix = false,
|
||||
isExternal = false,
|
||||
isInline = false,
|
||||
isSuspend = false,
|
||||
isTailRec = false,
|
||||
receiverTypeRef = null,
|
||||
returnTypeRef = FirResolvedTypeRefImpl(null, substitutedReturnType)
|
||||
).apply {
|
||||
valueParameters += listOf(
|
||||
FirValueParameterImpl(
|
||||
session, psi, SAM_PARAMETER_NAME,
|
||||
FirResolvedTypeRefImpl(firRegularClass.psi, substitutedFunctionType),
|
||||
defaultValue = null,
|
||||
isCrossinline = false, isNoinline = false, isVararg = false
|
||||
)
|
||||
)
|
||||
typeParameters += newTypeParameters
|
||||
resolvePhase = FirResolvePhase.BODY_RESOLVE
|
||||
}
|
||||
}
|
||||
|
||||
private fun resolveFunctionTypeIfSamInterface(firRegularClass: FirRegularClass): ConeKotlinType? {
|
||||
return cache.getOrPut(firRegularClass) {
|
||||
return resolvedFunctionType.getOrPut(firRegularClass) {
|
||||
val abstractMethod = firRegularClass.getSingleAbstractMethodOrNull(firSession, scopeSession) ?: return@getOrPut NULL_STUB
|
||||
// TODO: val shouldConvertFirstParameterToDescriptor = samWithReceiverResolvers.any { it.shouldConvertFirstSamParameterToReceiver(abstractMethod) }
|
||||
|
||||
|
||||
@@ -23,6 +23,7 @@ sealed class CallKind {
|
||||
object Function : CallKind() {
|
||||
override val resolutionSequence: List<ResolutionStage> = listOf(
|
||||
CheckVisibility,
|
||||
DiscriminateSynthetics,
|
||||
MapArguments,
|
||||
CheckExplicitReceiverConsistency,
|
||||
CreateFreshTypeVariableSubstitutorStage,
|
||||
@@ -42,4 +43,4 @@ sealed class CallKind {
|
||||
CheckReceivers.Extension
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ class ScopeTowerLevel(
|
||||
TowerScopeLevel.Token.Functions -> scope.processFunctionsAndConstructorsByName(
|
||||
name,
|
||||
session,
|
||||
bodyResolveComponents.scopeSession
|
||||
bodyResolveComponents
|
||||
) { candidate ->
|
||||
if (candidate.hasConsistentReceivers(extensionReceiver)) {
|
||||
processor.consumeCandidate(
|
||||
@@ -252,7 +252,7 @@ class QualifiedReceiverTowerLevel(
|
||||
processor.consumeCandidate(it as T, null, null)
|
||||
}
|
||||
TowerScopeLevel.Token.Functions -> {
|
||||
scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents.scopeSession, processorForCallables)
|
||||
scope.processFunctionsAndConstructorsByName(name, session, bodyResolveComponents, processorForCallables)
|
||||
}
|
||||
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name, processorForCallables)
|
||||
|
||||
@@ -275,7 +275,7 @@ private fun FirCallableSymbol<*>.hasExtensionReceiver(): Boolean = this.fir.rece
|
||||
private fun FirScope.processFunctionsAndConstructorsByName(
|
||||
name: Name,
|
||||
session: FirSession,
|
||||
scopeSession: ScopeSession,
|
||||
bodyResolveComponents: BodyResolveComponents,
|
||||
processor: (FirCallableSymbol<*>) -> ProcessorAction
|
||||
): ProcessorAction {
|
||||
val matchedClassSymbol = getFirstClassifierOrNull(name) as? FirClassLikeSymbol<*>
|
||||
@@ -284,13 +284,22 @@ private fun FirScope.processFunctionsAndConstructorsByName(
|
||||
matchedClassSymbol,
|
||||
processor,
|
||||
session,
|
||||
scopeSession,
|
||||
bodyResolveComponents.scopeSession,
|
||||
name
|
||||
).stop()
|
||||
) {
|
||||
return ProcessorAction.STOP
|
||||
}
|
||||
|
||||
if (processSyntheticConstructors(
|
||||
matchedClassSymbol,
|
||||
processor,
|
||||
bodyResolveComponents
|
||||
).stop()
|
||||
) {
|
||||
return ProcessorAction.STOP
|
||||
}
|
||||
|
||||
return processFunctionsByName(name, processor)
|
||||
}
|
||||
|
||||
@@ -315,6 +324,21 @@ private fun finalExpansionName(symbol: FirTypeAliasSymbol, session: FirSession):
|
||||
|
||||
}
|
||||
|
||||
val SAM_PARAMETER_NAME = Name.identifier("block")
|
||||
|
||||
private fun processSyntheticConstructors(
|
||||
matchedSymbol: FirClassLikeSymbol<*>?,
|
||||
processor: (FirFunctionSymbol<*>) -> ProcessorAction,
|
||||
bodyResolveComponents: BodyResolveComponents
|
||||
): ProcessorAction {
|
||||
if (matchedSymbol == null) return ProcessorAction.NEXT
|
||||
if (matchedSymbol !is FirClassSymbol) return ProcessorAction.NEXT
|
||||
|
||||
val function = bodyResolveComponents.samResolver.getSamConstructor(matchedSymbol.fir) ?: return ProcessorAction.NEXT
|
||||
|
||||
return processor(function.symbol)
|
||||
}
|
||||
|
||||
private fun processConstructors(
|
||||
matchedSymbol: FirClassLikeSymbol<*>?,
|
||||
processor: (FirFunctionSymbol<*>) -> ProcessorAction,
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
// FILE: MyFunction.java
|
||||
public interface MyFunction<T, R> {
|
||||
R foo(T x);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun main() {
|
||||
MyFunction<Int, String>{ x ->
|
||||
x.toInt().toString()
|
||||
}
|
||||
|
||||
MyFunction { x: Int ->
|
||||
x.toString()
|
||||
}
|
||||
|
||||
MyFunction { x ->
|
||||
""
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
FILE: main.kt
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/MyFunction|<R|kotlin/Int|, R|kotlin/String|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|()
|
||||
}
|
||||
)
|
||||
R|/MyFunction|<R|kotlin/Any?|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Any.toString|()
|
||||
}
|
||||
)
|
||||
R|/MyFunction|<R|kotlin/Any?|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Any?|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
String()
|
||||
}
|
||||
)
|
||||
}
|
||||
Vendored
+38
@@ -0,0 +1,38 @@
|
||||
// FILE: MyFunction.java
|
||||
public interface MyFunction<T, R> {
|
||||
R foo(T x);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun foo1(x: MyFunction<Int, String>) {}
|
||||
fun foo2(x: MyFunction<in Number, out CharSequence>) {}
|
||||
fun <X, Y> foo3(f: MyFunction<X, Y>, x: X) {}
|
||||
|
||||
fun main() {
|
||||
foo1(MyFunction { x ->
|
||||
x.toInt().toString()
|
||||
})
|
||||
|
||||
foo2(MyFunction { x ->
|
||||
x.toInt().toString()
|
||||
})
|
||||
|
||||
foo2(MyFunction { x: Int ->
|
||||
x.toString()
|
||||
})
|
||||
|
||||
foo3(
|
||||
MyFunction { x ->
|
||||
(x + 1).toString()
|
||||
},
|
||||
1
|
||||
)
|
||||
|
||||
foo3(
|
||||
MyFunction { x: Number ->
|
||||
x.toInt().toString()
|
||||
},
|
||||
2
|
||||
)
|
||||
}
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
FILE: main.kt
|
||||
public final fun foo1(x: R|MyFunction<kotlin/Int, kotlin/String>|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun foo2(x: R|MyFunction<in kotlin/Number, out kotlin/CharSequence>|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun <X, Y> foo3(f: R|MyFunction<X, Y>|, x: R|X|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/foo1|(R|/MyFunction|<R|kotlin/Int|, R|kotlin/String|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Int.toInt|().R|kotlin/Any.toString|()
|
||||
}
|
||||
))
|
||||
R|/foo2|(R|/MyFunction|<R|kotlin/Number|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Number|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|()
|
||||
}
|
||||
))
|
||||
R|/foo2|(R|/MyFunction|<R|kotlin/Number|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Any.toString|()
|
||||
}
|
||||
))
|
||||
R|/foo3|<R|kotlin/Int|, R|ft<kotlin/String, kotlin/String>|>(R|/MyFunction|<R|kotlin/Int|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Int.plus|(Int(1)).R|kotlin/Any.toString|()
|
||||
}
|
||||
), Int(1))
|
||||
R|/foo3|<R|kotlin/Int|, R|ft<kotlin/String, kotlin/String>|>(R|/MyFunction|<R|kotlin/Int|, R|ft<kotlin/String, kotlin/String>|>(<L> = MyFunction@fun <anonymous>(x: R|kotlin/Number|): R|kotlin/String| <kind=EXACTLY_ONCE> {
|
||||
R|<local>/x|.R|kotlin/Number.toInt|().R|kotlin/Any.toString|()
|
||||
}
|
||||
), Int(2))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
// TODO: This interface must be marked as "fun" ones that modifier is supported
|
||||
interface MyRunnable {
|
||||
fun foo(x: Int): Boolean
|
||||
}
|
||||
|
||||
fun foo(m: MyRunnable) {}
|
||||
|
||||
fun main() {
|
||||
foo(MyRunnable { x ->
|
||||
x > 1
|
||||
})
|
||||
|
||||
foo(MyRunnable({ it > 1 }))
|
||||
|
||||
val x = { x: Int -> x > 1 }
|
||||
|
||||
foo(MyRunnable(x))
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
FILE: kotlinSam.kt
|
||||
public abstract interface MyRunnable : R|kotlin/Any| {
|
||||
public abstract fun foo(x: R|kotlin/Int|): R|kotlin/Boolean|
|
||||
|
||||
}
|
||||
public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/foo|(R|/MyRunnable|(<L> = MyRunnable@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
))
|
||||
R|/foo|(R|/MyRunnable|(MyRunnable@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/it|, Int(1))
|
||||
}
|
||||
))
|
||||
lval x: R|kotlin/Function1<kotlin/Int, kotlin/Boolean>| = fun <anonymous>(x: R|kotlin/Int|): kotlin/Boolean {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
|
||||
R|/foo|(R|/MyRunnable|(R|<local>/x|))
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
// FILE: MyRunnable.java
|
||||
public interface MyRunnable {
|
||||
boolean foo(int x);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun foo(m: MyRunnable) {}
|
||||
|
||||
fun MyRunnable(x: (Int) -> Boolean) = 1
|
||||
|
||||
fun main() {
|
||||
foo(MyRunnable { x ->
|
||||
x > 1
|
||||
})
|
||||
|
||||
foo(MyRunnable({ it > 1 }))
|
||||
|
||||
val x = { x: Int -> x > 1 }
|
||||
|
||||
foo(MyRunnable(x))
|
||||
}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
FILE: main.kt
|
||||
public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun MyRunnable(x: R|kotlin/Function1<kotlin/Int, kotlin/Boolean>|): R|kotlin/Int| {
|
||||
^MyRunnable Int(1)
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(R|/MyRunnable|(<L> = MyRunnable@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
))
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(R|/MyRunnable|(MyRunnable@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/it|, Int(1))
|
||||
}
|
||||
))
|
||||
lval x: R|kotlin/Function1<kotlin/Int, kotlin/Boolean>| = fun <anonymous>(x: R|kotlin/Int|): kotlin/Boolean {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
|
||||
<Inapplicable(INAPPLICABLE): [/foo]>#(R|/MyRunnable|(R|<local>/x|))
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun foo(runnable: Runnable) {}
|
||||
|
||||
fun main() {
|
||||
foo(Runnable {})
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
FILE: runnable.kt
|
||||
public final fun foo(runnable: R|java/lang/Runnable|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/foo|(R|java/lang/Runnable|(<L> = Runnable@fun <anonymous>(): R|kotlin/Unit| <kind=EXACTLY_ONCE> {
|
||||
Unit
|
||||
}
|
||||
))
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
// FILE: MyRunnable.java
|
||||
public interface MyRunnable {
|
||||
boolean foo(int x);
|
||||
}
|
||||
|
||||
// FILE: main.kt
|
||||
|
||||
fun foo(m: MyRunnable) {}
|
||||
|
||||
fun main() {
|
||||
foo(MyRunnable { x ->
|
||||
x > 1
|
||||
})
|
||||
|
||||
foo(MyRunnable({ it > 1 }))
|
||||
|
||||
val x = { x: Int -> x > 1 }
|
||||
|
||||
foo(MyRunnable(x))
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
FILE: main.kt
|
||||
public final fun foo(m: R|MyRunnable|): R|kotlin/Unit| {
|
||||
}
|
||||
public final fun main(): R|kotlin/Unit| {
|
||||
R|/foo|(R|/MyRunnable|(<L> = MyRunnable@fun <anonymous>(x: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
))
|
||||
R|/foo|(R|/MyRunnable|(MyRunnable@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Boolean| <kind=EXACTLY_ONCE> {
|
||||
>(R|<local>/it|, Int(1))
|
||||
}
|
||||
))
|
||||
lval x: R|kotlin/Function1<kotlin/Int, kotlin/Boolean>| = fun <anonymous>(x: R|kotlin/Int|): kotlin/Boolean {
|
||||
>(R|<local>/x|, Int(1))
|
||||
}
|
||||
|
||||
R|/foo|(R|/MyRunnable|(R|<local>/x|))
|
||||
}
|
||||
+43
@@ -92,6 +92,49 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/diagnostics/samConstructors")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SamConstructors extends AbstractFirDiagnosticsTest {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInSamConstructors() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/diagnostics/samConstructors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("genericSam.kt")
|
||||
public void testGenericSam() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/genericSam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("genericSamInferenceFromExpectType.kt")
|
||||
public void testGenericSamInferenceFromExpectType() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/genericSamInferenceFromExpectType.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("kotlinSam.kt")
|
||||
public void testKotlinSam() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/kotlinSam.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("realConstructorFunction.kt")
|
||||
public void testRealConstructorFunction() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/realConstructorFunction.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("runnable.kt")
|
||||
public void testRunnable() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/runnable.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/diagnostics/samConstructors/simple.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/diagnostics/samConversions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -1,25 +1,25 @@
|
||||
FILE fqName:<root> fileName:/samConstructors.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:java.lang.Runnable
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: Runnable>#' type=IrErrorType
|
||||
FUN_EXPR type=IrErrorType origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:IrErrorType
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): java.lang.Runnable declared in <root>'
|
||||
CALL 'public final fun Runnable (block: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null
|
||||
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
GET_OBJECT 'CLASS IR_EXTERNAL_DECLARATION_STUB OBJECT name:Unit modality:FINAL visibility:public superTypes:[kotlin.Any]' type=kotlin.Unit
|
||||
FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0<kotlin.Unit>) returnType:IrErrorType
|
||||
FUN name:test2 visibility:public modality:FINAL <> (a:kotlin.Function0<kotlin.Unit>) returnType:java.lang.Runnable
|
||||
VALUE_PARAMETER name:a index:0 type:kotlin.Function0<kotlin.Unit>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (a: kotlin.Function0<kotlin.Unit>): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: Runnable>#' type=IrErrorType
|
||||
GET_VAR 'a: kotlin.Function0<kotlin.Unit> declared in <root>.test2' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (a: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in <root>'
|
||||
CALL 'public final fun Runnable (block: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null
|
||||
block: GET_VAR 'a: kotlin.Function0<kotlin.Unit> declared in <root>.test2' type=kotlin.Function0<kotlin.Unit> origin=null
|
||||
FUN name:foo visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
FUN name:test3 visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
FUN name:test3 visibility:public modality:FINAL <> () returnType:java.lang.Runnable
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: Runnable>#' type=IrErrorType
|
||||
ERROR_CALL 'Unsupported callable reference: ::<Unresolved name: foo>#' type=IrErrorType
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): java.lang.Runnable declared in <root>'
|
||||
CALL 'public final fun Runnable (block: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null
|
||||
block: ERROR_CALL 'Unsupported callable reference: ::<Unresolved name: foo>#' type=IrErrorType
|
||||
FUN name:test4 visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test4 (): IrErrorType declared in <root>'
|
||||
|
||||
+21
-21
@@ -1,22 +1,22 @@
|
||||
FILE fqName:<root> fileName:/samConversionToGeneric.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:<root>.J<kotlin.String>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: J>#' type=IrErrorType
|
||||
FUN_EXPR type=IrErrorType origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (x:IrErrorType) returnType:IrErrorType
|
||||
VALUE_PARAMETER name:x index:0 type:IrErrorType
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Unresolved reference: x#' type=IrErrorType
|
||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:IrErrorType
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: J>#' type=IrErrorType
|
||||
FUN_EXPR type=IrErrorType origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (x:kotlin.String) returnType:IrErrorType
|
||||
RETURN type=kotlin.Nothing from='public final fun test1 (): <root>.J<kotlin.String> declared in <root>'
|
||||
CALL 'public final fun J (block: kotlin.Function1<T of <uninitialized parent>?, T of <uninitialized parent>?>): <root>.J<T of <uninitialized parent>> declared in <root>' type=<root>.J<kotlin.String> origin=null
|
||||
block: FUN_EXPR type=kotlin.Function1<kotlin.String, kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (x:kotlin.String) returnType:kotlin.String
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.String
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Unresolved reference: x#' type=IrErrorType
|
||||
GET_VAR 'x: kotlin.String declared in <root>.test1.<anonymous>' type=kotlin.String origin=null
|
||||
FUN name:test2 visibility:public modality:FINAL <> () returnType:<root>.J<kotlin.String>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test2 (): <root>.J<kotlin.String> declared in <root>'
|
||||
CALL 'public final fun J (block: kotlin.Function1<T of <uninitialized parent>?, T of <uninitialized parent>?>): <root>.J<T of <uninitialized parent>> declared in <root>' type=<root>.J<kotlin.String> origin=null
|
||||
block: FUN_EXPR type=kotlin.Function1<kotlin.String, kotlin.String> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> (x:kotlin.String) returnType:kotlin.String
|
||||
VALUE_PARAMETER name:x index:0 type:kotlin.String
|
||||
BLOCK_BODY
|
||||
GET_VAR 'x: kotlin.String declared in <root>.test2.<anonymous>' type=kotlin.String origin=null
|
||||
FUN name:test3 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test3 (): kotlin.Unit declared in <root>'
|
||||
@@ -54,12 +54,12 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
|
||||
GET_VAR 'a: kotlin.Any declared in <root>.test7' type=kotlin.Any origin=null
|
||||
CALL 'public open fun bar (j: <root>.J<X of <uninitialized parent>?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null
|
||||
j: GET_VAR 'a: kotlin.Any declared in <root>.test7' type=kotlin.Function1<T of <root>.test7, T of <root>.test7> origin=null
|
||||
FUN name:test8 visibility:public modality:FINAL <> (efn:kotlin.Function1<kotlin.String, kotlin.String>) returnType:IrErrorType
|
||||
FUN name:test8 visibility:public modality:FINAL <> (efn:kotlin.Function1<kotlin.String, kotlin.String>) returnType:<root>.J<kotlin.String>
|
||||
VALUE_PARAMETER name:efn index:0 type:kotlin.Function1<kotlin.String, kotlin.String>
|
||||
BLOCK_BODY
|
||||
RETURN type=kotlin.Nothing from='public final fun test8 (efn: kotlin.Function1<kotlin.String, kotlin.String>): IrErrorType declared in <root>'
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: J>#' type=IrErrorType
|
||||
GET_VAR 'efn: kotlin.Function1<kotlin.String, kotlin.String> declared in <root>.test8' type=kotlin.Function1<kotlin.String, kotlin.String> origin=null
|
||||
RETURN type=kotlin.Nothing from='public final fun test8 (efn: kotlin.Function1<kotlin.String, kotlin.String>): <root>.J<kotlin.String> declared in <root>'
|
||||
CALL 'public final fun J (block: kotlin.Function1<T of <uninitialized parent>?, T of <uninitialized parent>?>): <root>.J<T of <uninitialized parent>> declared in <root>' type=<root>.J<kotlin.String> origin=null
|
||||
block: GET_VAR 'efn: kotlin.Function1<kotlin.String, kotlin.String> declared in <root>.test8' type=kotlin.Function1<kotlin.String, kotlin.String> origin=null
|
||||
FUN name:test9 visibility:public modality:FINAL <> (efn:kotlin.Function1<kotlin.String, kotlin.String>) returnType:kotlin.Unit
|
||||
VALUE_PARAMETER name:efn index:0 type:kotlin.Function1<kotlin.String, kotlin.String>
|
||||
BLOCK_BODY
|
||||
@@ -68,5 +68,5 @@ FILE fqName:<root> fileName:/samConversionToGeneric.kt
|
||||
FUN name:test10 visibility:public modality:FINAL <> (fn:kotlin.Function1<kotlin.Int, kotlin.String>) returnType:kotlin.Unit
|
||||
VALUE_PARAMETER name:fn index:0 type:kotlin.Function1<kotlin.Int, kotlin.String>
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Unresolved reference: <Inapplicable(INAPPLICABLE): [/H.bar2x]>#' type=IrErrorType
|
||||
GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.String> declared in <root>.test10' type=kotlin.Function1<kotlin.Int, kotlin.String> origin=null
|
||||
CALL 'public open fun bar2x (j2x: <root>.J2X<Y of <uninitialized parent>?>?): kotlin.Unit declared in <root>.H' type=kotlin.Unit origin=null
|
||||
j2x: GET_VAR 'fn: kotlin.Function1<kotlin.Int, kotlin.String> declared in <root>.test10' type=kotlin.Function1<kotlin.Int, kotlin.String> origin=null
|
||||
|
||||
+8
-7
@@ -1,11 +1,12 @@
|
||||
FILE fqName:<root> fileName:/samAdapter.kt
|
||||
FUN name:test1 visibility:public modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
VAR name:hello type:IrErrorType [val]
|
||||
ERROR_CALL 'Unresolved reference: <Unresolved name: Runnable>#' type=IrErrorType
|
||||
FUN_EXPR type=IrErrorType origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:IrErrorType
|
||||
VAR name:hello type:java.lang.Runnable [val]
|
||||
CALL 'public final fun Runnable (block: kotlin.Function0<kotlin.Unit>): java.lang.Runnable declared in java.lang' type=java.lang.Runnable origin=null
|
||||
block: FUN_EXPR type=kotlin.Function0<kotlin.Unit> origin=LAMBDA
|
||||
FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.Unit
|
||||
BLOCK_BODY
|
||||
ERROR_CALL 'Unresolved reference: println#' type=IrErrorType
|
||||
CONST String type=IrErrorType value="Hello, world!"
|
||||
ERROR_CALL 'Unresolved reference: <Inapplicable(PARAMETER_MAPPING_ERROR): [kotlin/run]>#' type=IrErrorType
|
||||
CALL 'public final fun println (message: kotlin.Any?): kotlin.Unit [inline] declared in kotlin.io' type=kotlin.Unit origin=null
|
||||
message: CONST String type=kotlin.String value="Hello, world!"
|
||||
CALL 'public abstract fun run (): kotlin.Unit declared in java.lang.Runnable' type=kotlin.Unit origin=null
|
||||
$this: GET_VAR 'val hello: java.lang.Runnable [val] declared in <root>.test1' type=java.lang.Runnable origin=null
|
||||
|
||||
Reference in New Issue
Block a user