[FIR] Fix resolving of single underscore _

Now compiler throws `UNRESOLVED_REFERENCE` here:

```
val boo = { _: Exception -> `_`.stackTrace }
```
This commit is contained in:
Ivan Kochurkin
2021-07-23 18:18:13 +03:00
committed by Space
parent 8bfaa39a5c
commit 1a40164ef0
14 changed files with 87 additions and 44 deletions
+2 -2
View File
@@ -13,12 +13,12 @@ FILE: cast.kt
}
public get(): R|() -> kotlin/Unit|
public final val h: R|(kotlin/String) -> kotlin/Boolean| = fun <anonymous>(_: R|kotlin/String|): R|kotlin/Boolean| <inline=Unknown> {
public final val h: R|(kotlin/String) -> kotlin/Boolean| = fun <anonymous>(<unused var>: R|kotlin/String|): R|kotlin/Boolean| <inline=Unknown> {
^ Boolean(false)
}
public get(): R|(kotlin/String) -> kotlin/Boolean|
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(_: <ERROR TYPE REF: No type for parameter>): R|kotlin/Boolean| <inline=Unknown> {
public final val hError: R|(ERROR CLASS: No type for parameter) -> kotlin/Boolean| = fun <anonymous>(<unused var>: <ERROR TYPE REF: No type for parameter>): R|kotlin/Boolean| <inline=Unknown> {
^ Boolean(true)
}
@@ -19,7 +19,7 @@ FILE: delegateTypeMismatch.kt
public get(): R|kotlin/Boolean|
private final fun <T> property(initialValue: R|T|): R|kotlin/properties/ReadWriteProperty<A, T>| {
^property Q|kotlin/properties/Delegates|.R|kotlin/properties/Delegates.vetoable|<R|T|>(R|<local>/initialValue|, <L> = vetoable@fun <anonymous>(_: R|@R|kotlin/ParameterName|(name = String(property)) kotlin/reflect/KProperty<*>|, _: R|T|, _: R|T|): R|kotlin/Boolean| <inline=CrossInline, kind=UNKNOWN> {
^property Q|kotlin/properties/Delegates|.R|kotlin/properties/Delegates.vetoable|<R|T|>(R|<local>/initialValue|, <L> = vetoable@fun <anonymous>(<unused var>: R|@R|kotlin/ParameterName|(name = String(property)) kotlin/reflect/KProperty<*>|, <unused var>: R|T|, <unused var>: R|T|): R|kotlin/Boolean| <inline=CrossInline, kind=UNKNOWN> {
^ when () {
this@R|/A|.R|/A.isLocked| -> {
throw R|java/lang/IllegalStateException.IllegalStateException|(String(Cannot modify readonly DescriptorRendererOptions))
@@ -1,6 +1,6 @@
FILE: MapCompute.kt
public final fun <D> R|kotlin/collections/MutableMap<kotlin/String, kotlin/collections/MutableSet<D>>|.initAndAdd(key: R|kotlin/String|, value: R|D|): R|kotlin/Unit| {
this@R|/initAndAdd|.R|SubstitutionOverride<kotlin/collections/MutableMap.compute: R|kotlin/collections/MutableSet<D>?|>|(R|<local>/key|, <L> = compute@fun <anonymous>(_: R|ft<kotlin/String, kotlin/String?>|, maybeValues: R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>|): R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>| <inline=NoInline> {
this@R|/initAndAdd|.R|SubstitutionOverride<kotlin/collections/MutableMap.compute: R|kotlin/collections/MutableSet<D>?|>|(R|<local>/key|, <L> = compute@fun <anonymous>(<unused var>: R|ft<kotlin/String, kotlin/String?>|, maybeValues: R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>|): R|ft<kotlin/collections/MutableSet<D>, kotlin/collections/MutableSet<D>?>| <inline=NoInline> {
lval setOfValues: R|kotlin/collections/MutableSet<D>| = R|<local>/maybeValues| ?: R|kotlin/collections/mutableSetOf|<R|D|>()
R|<local>/setOfValues|.R|SubstitutionOverride<kotlin/collections/MutableSet.add: R|kotlin/Boolean|>|(R|<local>/value|)
^ R|<local>/setOfValues|
@@ -2009,10 +2009,13 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseValueParameterList
*/
fun convertValueParameters(valueParameters: LighterASTNode): List<ValueParameter> {
fun convertValueParameters(
valueParameters: LighterASTNode,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
): List<ValueParameter> {
return valueParameters.forEachChildrenReturnList { node, container ->
when (node.tokenType) {
VALUE_PARAMETER -> container += convertValueParameter(node)
VALUE_PARAMETER -> container += convertValueParameter(node, valueParameterDeclaration)
}
}
}
@@ -2020,7 +2023,10 @@ class DeclarationsConverter(
/**
* @see org.jetbrains.kotlin.parsing.KotlinParsing.parseValueParameter
*/
fun convertValueParameter(valueParameter: LighterASTNode): ValueParameter {
fun convertValueParameter(
valueParameter: LighterASTNode,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
): ValueParameter {
var modifiers = Modifier()
var isVal = false
var isVar = false
@@ -2040,7 +2046,7 @@ class DeclarationsConverter(
}
}
val name = identifier.nameAsSafeName()
val name = convertValueParameterName(identifier.nameAsSafeName(), identifier, valueParameterDeclaration)
val firValueParameter = buildValueParameter {
source = valueParameter.toFirSourceElement()
moduleData = baseModuleData
@@ -125,7 +125,7 @@ class ExpressionsConverter(
var block: LighterASTNode? = null
lambdaExpression.getChildNodesByType(FUNCTION_LITERAL).first().forEachChildren {
when (it.tokenType) {
VALUE_PARAMETER_LIST -> valueParameterList += declarationsConverter.convertValueParameters(it)
VALUE_PARAMETER_LIST -> valueParameterList += declarationsConverter.convertValueParameters(it, ValueParameterDeclaration.LAMBDA)
BLOCK -> block = it
}
}
@@ -1174,7 +1174,8 @@ class ExpressionsConverter(
var blockNode: LighterASTNode? = null
catchClause.forEachChildren {
when (it.tokenType) {
VALUE_PARAMETER_LIST -> valueParameter = declarationsConverter.convertValueParameters(it).firstOrNull() ?: return null
VALUE_PARAMETER_LIST -> valueParameter = declarationsConverter.convertValueParameters(it, ValueParameterDeclaration.CATCH)
.firstOrNull() ?: return null
BLOCK -> blockNode = it
}
}
@@ -32,7 +32,10 @@ import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirQualifierPartImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeArgumentListImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection
import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.Name
@@ -173,8 +176,11 @@ open class RawFirBuilder(
ownerRegularClassTypeParametersCount: Int?,
): FirProperty = property.toFirProperty(ownerRegularOrAnonymousObjectSymbol, ownerRegularClassTypeParametersCount)
open fun convertValueParameter(valueParameter: KtParameter, defaultTypeRef: FirTypeRef? = null): FirValueParameter =
valueParameter.toFirValueParameter(defaultTypeRef)
open fun convertValueParameter(
valueParameter: KtParameter,
defaultTypeRef: FirTypeRef? = null,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
): FirValueParameter = valueParameter.toFirValueParameter(defaultTypeRef, valueParameterDeclaration)
private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef =
convertSafe() ?: buildImplicitTypeRef {
@@ -444,8 +450,11 @@ open class RawFirBuilder(
}
}
private fun KtParameter.toFirValueParameter(defaultTypeRef: FirTypeRef? = null): FirValueParameter {
val name = nameAsSafeName
private fun KtParameter.toFirValueParameter(
defaultTypeRef: FirTypeRef? = null,
valueParameterDeclaration: ValueParameterDeclaration = ValueParameterDeclaration.OTHER
): FirValueParameter {
val name = convertValueParameterName(nameAsSafeName, nameIdentifier?.node?.text, valueParameterDeclaration)
return buildValueParameter {
source = toFirSourceElement()
moduleData = baseModuleData
@@ -1248,7 +1257,7 @@ open class RawFirBuilder(
val typeRef = valueParameter.typeReference?.convertSafe() ?: buildImplicitTypeRef {
source = implicitTypeRefSource
}
convertValueParameter(valueParameter, typeRef)
convertValueParameter(valueParameter, typeRef, ValueParameterDeclaration.LAMBDA)
}
}
val expressionSource = expression.toFirSourceElement()
@@ -1717,7 +1726,12 @@ open class RawFirBuilder(
tryBlock = expression.tryBlock.toFirBlock()
finallyBlock = expression.finallyBlock?.finalExpression?.toFirBlock()
for (clause in expression.catchClauses) {
val parameter = clause.catchParameter?.let { convertValueParameter(it) } ?: continue
val parameter = clause.catchParameter?.let {
convertValueParameter(
it,
valueParameterDeclaration = ValueParameterDeclaration.CATCH
)
} ?: continue
catches += buildCatch {
source = clause.toFirSourceElement()
this.parameter = parameter
@@ -2376,3 +2390,4 @@ enum class PsiHandlingMode {
*/
IDE;
}
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.builder
import com.intellij.psi.tree.IElementType
import org.jetbrains.kotlin.KtNodeTypes.*
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.*
@@ -35,6 +36,7 @@ import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.CallableId
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.parsing.*
import org.jetbrains.kotlin.psi.KtPsiUtil
import org.jetbrains.kotlin.types.ConstantValueKind
@@ -1234,9 +1236,8 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
return if (valueParameterDeclaration == ValueParameterDeclaration.LAMBDA && rawName == "_"
||
valueParameterDeclaration == ValueParameterDeclaration.CATCH &&
baseSession.sessionProvider != null &&
baseSession.languageVersionSettings.supportsFeature(LanguageFeature.ForbidReferencingToUnderscoreNamedParameterOfCatchBlock) &&
safeName.asString() == "_"
safeName.asString() == "_" &&
baseSession.safeLanguageVersionSettings?.supportsFeature(LanguageFeature.ForbidReferencingToUnderscoreNamedParameterOfCatchBlock) == true
) {
SpecialNames.UNDERSCORE_FOR_UNUSED_VAR
} else {
@@ -1252,4 +1253,10 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
val ITERATOR_NAME = Name.special("<iterator>")
}
enum class ValueParameterDeclaration {
OTHER,
LAMBDA,
CATCH
}
}
@@ -39,6 +39,7 @@ import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
import org.jetbrains.kotlin.fir.types.coneType
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.name.SpecialNames.UNDERSCORE_FOR_UNUSED_VAR
class BodyResolveContext(
val returnTypeCalculator: ReturnTypeCalculator,
@@ -612,7 +613,9 @@ class BodyResolveContext(
valueParameter: FirValueParameter,
f: () -> T
): T {
storeVariable(valueParameter)
if (!valueParameter.name.isSpecial || valueParameter.name != UNDERSCORE_FOR_UNUSED_VAR) {
storeVariable(valueParameter)
}
return withContainer(valueParameter, f)
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -12,5 +12,10 @@ class FirLanguageSettingsComponent(val languageVersionSettings: LanguageVersionS
private val FirSession.languageSettingsComponent: FirLanguageSettingsComponent by FirSession.sessionComponentAccessor()
private val FirSession.safeLanguageSettingsComponent: FirLanguageSettingsComponent? by FirSession.nullableSessionComponentAccessor()
val FirSession.languageVersionSettings: LanguageVersionSettings
get() = languageSettingsComponent.languageVersionSettings
val FirSession.safeLanguageVersionSettings: LanguageVersionSettings?
get() = safeLanguageSettingsComponent?.languageVersionSettings
@@ -5,35 +5,35 @@ fun foobar(block: (Double) -> Unit) { }
fun bar() {
foo { _, b ->
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
b checkType { _<String>() }
}
foo { a, _ ->
a checkType { _<Int>() }
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
}
foo { _, _ ->
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
}
foo { _: Int, b: String ->
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
b checkType { _<String>() }
}
foo { a: Int, _: String ->
a checkType { _<Int>() }
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
}
foo { _: Int, _: String ->
_.hashCode()
<!UNRESOLVED_REFERENCE!>_<!>.hashCode()
}
foo { `_`, _ ->
_ checkType { <!INAPPLICABLE_CANDIDATE!>_<!><Int>() }
_ checkType { _<Int>() }
}
foo { _, `_` ->
@@ -15,7 +15,7 @@ fun foo() {
val x2 = {
val x3 = { y: Int ->
val x4 = { _: Int ->
`_`
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>
}
<!RESOLVED_TO_UNDERSCORE_NAMED_CATCH_PARAMETER!>`_`<!>
}
@@ -52,7 +52,7 @@ fun foo() {
try {
TODO()
} catch (x: Exception) {
`_`.stackTrace
<!UNRESOLVED_REFERENCE!>`_`<!>.stackTrace
}
}
}
@@ -6,7 +6,7 @@ fun foo() {
try {
TODO()
} catch (_: Exception) {
`_`.stackTrace
<!UNRESOLVED_REFERENCE!>`_`<!>.stackTrace
}
try {
TODO()
@@ -15,22 +15,22 @@ fun foo() {
val x2 = {
val x3 = { y: Int ->
val x4 = { _: Int ->
`_`
<!UNRESOLVED_REFERENCE!>`_`<!>
}
`_`
<!UNRESOLVED_REFERENCE!>`_`<!>
}
`_`
<!UNRESOLVED_REFERENCE!>`_`<!>
10
}
fun bar(x: Exception = `_`) {}
fun bar(x: Exception = <!UNRESOLVED_REFERENCE!>`_`<!>) {}
class Bar(`_`: Exception = <!UNINITIALIZED_PARAMETER!>`_`<!>) {
inner class Bar2(x: Exception = `_`) { }
inner class Bar2(x: Exception = <!UNRESOLVED_REFERENCE!>`_`<!>) { }
}
}
} catch (_: Exception) {
`_`.stackTrace
val y1 = <!UNDERSCORE_USAGE_WITHOUT_BACKTICKS!>_<!>
val y2 = (`_`)
<!UNRESOLVED_REFERENCE!>`_`<!>.stackTrace
val y1 = <!UNDERSCORE_USAGE_WITHOUT_BACKTICKS, UNRESOLVED_REFERENCE!>_<!>
val y2 = (<!UNRESOLVED_REFERENCE!>`_`<!>)
}
try {
TODO()
@@ -38,7 +38,7 @@ fun foo() {
try {
TODO()
} catch (x: Exception) {
`_`.stackTrace
<!UNRESOLVED_REFERENCE!>`_`<!>.stackTrace
}
}
val boo1 = { `_`: Exception ->
@@ -52,7 +52,7 @@ fun foo() {
try {
TODO()
} catch (x: Exception) {
`_`.stackTrace
<!UNRESOLVED_REFERENCE!>`_`<!>.stackTrace
}
}
}
@@ -22,6 +22,7 @@ import org.jetbrains.annotations.Nullable;
public class SpecialNames {
public static final Name NO_NAME_PROVIDED = Name.special("<no name provided>");
public static final Name ROOT_PACKAGE = Name.special("<root package>");
public static final Name UNDERSCORE_FOR_UNUSED_VAR = Name.special("<unused var>");
public static final Name DEFAULT_NAME_FOR_COMPANION_OBJECT = Name.identifier("Companion");
@@ -95,12 +95,17 @@ internal class RawFirNonLocalDeclarationBuilder private constructor(
)
}
override fun convertValueParameter(valueParameter: KtParameter, defaultTypeRef: FirTypeRef?): FirValueParameter {
override fun convertValueParameter(
valueParameter: KtParameter,
defaultTypeRef: FirTypeRef?,
valueParameterDeclaration: ValueParameterDeclaration
): FirValueParameter {
val replacementParameter = replacementApplier?.tryReplace(valueParameter) ?: valueParameter
check(replacementParameter is KtParameter)
return super.convertValueParameter(
valueParameter = replacementParameter,
defaultTypeRef = defaultTypeRef
defaultTypeRef = defaultTypeRef,
valueParameterDeclaration = valueParameterDeclaration
)
}
}