https://kotlinlang.org logo
#compiler
Title
# compiler
a

Alexander Ioffe

03/27/2024, 2:12 AM
Could someone point me to an example of how to instantiate a
IrLocalDelegatedProperty
? I'm trying to write a visitor that converts something like this:
Copy code
val x = stuff
To something like this:
Copy code
val x by MyDelegateValue { stuff }
t

Tóth István Zoltán

03/27/2024, 3:26 AM
I guess, and this is really just a guess, that you are not supposed to create a delegated property from a compiler plugin. The function you've mentioned is for older versions of the compiler or for the frontend plugin. Technically you can simply create a backing field that contains the MyDelegatedValue instance and a getter that uses that instance to get the value. Have you checked what the compiler actually generates with dump (preferably in a backend plugin)? Actually, I've found a warning in the compiler code about depending on an information that a property is a delegate, advising against it.
a

Alexander Ioffe

03/27/2024, 3:52 AM
As a mater of fact I have. This:
Copy code
val x by MyDelegateValue { stuff }
Is this:
Copy code
[IrLocalDelegatedProperty] name:x type:kotlin.String flags:val
  [IrVariable] (orig:PROPERTY_DELEGATE)name:x$delegate type:<root>.UsingStuff.MyDelegateValue<kotlin.String> [val]
    [IrConstructorCall] Fun(<init>):<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
      <class: T>: kotlin.String
      inner: [IrFunctionExpression] type=kotlin.coroutines.SuspendFunction0<kotlin.String> origin=LAMBDA
        [IrSimpleFunction] (orig:LOCAL_FUNCTION_FOR_LAMBDA) <anonymous>(): kotlin.String [suspend]
          [IrBlockBody]
            [IrReturn] type=kotlin.Nothing from='Fun(<anonymous>)'
              [IrCall] Fun(stuff) - dispatch=UsingStuff
                [IrGetObjectValue] 'CLASS OBJECT name:UsingStuff modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.UsingStuff
  [IrSimpleFunction] (orig:DELEGATED_PROPERTY_ACCESSOR) <get-x>(): kotlin.String
    [IrBlockBody]
      [IrReturn] type=kotlin.Nothing from='Fun(<get-x>)'
        [IrCall] Fun(getValue) - dispatch=UsingStuff.MyDelegateValue
          [IrGetValue] Var(x$delegate)
          t: [IrConst] null: kotlin.Nothing?
          property: LOCAL_DELEGATED_PROPERTY_REFERENCE 'val x: kotlin.String by (...)' delegate='Var(x$delegate)' getter='Fun(<get-x>)' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
The above is my person kotlin-ir dumper which actually prints the IR classes. If you prefer the original it is:
Copy code
LOCAL_DELEGATED_PROPERTY name:x type:kotlin.String flags:val
  VAR PROPERTY_DELEGATE name:x$delegate type:<root>.UsingStuff.MyDelegateValue<kotlin.String> [val]
    CONSTRUCTOR_CALL 'public constructor <init> (inner: kotlin.coroutines.SuspendFunction0<T of <root>.UsingStuff.MyDelegateValue>) [primary] declared in <root>.UsingStuff.MyDelegateValue' type=<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
      <class: T>: kotlin.String
      inner: FUN_EXPR type=kotlin.coroutines.SuspendFunction0<kotlin.String> origin=LAMBDA
        FUN LOCAL_FUNCTION_FOR_LAMBDA name:<anonymous> visibility:local modality:FINAL <> () returnType:kotlin.String [suspend]
          BLOCK_BODY
            RETURN type=kotlin.Nothing from='local final fun <anonymous> (): kotlin.String [suspend] declared in <root>.UsingStuff.testing.<anonymous>'
              CALL 'public final fun <get-stuff> (): kotlin.String declared in <root>.UsingStuff' type=kotlin.String origin=GET_PROPERTY
                $this: GET_OBJECT 'CLASS OBJECT name:UsingStuff modality:FINAL visibility:public superTypes:[kotlin.Any]' type=<root>.UsingStuff
  FUN DELEGATED_PROPERTY_ACCESSOR name:<get-x> visibility:local modality:FINAL <> () returnType:kotlin.String
    BLOCK_BODY
      RETURN type=kotlin.Nothing from='local final fun <get-x> (): kotlin.String declared in <root>.UsingStuff.testing.<anonymous>'
        CALL 'public final fun getValue (t: T of <root>.UsingStuff.MyDelegateValue?, property: kotlin.reflect.KProperty<*>): T of <root>.UsingStuff.MyDelegateValue [operator] declared in <root>.UsingStuff.MyDelegateValue' type=kotlin.String origin=null
          $this: GET_VAR 'val x$delegate: <root>.UsingStuff.MyDelegateValue<kotlin.String> [val] declared in <root>.UsingStuff.testing.<anonymous>' type=<root>.UsingStuff.MyDelegateValue<kotlin.String> origin=null
          t: CONST Null type=kotlin.Nothing? value=null
          property: LOCAL_DELEGATED_PROPERTY_REFERENCE 'val x: kotlin.String by (...)' delegate='val x$delegate: <root>.UsingStuff.MyDelegateValue<kotlin.String> [val] declared in <root>.UsingStuff.testing.<anonymous>' getter='local final fun <get-x> (): kotlin.String declared in <root>.UsingStuff.testing.<anonymous>' setter=null type=kotlin.reflect.KProperty0<kotlin.String> origin=PROPERTY_REFERENCE_FOR_DELEGATE
@Tóth István Zoltán when you say: > The function you've mentioned is for older versions of the compiler or for the frontend plugin. Do you mean
irFactory.createLocalDelegatedProperty
? That's almost the same as creating a
IrLocalDelegatedPropertyImpl
directly which I can use instead. > Technically you can simply create a backing field that contains the MyDelegatedValue instance and a getter that uses that instance to get the value. Can you elaborate? How could I do that?
t

Tóth István Zoltán

03/27/2024, 6:31 AM
I would: • create a private property that belongs to
x
let's call it
x$yourdelegate
• initialize the backing field of
x$yourdelegate
with
MyDelegateValue { stuff }
• replace the getter and setter of
x
with: ◦ fetch
x$yourdelegate
◦ call the appropriate get/set function This is quite similar to the delegation above and works basically the same. Technically it is not necessary for
MyDelegateValue
to be a delegation provider. You can call whatever function from the getter and the setter. This code does something similar, in this case it replaces the delegate with a class function call. https://github.com/spxbhuhb/z2/blob/041dc0048f675ff388c0b8f7be47878c2b80daaf/z2-ko[…]xion/z2/kotlin/schematic/ir/klass/SchematicPropertyTransform.kt