FIR: add & use hasExplicitParameterList to anonymous functions

#KT-49134 Fixed
This commit is contained in:
Mikhail Glukhikh
2021-10-15 16:26:37 +03:00
committed by teamcityserver
parent 9307757bb4
commit 29e4c299e7
20 changed files with 38 additions and 16 deletions
@@ -86,6 +86,7 @@ class FirMetadataSerializer(
returnTypeRef = function.returnTypeRef.approximated(toSuper = true, typeParameterSet)
receiverTypeRef = function.receiverTypeRef?.approximated(toSuper = false, typeParameterSet)
isLambda = (function as? FirAnonymousFunction)?.isLambda == true
hasExplicitParameterList = (function as? FirAnonymousFunction)?.hasExplicitParameterList == true
valueParameters.addAll(function.valueParameters.map {
buildValueParameterCopy(it) {
returnTypeRef = it.returnTypeRef.approximated(toSuper = false, typeParameterSet)
@@ -99,6 +99,7 @@ fun FirAnonymousFunction.copy(
this.receiverTypeRef = receiverTypeRef
symbol = this@copy.symbol
isLambda = this@copy.isLambda
hasExplicitParameterList = this@copy.hasExplicitParameterList
this.valueParameters.addAll(valueParameters)
this.body = body
this.annotations.addAll(annotations)
@@ -1548,6 +1548,7 @@ class DeclarationsConverter(
receiverTypeRef = receiverType
symbol = functionSymbol
isLambda = false
hasExplicitParameterList = true
label = context.getLastLabel(functionDeclaration)
val labelName = label?.name ?: context.calleeNamesForLambda.lastOrNull()?.identifier
target = FirFunctionTarget(labelName = labelName, isLambda = false)
@@ -125,10 +125,12 @@ class ExpressionsConverter(
private fun convertLambdaExpression(lambdaExpression: LighterASTNode): FirExpression {
val valueParameterList = mutableListOf<ValueParameter>()
var block: LighterASTNode? = null
var hasArrow = false
lambdaExpression.getChildNodesByType(FUNCTION_LITERAL).first().forEachChildren {
when (it.tokenType) {
VALUE_PARAMETER_LIST -> valueParameterList += declarationsConverter.convertValueParameters(it, ValueParameterDeclaration.LAMBDA)
BLOCK -> block = it
ARROW -> hasArrow = true
}
}
@@ -142,6 +144,7 @@ class ExpressionsConverter(
receiverTypeRef = implicitType
symbol = FirAnonymousFunctionSymbol()
isLambda = true
hasExplicitParameterList = hasArrow
label = context.getLastLabel(lambdaExpression) ?: context.calleeNamesForLambda.lastOrNull()?.let {
buildLabel {
source = expressionSource.fakeElement(FirFakeSourceElementKind.GeneratedLambdaLabel)
@@ -1223,6 +1223,7 @@ open class RawFirBuilder(
receiverTypeRef = receiverType
symbol = FirAnonymousFunctionSymbol()
isLambda = false
hasExplicitParameterList = true
label = context.getLastLabel(function)
labelName = label?.name ?: context.calleeNamesForLambda.lastOrNull()?.identifier
}
@@ -1338,6 +1339,7 @@ open class RawFirBuilder(
receiverTypeRef = receiverType
symbol = FirAnonymousFunctionSymbol()
isLambda = true
hasExplicitParameterList = expression.functionLiteral.arrow != null
val destructuringStatements = mutableListOf<FirStatement>()
for (valueParameter in literal.valueParameters) {
@@ -31,4 +31,6 @@ fun test(list: List<Int>) {
val simple = { }
val simpleWithArrow = { -> }
val another = { 42 }
@@ -23,5 +23,7 @@ FILE: lambda.kt
public? final? fun test(list: List<Int>): R|kotlin/Unit| { LAZY_BLOCK }
public? final? val simple: <implicit> = LAZY_EXPRESSION
public? get(): <implicit>
public? final? val simpleWithArrow: <implicit> = LAZY_EXPRESSION
public? get(): <implicit>
public? final? val another: <implicit> = LAZY_EXPRESSION
public? get(): <implicit>
@@ -70,6 +70,11 @@ FILE: lambda.kt
^ Unit
}
public? get(): <implicit>
public? final? val simpleWithArrow: <implicit> = fun <implicit>.<anonymous>(<no-parameters>)(): <implicit> <inline=Unknown> {
^ Unit
}
public? get(): <implicit>
public? final? val another: <implicit> = fun <implicit>.<anonymous>(): <implicit> <inline=Unknown> {
IntegerLiteral(42)
@@ -59,7 +59,7 @@ fun extractLambdaInfoFromFunctionalType(
var coerceFirstParameterToExtensionReceiver = false
val argumentValueParameters = argument.valueParameters
val parameters = if (argument.isLambda && argumentValueParameters.isEmpty() && expectedParameters.size < 2) {
val parameters = if (argument.isLambda && !argument.hasExplicitParameterList && expectedParameters.size < 2) {
expectedParameters // Infer existence of a parameter named `it` of an appropriate type.
} else {
if (duringCompletion &&
@@ -167,6 +167,7 @@ open class FirContractResolveTransformer(
receiverTypeRef = buildImplicitTypeRef()
symbol = FirAnonymousFunctionSymbol()
isLambda = true
hasExplicitParameterList = true
body = buildBlock {
contractDescription.rawEffects.forEach {
@@ -45,6 +45,7 @@ abstract class FirAnonymousFunction : FirFunction(), FirTypeParametersOwner {
abstract val invocationKind: EventOccurrencesRange?
abstract val inlineStatus: InlineStatus
abstract val isLambda: Boolean
abstract val hasExplicitParameterList: Boolean
abstract override val typeParameters: List<FirTypeParameter>
abstract val typeRef: FirTypeRef
@@ -59,6 +59,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
var invocationKind: EventOccurrencesRange? = null
var inlineStatus: InlineStatus = InlineStatus.Unknown
var isLambda: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
var hasExplicitParameterList: Boolean by kotlin.properties.Delegates.notNull<Boolean>()
val typeParameters: MutableList<FirTypeParameter> = mutableListOf()
var typeRef: FirTypeRef = FirImplicitTypeRefImpl(null)
@@ -82,6 +83,7 @@ class FirAnonymousFunctionBuilder : FirFunctionBuilder, FirAnnotationContainerBu
invocationKind,
inlineStatus,
isLambda,
hasExplicitParameterList,
typeParameters,
typeRef,
)
@@ -52,6 +52,7 @@ internal class FirAnonymousFunctionImpl(
override var invocationKind: EventOccurrencesRange?,
override var inlineStatus: InlineStatus,
override val isLambda: Boolean,
override val hasExplicitParameterList: Boolean,
override val typeParameters: MutableList<FirTypeParameter>,
override var typeRef: FirTypeRef,
) : FirAnonymousFunction() {
@@ -626,6 +626,12 @@ open class FirRenderer(builder: StringBuilder, protected val mode: RenderMode =
print(".")
}
print("<anonymous>")
if (anonymousFunction.valueParameters.isEmpty() &&
anonymousFunction.hasExplicitParameterList &&
anonymousFunction.returnTypeRef is FirImplicitTypeRef
) {
print("(<no-parameters>)")
}
anonymousFunction.valueParameters.renderParameters()
print(": ")
anonymousFunction.returnTypeRef.accept(this)
@@ -282,6 +282,7 @@ object NodeConfigurator : AbstractFieldConfigurator<FirTreeBuilder>(FirTreeBuild
isMutable = true
}
+booleanField("isLambda")
+booleanField("hasExplicitParameterList")
+typeParameters
+field(typeRef, withReplace = true)
}
@@ -24,9 +24,9 @@ fun test1() {
foo1 <!ARGUMENT_TYPE_MISMATCH!>{
x, <!CANNOT_INFER_PARAMETER_TYPE!>y<!> -> ""
}<!>
foo1 {
foo1 <!ARGUMENT_TYPE_MISMATCH!>{
-> <!ARGUMENT_TYPE_MISMATCH!>42<!>
}
}<!>
foo2 <!ARGUMENT_TYPE_MISMATCH!>{
@@ -1,8 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo(g: () -> Int) {}
fun foo(f: (Int) -> Int) {}
fun test() {
<!OVERLOAD_RESOLUTION_AMBIGUITY!>foo<!> { -> 42 }
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun foo(g: () -> Int) {}
@@ -130,7 +130,7 @@ fun test4() { // to non-extension lambda 2
}
open class A(a: () -> Unit) {
constructor(f: (String) -> Unit) : <!OVERLOAD_RESOLUTION_AMBIGUITY!>this<!>({ -> f("") })
constructor(f: (String) -> Unit) : this({ -> f("") })
}
class B: A({ s -> "1" })
@@ -2,14 +2,14 @@
package kt352
val f : (Any) -> Unit = { -> } //type mismatch
val f : (Any) -> Unit = <!INITIALIZER_TYPE_MISMATCH!>{ -> }<!> //type mismatch
fun foo() {
val f : (Any) -> Unit = { -> } //!!! no error
val f : (Any) -> Unit = <!INITIALIZER_TYPE_MISMATCH!>{ -> }<!> //!!! no error
}
class A() {
val f : (Any) -> Unit = { -> } //type mismatch
val f : (Any) -> Unit = <!INITIALIZER_TYPE_MISMATCH!>{ -> }<!> //type mismatch
}
//more tests
@@ -25,4 +25,4 @@ val testIt : (Any) -> Unit = {
if (it is String) {
doSmth(it)
}
}
}