From f1ccb6bda0701f3657f21e17c7eae0844c147296 Mon Sep 17 00:00:00 2001 From: Anders Fugmann Date: Mon, 13 Jul 2026 15:15:10 +0200 Subject: [PATCH] Kotlin: converge delegated-setter value-parameter name to `` The synthetic setter of a *delegated* property has one implicit value parameter. The K2 frontend names it `` (`SpecialNames.IMPLICIT_SETTER_PARAMETER`), matching what it does for an ordinary member property's setter. The K1 frontend instead names a delegated property's setter parameter `value`, diverging from both K2 and from its own naming of member-property setters. This produced two divergent rows per delegated `var` between test-kotlin1 and test-kotlin2 (the `[Parameter]` declaration and the `[VarAccess]` that reads it back inside the generated setter body): - [Parameter] value -> [Parameter] - [VarAccess] value -> [VarAccess] Decision: adopt the K2 name. `` is the canonical implicit setter-parameter name the frontend already uses everywhere else, so it is the more consistent and less surprising choice; a bare `value` is indistinguishable from a user-written parameter of that name. `getConvergedValueParameterName` renames the parameter only when its enclosing function has origin `DELEGATED_PROPERTY_ACCESSOR` *and* its K1 source name is `value`. The origin guard restricts the rename to the fully synthetic delegated accessors (a hand-written `ReadWriteProperty.setValue` has origin `DEFINED`, so its `value` parameter is untouched); the name guard restricts it to the setter value parameter, leaving the accessor's receiver parameters (`` for an extension property, `` for a member property) unchanged. Under K2 the setter parameter is already `` and receivers are ``, so nothing matches and the canonical K2 output is byte-for-byte unchanged (only the three K1 setters in test-kotlin1 relearn). The literal `` is used because `SpecialNames.IMPLICIT_SETTER_PARAMETER` is not resolvable in every compiler version the extractor is built against. Relearned both suites (all 3333 tests pass); only the three delegated setters in test-kotlin1 (delegatedProperties.kt lines 19, 34, 82) change. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../src/main/kotlin/KotlinFileExtractor.kt | 32 ++++++++++++++++++- .../library-tests/exprs/PrintAst.expected | 12 +++---- .../library-tests/exprs/exprs.expected | 6 ++-- 3 files changed, 40 insertions(+), 10 deletions(-) diff --git a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt index 8cb27040881..320cae7ff09 100644 --- a/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt +++ b/java/kotlin-extractor/src/main/kotlin/KotlinFileExtractor.kt @@ -1439,7 +1439,7 @@ open class KotlinFileExtractor( return extractValueParameter( id, substitutedType, - vp.name.asString(), + getConvergedValueParameterName(vp), location, parent, idx, @@ -3168,6 +3168,36 @@ open class KotlinFileExtractor( return tw.getLocation(keyword.startOffset, vp.endOffset) } + /** + * Returns the name to record for a value parameter, converging the two frontends where they + * disagree. + * + * A property's synthetic setter has a single implicit value parameter. The K2 frontend names + * it ``; the K1 frontend does the same for a + * member property's setter but names a *delegated* property's setter parameter `value`. That + * parameter is always compiler-synthesised (a delegated-property accessor carries no + * source-written parameters), so renaming it can never affect a user-written `value` parameter + * (for example the `value` parameter of a hand-written `ReadWriteProperty.setValue`, whose + * function has origin `DEFINED`). We therefore converge the delegated-setter parameter onto the + * canonical `` name (the `SpecialNames.IMPLICIT_SETTER_PARAMETER` constant is not present + * in every supported compiler version, so the literal is used directly). + * + * The rename is guarded on the K1 source name `value` so it targets *only* the setter value + * parameter: a delegated accessor's other parameters are receivers (`` for an extension + * property, `` for a member property), which must keep their names. Under K2 + * the setter parameter is already `` and the receivers are ``, so none match and + * the canonical K2 output is left untouched. + */ + private fun getConvergedValueParameterName(vp: IrValueParameter): String { + if ( + (vp.parent as? IrFunction)?.origin == IrDeclarationOrigin.DELEGATED_PROPERTY_ACCESSOR && + vp.name.asString() == "value" + ) { + return "" + } + return vp.name.asString() + } + /** * Returns the PSI-based location for a *synthesised* value parameter that has no source * token of its own, matching the span the K2 frontend emits natively, or null to leave the diff --git a/java/ql/test-kotlin1/library-tests/exprs/PrintAst.expected b/java/ql/test-kotlin1/library-tests/exprs/PrintAst.expected index 45bfea8c128..d9d2100a60e 100644 --- a/java/ql/test-kotlin1/library-tests/exprs/PrintAst.expected +++ b/java/ql/test-kotlin1/library-tests/exprs/PrintAst.expected @@ -294,7 +294,7 @@ delegatedProperties.kt: # 19| 2: [Method] # 19| 3: [TypeAccess] Unit #-----| 4: (Parameters) -# 19| 0: [Parameter] value +# 19| 0: [Parameter] # 19| 0: [TypeAccess] int # 19| 5: [BlockStmt] { ... } # 19| 0: [ReturnStmt] return ... @@ -328,7 +328,7 @@ delegatedProperties.kt: # 19| 0: [VarAccess] a0 # 19| -3: [TypeAccess] KMutableProperty0 # 19| 0: [TypeAccess] Integer -# 19| 2: [VarAccess] value +# 19| 2: [VarAccess] # 20| 1: [ExprStmt] ; # 20| 0: [MethodCall] println(...) # 20| -1: [TypeAccess] ConsoleKt @@ -538,7 +538,7 @@ delegatedProperties.kt: # 34| 2: [Method] # 34| 3: [TypeAccess] Unit #-----| 4: (Parameters) -# 34| 0: [Parameter] value +# 34| 0: [Parameter] # 34| 0: [TypeAccess] int # 34| 5: [BlockStmt] { ... } # 34| 0: [ReturnStmt] return ... @@ -572,7 +572,7 @@ delegatedProperties.kt: # 34| 0: [VarAccess] a0 # 34| -3: [TypeAccess] KMutableProperty0 # 34| 0: [TypeAccess] Integer -# 34| 2: [VarAccess] value +# 34| 2: [VarAccess] # 36| 7: [ExprStmt] ; # 36| 0: [MethodCall] println(...) # 36| -1: [TypeAccess] ConsoleKt @@ -1848,7 +1848,7 @@ delegatedProperties.kt: # 82| 2: [Method] # 82| 3: [TypeAccess] Unit #-----| 4: (Parameters) -# 82| 0: [Parameter] value +# 82| 0: [Parameter] # 82| 0: [TypeAccess] int # 82| 5: [BlockStmt] { ... } # 82| 0: [ReturnStmt] return ... @@ -1884,7 +1884,7 @@ delegatedProperties.kt: # 82| 0: [VarAccess] a0 # 82| -3: [TypeAccess] KMutableProperty0 # 82| 0: [TypeAccess] Integer -# 82| 3: [VarAccess] value +# 82| 3: [VarAccess] # 83| 1: [ExprStmt] ; # 83| 0: [MethodCall] fn(...) # 83| -1: [ThisAccess] this diff --git a/java/ql/test-kotlin1/library-tests/exprs/exprs.expected b/java/ql/test-kotlin1/library-tests/exprs/exprs.expected index 4a69ab873a0..7b5c952d6f3 100644 --- a/java/ql/test-kotlin1/library-tests/exprs/exprs.expected +++ b/java/ql/test-kotlin1/library-tests/exprs/exprs.expected @@ -58,6 +58,7 @@ | delegatedProperties.kt:19:34:19:51 | ...::... | delegatedProperties.kt:19:9:19:51 | | PropertyRefExpr | | delegatedProperties.kt:19:34:19:51 | (...) | delegatedProperties.kt:19:34:19:51 | get | MethodCall | | delegatedProperties.kt:19:34:19:51 | (...) | delegatedProperties.kt:19:34:19:51 | get | MethodCall | +| delegatedProperties.kt:19:34:19:51 | | delegatedProperties.kt:19:9:19:51 | | VarAccess | | delegatedProperties.kt:19:34:19:51 | (...) | delegatedProperties.kt:19:34:19:51 | set | MethodCall | | delegatedProperties.kt:19:34:19:51 | (...) | delegatedProperties.kt:19:34:19:51 | set | MethodCall | | delegatedProperties.kt:19:34:19:51 | Integer | delegatedProperties.kt:19:9:19:51 | | TypeAccess | @@ -82,7 +83,6 @@ | delegatedProperties.kt:19:34:19:51 | setValue(...) | delegatedProperties.kt:19:9:19:51 | | MethodCall | | delegatedProperties.kt:19:34:19:51 | this | delegatedProperties.kt:19:34:19:51 | invoke | ThisAccess | | delegatedProperties.kt:19:34:19:51 | this | delegatedProperties.kt:19:34:19:51 | invoke | ThisAccess | -| delegatedProperties.kt:19:34:19:51 | value | delegatedProperties.kt:19:9:19:51 | | VarAccess | | delegatedProperties.kt:19:34:19:51 | varResource1$delegate | delegatedProperties.kt:19:9:19:51 | | VarAccess | | delegatedProperties.kt:19:34:19:51 | varResource1$delegate | delegatedProperties.kt:19:9:19:51 | | VarAccess | | delegatedProperties.kt:20:9:20:29 | ConsoleKt | delegatedProperties.kt:18:5:40:5 | fn | TypeAccess | @@ -166,6 +166,7 @@ | delegatedProperties.kt:34:31:34:48 | ...::... | delegatedProperties.kt:34:9:34:48 | | PropertyRefExpr | | delegatedProperties.kt:34:31:34:48 | (...) | delegatedProperties.kt:34:31:34:48 | get | MethodCall | | delegatedProperties.kt:34:31:34:48 | (...) | delegatedProperties.kt:34:31:34:48 | get | MethodCall | +| delegatedProperties.kt:34:31:34:48 | | delegatedProperties.kt:34:9:34:48 | | VarAccess | | delegatedProperties.kt:34:31:34:48 | (...) | delegatedProperties.kt:34:31:34:48 | set | MethodCall | | delegatedProperties.kt:34:31:34:48 | (...) | delegatedProperties.kt:34:31:34:48 | set | MethodCall | | delegatedProperties.kt:34:31:34:48 | Integer | delegatedProperties.kt:34:9:34:48 | | TypeAccess | @@ -193,7 +194,6 @@ | delegatedProperties.kt:34:31:34:48 | setValue(...) | delegatedProperties.kt:34:9:34:48 | | MethodCall | | delegatedProperties.kt:34:31:34:48 | this | delegatedProperties.kt:34:31:34:48 | invoke | ThisAccess | | delegatedProperties.kt:34:31:34:48 | this | delegatedProperties.kt:34:31:34:48 | invoke | ThisAccess | -| delegatedProperties.kt:34:31:34:48 | value | delegatedProperties.kt:34:9:34:48 | | VarAccess | | delegatedProperties.kt:36:9:36:29 | ConsoleKt | delegatedProperties.kt:18:5:40:5 | fn | TypeAccess | | delegatedProperties.kt:36:9:36:29 | println(...) | delegatedProperties.kt:18:5:40:5 | fn | MethodCall | | delegatedProperties.kt:36:17:36:28 | getVarResource0(...) | delegatedProperties.kt:18:5:40:5 | fn | MethodCall | @@ -777,6 +777,7 @@ | delegatedProperties.kt:82:40:82:54 | | delegatedProperties.kt:82:40:82:54 | | VarAccess | | delegatedProperties.kt:82:40:82:54 | (...) | delegatedProperties.kt:82:40:82:54 | get | MethodCall | | delegatedProperties.kt:82:40:82:54 | (...) | delegatedProperties.kt:82:40:82:54 | get | MethodCall | +| delegatedProperties.kt:82:40:82:54 | | delegatedProperties.kt:82:9:82:54 | | VarAccess | | delegatedProperties.kt:82:40:82:54 | (...) | delegatedProperties.kt:82:40:82:54 | set | MethodCall | | delegatedProperties.kt:82:40:82:54 | (...) | delegatedProperties.kt:82:40:82:54 | set | MethodCall | | delegatedProperties.kt:82:40:82:54 | Integer | delegatedProperties.kt:81:5:84:5 | fn | TypeAccess | @@ -819,7 +820,6 @@ | delegatedProperties.kt:82:40:82:54 | this. | delegatedProperties.kt:82:40:82:54 | | VarAccess | | delegatedProperties.kt:82:40:82:54 | this. | delegatedProperties.kt:82:40:82:54 | get | VarAccess | | delegatedProperties.kt:82:40:82:54 | this. | delegatedProperties.kt:82:40:82:54 | set | VarAccess | -| delegatedProperties.kt:82:40:82:54 | value | delegatedProperties.kt:82:9:82:54 | | VarAccess | | delegatedProperties.kt:83:9:83:12 | fn(...) | delegatedProperties.kt:81:5:84:5 | fn | MethodCall | | delegatedProperties.kt:83:9:83:12 | this | delegatedProperties.kt:81:5:84:5 | fn | ThisAccess | | delegatedProperties.kt:87:1:87:46 | MyClass | file://:0:0:0:0 | | TypeAccess |