Kotlin: converge delegated-setter value-parameter name to <set-?>

The synthetic setter of a *delegated* property has one implicit value
parameter. The K2 frontend names it `<set-?>`
(`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] <set-?>
    - [VarAccess] value        ->  [VarAccess] <set-?>

Decision: adopt the K2 name. `<set-?>` 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 (`<this>` for an extension property,
`<dispatchReceiver>` for a member property) unchanged. Under K2 the setter
parameter is already `<set-?>` and receivers are `<this>`, so nothing
matches and the canonical K2 output is byte-for-byte unchanged (only the
three K1 setters in test-kotlin1 relearn).

The literal `<set-?>` 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>
This commit is contained in:
Anders Fugmann
2026-07-13 15:15:10 +02:00
parent a17c88ab94
commit f1ccb6bda0
3 changed files with 40 additions and 10 deletions

View File

@@ -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 `<set-?>`; 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 `<set-?>` 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 (`<this>` for an extension
* property, `<dispatchReceiver>` for a member property), which must keep their names. Under K2
* the setter parameter is already `<set-?>` and the receivers are `<this>`, 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 "<set-?>"
}
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

View File

@@ -294,7 +294,7 @@ delegatedProperties.kt:
# 19| 2: [Method] <set-varResource1>
# 19| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 19| 0: [Parameter] value
# 19| 0: [Parameter] <set-?>
# 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<Integer>
# 19| 0: [TypeAccess] Integer
# 19| 2: [VarAccess] value
# 19| 2: [VarAccess] <set-?>
# 20| 1: [ExprStmt] <Expr>;
# 20| 0: [MethodCall] println(...)
# 20| -1: [TypeAccess] ConsoleKt
@@ -538,7 +538,7 @@ delegatedProperties.kt:
# 34| 2: [Method] <set-readWrite>
# 34| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 34| 0: [Parameter] value
# 34| 0: [Parameter] <set-?>
# 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<Integer>
# 34| 0: [TypeAccess] Integer
# 34| 2: [VarAccess] value
# 34| 2: [VarAccess] <set-?>
# 36| 7: [ExprStmt] <Expr>;
# 36| 0: [MethodCall] println(...)
# 36| -1: [TypeAccess] ConsoleKt
@@ -1848,7 +1848,7 @@ delegatedProperties.kt:
# 82| 2: [Method] <set-delegatedToMember3>
# 82| 3: [TypeAccess] Unit
#-----| 4: (Parameters)
# 82| 0: [Parameter] value
# 82| 0: [Parameter] <set-?>
# 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<Integer>
# 82| 0: [TypeAccess] Integer
# 82| 3: [VarAccess] value
# 82| 3: [VarAccess] <set-?>
# 83| 1: [ExprStmt] <Expr>;
# 83| 0: [MethodCall] fn(...)
# 83| -1: [ThisAccess] this

View File

@@ -58,6 +58,7 @@
| delegatedProperties.kt:19:34:19:51 | ...::... | delegatedProperties.kt:19:9:19:51 | <set-varResource1> | PropertyRefExpr |
| delegatedProperties.kt:19:34:19:51 | <get-varResource1>(...) | delegatedProperties.kt:19:34:19:51 | get | MethodCall |
| delegatedProperties.kt:19:34:19:51 | <get-varResource1>(...) | delegatedProperties.kt:19:34:19:51 | get | MethodCall |
| delegatedProperties.kt:19:34:19:51 | <set-?> | delegatedProperties.kt:19:9:19:51 | <set-varResource1> | VarAccess |
| delegatedProperties.kt:19:34:19:51 | <set-varResource1>(...) | delegatedProperties.kt:19:34:19:51 | set | MethodCall |
| delegatedProperties.kt:19:34:19:51 | <set-varResource1>(...) | delegatedProperties.kt:19:34:19:51 | set | MethodCall |
| delegatedProperties.kt:19:34:19:51 | Integer | delegatedProperties.kt:19:9:19:51 | <get-varResource1> | TypeAccess |
@@ -82,7 +83,6 @@
| delegatedProperties.kt:19:34:19:51 | setValue(...) | delegatedProperties.kt:19:9:19:51 | <set-varResource1> | 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 | <set-varResource1> | VarAccess |
| delegatedProperties.kt:19:34:19:51 | varResource1$delegate | delegatedProperties.kt:19:9:19:51 | <get-varResource1> | VarAccess |
| delegatedProperties.kt:19:34:19:51 | varResource1$delegate | delegatedProperties.kt:19:9:19:51 | <set-varResource1> | 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 | <set-readWrite> | PropertyRefExpr |
| delegatedProperties.kt:34:31:34:48 | <get-readWrite>(...) | delegatedProperties.kt:34:31:34:48 | get | MethodCall |
| delegatedProperties.kt:34:31:34:48 | <get-readWrite>(...) | delegatedProperties.kt:34:31:34:48 | get | MethodCall |
| delegatedProperties.kt:34:31:34:48 | <set-?> | delegatedProperties.kt:34:9:34:48 | <set-readWrite> | VarAccess |
| delegatedProperties.kt:34:31:34:48 | <set-readWrite>(...) | delegatedProperties.kt:34:31:34:48 | set | MethodCall |
| delegatedProperties.kt:34:31:34:48 | <set-readWrite>(...) | delegatedProperties.kt:34:31:34:48 | set | MethodCall |
| delegatedProperties.kt:34:31:34:48 | Integer | delegatedProperties.kt:34:9:34:48 | <get-readWrite> | TypeAccess |
@@ -193,7 +194,6 @@
| delegatedProperties.kt:34:31:34:48 | setValue(...) | delegatedProperties.kt:34:9:34:48 | <set-readWrite> | 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 | <set-readWrite> | 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 | <dispatchReceiver> | delegatedProperties.kt:82:40:82:54 | | VarAccess |
| delegatedProperties.kt:82:40:82:54 | <get-delegatedToMember3>(...) | delegatedProperties.kt:82:40:82:54 | get | MethodCall |
| delegatedProperties.kt:82:40:82:54 | <get-delegatedToMember3>(...) | delegatedProperties.kt:82:40:82:54 | get | MethodCall |
| delegatedProperties.kt:82:40:82:54 | <set-?> | delegatedProperties.kt:82:9:82:54 | <set-delegatedToMember3> | VarAccess |
| delegatedProperties.kt:82:40:82:54 | <set-delegatedToMember3>(...) | delegatedProperties.kt:82:40:82:54 | set | MethodCall |
| delegatedProperties.kt:82:40:82:54 | <set-delegatedToMember3>(...) | 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.<dispatchReceiver> | delegatedProperties.kt:82:40:82:54 | | VarAccess |
| delegatedProperties.kt:82:40:82:54 | this.<dispatchReceiver> | delegatedProperties.kt:82:40:82:54 | get | VarAccess |
| delegatedProperties.kt:82:40:82:54 | this.<dispatchReceiver> | delegatedProperties.kt:82:40:82:54 | set | VarAccess |
| delegatedProperties.kt:82:40:82:54 | value | delegatedProperties.kt:82:9:82:54 | <set-delegatedToMember3> | 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 | <none> | TypeAccess |