[FIR] Add receiver for lambda in position of default argument

#KT-36905 Fixed
This commit is contained in:
Dmitriy Novozhilov
2020-03-02 11:54:55 +03:00
parent c12fb1e069
commit 7ee125e1ad
10 changed files with 73 additions and 61 deletions
@@ -542,7 +542,10 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
) )
af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null) af = af.transformValueParameters(ImplicitToErrorTypeTransformer, null)
val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef val bodyExpectedType = returnTypeRefFromResolvedAtom ?: expectedTypeRef
af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction val labelName = af.label?.name?.let { Name.identifier(it) }
withLabelAndReceiverType(labelName, af, af.receiverTypeRef?.coneTypeSafe()) {
af = transformFunction(af, withExpectedType(bodyExpectedType)).single as FirAnonymousFunction
}
// To separate function and separate commit // To separate function and separate commit
val writer = FirCallCompletionResultsWriterTransformer( val writer = FirCallCompletionResultsWriterTransformer(
session, session,
@@ -601,49 +604,58 @@ class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransformer)
private inline fun <T> withLabelAndReceiverType( private inline fun <T> withLabelAndReceiverType(
labelName: Name?, labelName: Name?,
owner: FirDeclaration, owner: FirDeclaration,
type: ConeKotlinType, type: ConeKotlinType?,
block: () -> T block: () -> T
): T { ): T {
val implicitCompanionValues = mutableListOf<ImplicitReceiverValue<*>>() val implicitCompanionValues: List<ImplicitReceiverValue<*>>
val implicitReceiverValue = when (owner) { if (type != null) {
is FirClass<*> -> { implicitCompanionValues = mutableListOf()
// Questionable: performance val implicitReceiverValue = when (owner) {
(owner as? FirRegularClass)?.companionObject?.let { companion -> is FirClass<*> -> {
implicitCompanionValues += ImplicitDispatchReceiverValue( // Questionable: performance
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION (owner as? FirRegularClass)?.companionObject?.let { companion ->
)
}
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
superClass?.companionObject?.let { companion ->
implicitCompanionValues += ImplicitDispatchReceiverValue( implicitCompanionValues += ImplicitDispatchReceiverValue(
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION
) )
} }
lookupSuperTypes(owner, lookupInterfaces = false, deep = true, useSiteSession = session).mapNotNull {
val superClass = (it as? ConeClassLikeType)?.lookupTag?.toSymbol(session)?.fir as? FirRegularClass
superClass?.companionObject?.let { companion ->
implicitCompanionValues += ImplicitDispatchReceiverValue(
companion.symbol, session, scopeSession, kind = ImplicitDispatchReceiverKind.COMPANION_FROM_SUPERTYPE
)
}
}
// ---
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
}
is FirFunction<*> -> {
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
}
is FirVariable<*> -> {
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession)
}
else -> {
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}")
} }
// ---
ImplicitDispatchReceiverValue(owner.symbol, type, session, scopeSession)
} }
is FirFunction<*> -> { for (implicitCompanionValue in implicitCompanionValues.asReversed()) {
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) implicitReceiverStack.add(null, implicitCompanionValue)
} }
is FirVariable<*> -> { implicitReceiverStack.add(labelName, implicitReceiverValue)
ImplicitExtensionReceiverValue(owner.symbol, type, session, scopeSession) } else {
} implicitCompanionValues = emptyList()
else -> { }
throw IllegalArgumentException("Incorrect label & receiver owner: ${owner.javaClass}") try {
return block()
} finally {
if (type != null) {
implicitReceiverStack.pop(labelName)
for (implicitCompanionValue in implicitCompanionValues) {
implicitReceiverStack.pop(null)
}
} }
} }
for (implicitCompanionValue in implicitCompanionValues.asReversed()) {
implicitReceiverStack.add(null, implicitCompanionValue)
}
implicitReceiverStack.add(labelName, implicitReceiverValue)
val result = block()
implicitReceiverStack.pop(labelName)
for (implicitCompanionValue in implicitCompanionValues) {
implicitReceiverStack.pop(null)
}
return result
} }
private fun storeVariableReturnType(variable: FirVariable<*>) { private fun storeVariableReturnType(variable: FirVariable<*>) {
@@ -0,0 +1,5 @@
fun test(
val f: String.() -> Int = { length }
): Int {
return "".f()
}
@@ -1,6 +1,6 @@
FILE: extensionLambdaInDefaultArgument.kt FILE: extensionLambdaInDefaultArgument.kt
public final fun test(f: R|kotlin/String.() -> kotlin/Int| = fun R|kotlin/String|.<anonymous>(): R|ERROR CLASS: Unresolved name: length| { public final fun test(f: R|kotlin/String.() -> kotlin/Int| = fun R|kotlin/String|.<anonymous>(): R|kotlin/Int| {
^ <Unresolved name: length># ^ this@R|special/anonymous|.R|kotlin/String.length|
} }
): R|kotlin/Int| { ): R|kotlin/Int| {
^test R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(String()) ^test R|<local>/f|.R|FakeOverride<kotlin/Function1.invoke: R|kotlin/Int|>|(String())
@@ -1,5 +0,0 @@
fun test(
val f: String.() -> Int = { <!UNRESOLVED_REFERENCE!>length<!> }
): Int {
return "".f()
}
@@ -380,6 +380,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt");
} }
@TestMetadata("extensionLambdaInDefaultArgument.kt")
public void testExtensionLambdaInDefaultArgument() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt");
}
@TestMetadata("fieldPlusAssign.kt") @TestMetadata("fieldPlusAssign.kt")
public void testFieldPlusAssign() throws Exception { public void testFieldPlusAssign() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt");
@@ -1352,11 +1357,6 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt"); runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt");
} }
@TestMetadata("extensionLambdaInDefaultArgument.kt")
public void testExtensionLambdaInDefaultArgument() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt");
}
@TestMetadata("javaAccessorConversion.kt") @TestMetadata("javaAccessorConversion.kt")
public void testJavaAccessorConversion() throws Exception { public void testJavaAccessorConversion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt"); runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt");
@@ -380,6 +380,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/defaultFromOverrides.kt");
} }
@TestMetadata("extensionLambdaInDefaultArgument.kt")
public void testExtensionLambdaInDefaultArgument() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/extensionLambdaInDefaultArgument.kt");
}
@TestMetadata("fieldPlusAssign.kt") @TestMetadata("fieldPlusAssign.kt")
public void testFieldPlusAssign() throws Exception { public void testFieldPlusAssign() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt"); runTest("compiler/fir/resolve/testData/resolve/arguments/fieldPlusAssign.kt");
@@ -1352,11 +1357,6 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt"); runTest("compiler/fir/resolve/testData/resolve/problems/definitelyNotNullAndOriginalType.kt");
} }
@TestMetadata("extensionLambdaInDefaultArgument.kt")
public void testExtensionLambdaInDefaultArgument() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/extensionLambdaInDefaultArgument.kt");
}
@TestMetadata("javaAccessorConversion.kt") @TestMetadata("javaAccessorConversion.kt")
public void testJavaAccessorConversion() throws Exception { public void testJavaAccessorConversion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt"); runTest("compiler/fir/resolve/testData/resolve/problems/javaAccessorConversion.kt");
@@ -9,7 +9,7 @@ fun test(param: String) {
val local_val = 4 val local_val = 4
val bar = fun B.(fun_param: Int) { val bar = fun B.(fun_param: Int) {
param.length param.length
<!UNRESOLVED_REFERENCE!>b_fun<!>() b_fun()
val inner_bar = local_val + fun_param val inner_bar = local_val + fun_param
<!UNRESOLVED_REFERENCE!>bar<!> <!UNRESOLVED_REFERENCE!>bar<!>
+1 -1
View File
@@ -4,7 +4,7 @@ fun test() {
val a: (Int?).() -> Unit = a@{ val a: (Int?).() -> Unit = a@{
if (this != null) { if (this != null) {
val b: String.() -> Unit = { val b: String.() -> Unit = {
this@a.<!UNRESOLVED_REFERENCE!>times<!>(5) // a@ Unresolved this@a.times(5) // a@ Unresolved
} }
} }
} }
@@ -2,15 +2,15 @@
fun test() { fun test() {
(fun Foo.() { (fun Foo.() {
<!UNRESOLVED_REFERENCE!>bar<!>() bar()
(fun Barr.() { (fun Barr.() {
this.<!UNRESOLVED_REFERENCE!>bar<!>() this.bar()
<!UNRESOLVED_REFERENCE!>bar<!>() bar()
}) })
}) })
(fun Barr.() { (fun Barr.() {
this.<!UNRESOLVED_REFERENCE!>bar<!>() this.bar()
<!UNRESOLVED_REFERENCE!>bar<!>() bar()
}) })
} }
@@ -5,14 +5,14 @@ class A(val a:Int) {
fun Byte.xx() : Double.() -> Any { fun Byte.xx() : Double.() -> Any {
checkSubtype<Byte>(this) checkSubtype<Byte>(this)
val a: Double.() -> Unit = { val a: Double.() -> Unit = {
<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Double>(this) checkSubtype<Double>(this)
checkSubtype<Byte>(this@xx) checkSubtype<Byte>(this@xx)
checkSubtype<B>(this@B) checkSubtype<B>(this@B)
checkSubtype<A>(this@A) checkSubtype<A>(this@A)
} }
val b: Double.() -> Unit = a@{ <!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Double>(this@a) + checkSubtype<Byte>(this@xx) } val b: Double.() -> Unit = a@{ checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx) }
val c = a@{ -> this@a + checkSubtype<Byte>(this@xx) } val c = a@{ -> this@a + checkSubtype<Byte>(this@xx) }
return (a@{<!INAPPLICABLE_CANDIDATE!>checkSubtype<!><Double>(this@a) + checkSubtype<Byte>(this@xx)}) return (a@{checkSubtype<Double>(this@a) + checkSubtype<Byte>(this@xx)})
} }
} }
} }