# \[Proposal\] Customizable Type Merging in Mojo

**URL:** <https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249>\
**Category:** Language Design\
**Tags:** discussion\
**Created:** [April 15, 2025, 8:15pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249 "2025-04-15T20:15:59Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 15, 2025, 8:15pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/1 "2025-04-15T20:15:59Z")

</div>

This is a discussion thread for the following proposal from @clattner: [max/mojo/proposals/custom-type-merging.md at main · modular/max · GitHub](http://github.com/modular/max/blob/main/mojo/proposals/custom-type-merging.md)

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 15, 2025, 9:36pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/2 "2025-04-15T21:36:05Z")

</div>

Will ` __merge_with__ ` have a defined ordering, or will the compiler try flipping it if one parameter ordering doesn’t exist? I could see this causing a lot of dependency loops unless there’s some kind of “order-agnostic” behavior.

---

<div class="post-metadata">

**Author:** ![sora](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@sora](https://forum.modular.com/u/sora)\
**Post date:** [April 15, 2025, 9:58pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/3 "2025-04-15T21:58:15Z")

</div>

Easy™, just make sure all the ` __merge_with__ ` rules form a lattice.

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/clattner/32/201_2.png) [@clattner](https://forum.modular.com/u/clattner)\
**Post date:** [April 18, 2025, 6:49pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/4 "2025-04-18T18:49:50Z")

</div>

Consider a merge between two values of type A and B. The compiler will invoke mergewith on A (with the type of B) and mergewith on B (with the type of A) and then require them to agree. If not, it will throw an error.

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 18, 2025, 7:51pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/5 "2025-04-18T19:51:45Z")

</div>

Doesn’t that force dependency cycles between libraries?

For example, if A is a runtime arbitrary precision float from the Mojo ecosystem, and B is Float32, one would expect that the Float32 can promote to the arbitrary precision float. For those checks to match, that means that the stdlib now needs to depend on the library containing type A in order to pull in the type.

To me, feels like the absence of `A. __merge_with__ [B]() -> B` in the presence of a `B. __merge_with__ [A]() -> A` should indicate that `B` should be converted to A. I agree that if both exist and they can’t agree on which type to promote to, then there should be an error thrown.

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/clattner/32/201_2.png) [@clattner](https://forum.modular.com/u/clattner)\
**Post date:** [April 18, 2025, 9:20pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/6 "2025-04-18T21:20:10Z")

</div>

It can, but that is better solved with a feature like “extensions”, which we agree we want to add someday. You can read about the [feature in Swift](https://docs.swift.org/swift-book/documentation/the-swift-programming-language/extensions/) for example (another [example intro](https://www.avanderlee.com/swift/extensions/)).

In your specific example though, this won’t come up. If Float32 impl converts to your APFloat type, then you don’t need to use this feature at all.

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 20, 2025, 1:22am UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/7 "2025-04-20T01:22:27Z")

</div>

Thanks for the clarification! If extensions are a near-term feature then I don’t have any issues with this.

---

<div class="post-metadata">

**Author:** ![sora](https://avatars.discourse-cdn.com/v4/letter/s/ad7895/32.png) [@sora](https://forum.modular.com/u/sora)\
**Post date:** [April 20, 2025, 10:36pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/8 "2025-04-20T22:36:38Z")

</div>

Implemented in `f40b470`.

> <https://github.com/modular/max/commit/f40b4701614cb85f309cdc3e732c6a8104b0b092>
>
> This patch implements (and updates) the \[user-declared \`\_\_merge\_with\_\_\`
> dunder
> m…ethods\](https://github.com/modular/max/blob/main/mojo/proposals/custom-type-merging.md)
> proposal. This can be used to make it so types like \`Pointer\` can merge
> in ternary operators
> and other places.
> 
> MODULAR\_ORIG\_COMMIT\_REV\_ID: a9a3750c64532ce0a0013006a4c7b0c61cacce53

---

<div class="post-metadata">

**Author:** ![clattner](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/clattner/32/201_2.png) [@clattner](https://forum.modular.com/u/clattner)\
**Post date:** [April 21, 2025, 5:57am UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/9 "2025-04-21T05:57:38Z")

</div>

Hi Owen,

I implemented this yesterday and added the algorithm pseudo code to the proposal doc (look for an update in the next nightly). The final design takes your suggestion:

> To me, feels like the absence of `A. __merge_with__ [B]() -> B` in the presence of a `B. __merge_with__ [A]() -> A` should indicate that `B` should be converted to A. I agree that if both exist and they can’t agree on which type to promote to, then there should be an error thrown.

Yep, this is how it works. If you implement `B. __merge_with__ [A]() -> A` then things will “just work” because the A side of the branch doesn’t need to be converted. You can even implement `B. __merge_with__ [A]() -> C` so long as A implicitly converts to C or you implement `A. __merge_with__ [B]() -> C` to make the behavior merge specific.

Please give it a try and let me know if you have any additional questions!

---

<div class="post-metadata">

**Author:** ![owenhilyard](https://sea1.discourse-cdn.com/flex001/user_avatar/forum.modular.com/owenhilyard/32/41_2.png) [@owenhilyard](https://forum.modular.com/u/owenhilyard)\
**Post date:** [April 21, 2025, 2:41pm UTC](https://forum.modular.com/t/proposal-customizable-type-merging-in-mojo/1249/10 "2025-04-21T14:41:06Z")

</div>

Thanks for the detailed docs! It will be interesting to compare this to Rust’s `Into`/`From` trait pair which has similar functionality. Being able to also make use of implicit conversions is a nice quality of life feature as well!
