Skip to content

Commit fa5b17a

Browse files
[C15] Kotlin: emit _ for source underscore locals under K2
A source underscore variable (an unused `_` in a `catch (_: E)` clause or a `val _ = ...` discard) is named differently by the two frontends: - K1 keeps the source spelling `_`. - K2 assigns the synthetic `SpecialNames.UNDERSCORE_FOR_UNUSED_VAR`, which renders as `<unused var>`. Decision (D15): adopt the K1 behaviour. `_` is the actual source token, so it is the more intuitive and source-faithful name; it also keeps the local variable name consistent with the corresponding value-parameter case, where a prior fix already normalises the underscore setter parameter to `_`. `extractVariableExpr` now maps a variable whose IR name is `SpecialNames.UNDERSCORE_FOR_UNUSED_VAR` to `_` before writing `localvars`. The check is on the special name rather than a raw string so it is robust across compiler versions, and it only fires for the frontend-synthesised unused-variable name, leaving all other locals untouched. Full dual-suite relearn: all 3333 tests pass. The only changed expected row is in query-tests/UnderscoreIdentifier, where the K2 catch parameter row converges from `Exception <unused var>` to `Exception _`, matching K1. The remaining divergence in that file (the destructuring container `<destruct>` vs `tmp0_container`) is a separate naming/location issue tracked under C14. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 2121d74 commit fa5b17a

2 files changed

Lines changed: 9 additions & 2 deletions

File tree

java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
5151
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
5252
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
5353
import org.jetbrains.kotlin.name.FqName
54+
import org.jetbrains.kotlin.name.SpecialNames
5455
import org.jetbrains.kotlin.types.Variance
5556
import org.jetbrains.kotlin.util.OperatorNameConventions
5657
import org.jetbrains.kotlin.psi.KtClass
@@ -3489,7 +3490,13 @@ open class KotlinFileExtractor(
34893490
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr>()
34903491
val locId = getPsiBasedLocation(v) ?: tw.getLocation(getVariableLocationProvider(v))
34913492
val type = useType(v.type)
3492-
tw.writeLocalvars(varId, v.name.asString(), type.javaResult.id, exprId)
3493+
// K2 names a source `_` (unused) local/catch variable with the synthetic
3494+
// SpecialNames.UNDERSCORE_FOR_UNUSED_VAR (`<unused var>`), whereas K1 keeps the
3495+
// source spelling `_`. Emit `_` so both frontends produce the same, source-faithful
3496+
// name (D15).
3497+
val varName =
3498+
if (v.name == SpecialNames.UNDERSCORE_FOR_UNUSED_VAR) "_" else v.name.asString()
3499+
tw.writeLocalvars(varId, varName, type.javaResult.id, exprId)
34933500
tw.writeLocalvarsKotlinType(varId, type.kotlinResult.id)
34943501
tw.writeHasLocation(varId, locId)
34953502
tw.writeExprs_localvariabledeclexpr(exprId, type.javaResult.id, parent, idx)

java/ql/test-kotlin2/query-tests/UnderscoreIdentifier/test.expected

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@
44
| Test.kt:6:9:6:26 | Pair<Integer,Integer> p |
55
| Test.kt:7:9:7:26 | Pair<Integer,Integer> <destruct> |
66
| Test.kt:7:14:7:18 | int first |
7-
| Test.kt:8:14:8:25 | Exception <unused var> |
7+
| Test.kt:8:14:8:25 | Exception _ |

0 commit comments

Comments
 (0)