"Extending" class property leads to stack overflow #361

Closed
opened 2025-12-30 01:23:50 +01:00 by adam · 4 comments
Owner

Originally created by @StefMa on GitHub (Nov 6, 2025).

My goal:
I have a class with a property.
I create a instance from this class.
The I want to re-use this instance but "extend" a property.
Like concatenate some words to an String.

Code:

class Bird {
  name: String
}

pigeon: Bird = new {
  name = "Pigeon"
}

I want to re-use the existing pigeon but modify the name.
The most obviously solution to me would be to amend the pigeon:

superHeroPigeon = (pigeon) {
  name = "SuperHero" + this.name
}

But this leads to an:

pkl failed with error Error: Command failed: /var/task/node_modules/@pkl-community/pkl-linux-x64/bin/pkl eval - --no-project --format json --allowed-modules pkl:,repl: --allowed-modules package: --cache-dir /tmp/pkl
–– Pkl Error ––
A stack overflow occurred.

┌─ 11564 repetitions of:
│ 10 | name = "SuperHero" + this.name
│                           ^^^^^^^^^
│ at text#superHeroPigeon.name (repl:text)
└─

106 | text = renderer.renderDocument(value)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.1/stdlib/base.pkl#L106)
 and stderr:
 –– Pkl Error ––
A stack overflow occurred.

┌─ 11564 repetitions of:
│ 10 | name = "SuperHero" + this.name
│                           ^^^^^^^^^
│ at text#superHeroPigeon.name (repl:text)
└─

106 | text = renderer.renderDocument(value)
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.1/stdlib/base.pkl#L106)

See also: https://pkl-playground.vercel.app/?share=start-air-involved

Overriding however, works.
So I can go with this workaround:

superHeroPigeon = let (originalPigeon = pigeon)
  (pigeon) {
    name = "SuperHero" + originalPigeon.name
  }

This is a super simplified example for our use case.
I'm not sure if a "real bug" of if just hold it wrong 🫣

Originally created by @StefMa on GitHub (Nov 6, 2025). **My goal:** I have a class with a property. I create a instance from this class. The I want to re-use this instance but "extend" a property. Like concatenate some words to an `String`. **Code:** ```pkl class Bird { name: String } pigeon: Bird = new { name = "Pigeon" } ``` I want to re-use the existing `pigeon` but modify the name. The most obviously solution to me would be to amend the pigeon: ```pkl superHeroPigeon = (pigeon) { name = "SuperHero" + this.name } ``` But this leads to an: ``` pkl failed with error Error: Command failed: /var/task/node_modules/@pkl-community/pkl-linux-x64/bin/pkl eval - --no-project --format json --allowed-modules pkl:,repl: --allowed-modules package: --cache-dir /tmp/pkl –– Pkl Error –– A stack overflow occurred. ┌─ 11564 repetitions of: │ 10 | name = "SuperHero" + this.name │ ^^^^^^^^^ │ at text#superHeroPigeon.name (repl:text) └─ 106 | text = renderer.renderDocument(value) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.1/stdlib/base.pkl#L106) and stderr: –– Pkl Error –– A stack overflow occurred. ┌─ 11564 repetitions of: │ 10 | name = "SuperHero" + this.name │ ^^^^^^^^^ │ at text#superHeroPigeon.name (repl:text) └─ 106 | text = renderer.renderDocument(value) ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ at pkl.base#Module.output.text (https://github.com/apple/pkl/blob/0.25.1/stdlib/base.pkl#L106) ``` See also: https://pkl-playground.vercel.app/?share=start-air-involved **Overriding** however, works. So I can go with this workaround: ``` superHeroPigeon = let (originalPigeon = pigeon) (pigeon) { name = "SuperHero" + originalPigeon.name } ``` This is a super simplified example for our use case. I'm not sure if a "real bug" of if just hold it wrong 🫣
adam closed this issue 2025-12-30 01:23:50 +01:00
Author
Owner

@HT154 commented on GitHub (Nov 6, 2025):

You're looking for this:

superHeroPigeon = (pigeon) {
  name = "SuperHero" + super.name
}

This also works:

superHeroPigeon = (pigeon) {
  name = "SuperHero" + pigeon.name
}

Your original code resulting in a stack overflow is expected behavior.

@HT154 commented on GitHub (Nov 6, 2025): You're looking for this: ```pkl superHeroPigeon = (pigeon) { name = "SuperHero" + super.name } ``` This also works: ```pkl superHeroPigeon = (pigeon) { name = "SuperHero" + pigeon.name } ``` Your original code resulting in a stack overflow is expected behavior.
Author
Owner

@StefMa commented on GitHub (Nov 6, 2025):

Thanks for the fast response and the answer!

superHeroPigeon = (pigeon) {
  name = "SuperHero" + pigeon.name
}

This works, but doesn't look like it uses this pigeon what you amend, right? 🤔
Its rather "just a string coming from somewhere".

Imagine having a class coming from somewhere else (e.g. from an import), the you have to do something like this:

(ImportedModule.thePigeonInThisCase) {
  name = "SuperHero" + ImportedModule.thePigeonInThisCase
}

Looks a b it cumbersome

Your original code resulting in a stack overflow is expected behavior.

If this is the case, and this is the "final" answer, then its fine for me.
Feel free to close it 🔒

@StefMa commented on GitHub (Nov 6, 2025): Thanks for the fast response and the answer! ```pkl superHeroPigeon = (pigeon) { name = "SuperHero" + pigeon.name } ``` This works, but doesn't look like it uses `this` pigeon what you *amend*, right? 🤔 Its rather "just a string coming from somewhere". Imagine having a class coming from somewhere else (e.g. from an import), the you have to do something like this: ```pkl (ImportedModule.thePigeonInThisCase) { name = "SuperHero" + ImportedModule.thePigeonInThisCase } ``` Looks a b it cumbersome > Your original code resulting in a stack overflow is expected behavior. If this is the case, and this is the "final" answer, then its fine for me. Feel free to close it 🔒
Author
Owner

@bioball commented on GitHub (Nov 6, 2025):

Imagine having a class coming from somewhere else (e.g. from an import), the you have to do something like this:

(ImportedModule.thePigeonInThisCase) {
  name = "SuperHero" + ImportedModule.thePigeonInThisCase
}

Re-iterating what @HT154 said; the way to do this is with super, which is the this of the parent object!

(ImportedModule.thePigeonInThisCase) {
  name = "SuperHero" + super.name
}
@bioball commented on GitHub (Nov 6, 2025): > Imagine having a class coming from somewhere else (e.g. from an import), the you have to do something like this: > > ``` > (ImportedModule.thePigeonInThisCase) { > name = "SuperHero" + ImportedModule.thePigeonInThisCase > } > ``` Re-iterating what @HT154 said; the way to do this is with `super`, which is the `this` of the parent object! ```pkl (ImportedModule.thePigeonInThisCase) { name = "SuperHero" + super.name } ```
Author
Owner

@StefMa commented on GitHub (Nov 6, 2025):

🤯 This (pun intended) is actually the correct answer. this.name is of course referencing to this new instance name. So it's recursive. While super is the parent 🤦‍♂️. Yeah, it make sense now. My bad!

@StefMa commented on GitHub (Nov 6, 2025): 🤯 This (pun intended) is actually the correct answer. `this.name` is of course referencing to this new instance `name`. So it's recursive. While `super` is the parent 🤦‍♂️. Yeah, it make sense now. My bad!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/pkl#361