Skip to content

Allow multidep enums - #414

Open
LesterEvSe wants to merge 3 commits into
BlockstreamResearch:masterfrom
LesterEvSe:feat/multifile-enums
Open

Allow multidep enums#414
LesterEvSe wants to merge 3 commits into
BlockstreamResearch:masterfrom
LesterEvSe:feat/multifile-enums

Conversation

@LesterEvSe

Copy link
Copy Markdown
Collaborator

Add specific identifier to EnumInfo struct to support unique type in ABI

@LesterEvSe
LesterEvSe requested a review from KyrylR September 4, 2026 14:07
@LesterEvSe LesterEvSe self-assigned this Sep 4, 2026
@LesterEvSe
LesterEvSe requested a review from delta1 as a code owner September 4, 2026 14:07
@LesterEvSe LesterEvSe added bug Something isn't working enhancement New feature or request labels Sep 4, 2026
@apoelstra

Copy link
Copy Markdown
Contributor

Are there design documents or something about this way of identifying modules? Have you looked at https://community.simplicity-lang.org/t/nominal-types-and-module-identification-in-simplicityhl/62/3

@apoelstra

Copy link
Copy Markdown
Contributor

Also, in what sense are enums "special"? It seems like we are implementing a half-baked form of nominal typing for enums, and only enums. For example using the cast_preserves_enum_identity we attempt to reject casts between structurally-equivalent enums, but do so in a poorly-specified way that has multiple bugs.

@LesterEvSe

LesterEvSe commented Sep 4, 2026

Copy link
Copy Markdown
Collaborator Author

I think @KyrylR can give a better answer to the question "why are enums special."
Thanks for the link, I read it, now I have better understanding of the global problem.
Enums were written before that thread, I think it was an attempt to introduce nominal typing without intervening in the type system at all, so from that perspective it looks half-baked. It's still better than having no nominal typing at all, but it wasn't the end goal.

Regarding the module system: it currently supports inline mod, but it doesn't support importing a whole moduleб only individual items out of one (functions, type aliases, and enums).

So something like this doesn't currently work:

mod A {
    pub mod B {
        pub fn smth() {}
    }
}

use crate::A::B;
use B::smth; // error

fn main() {}

But we can get smth() directly with use crate::A::B::smth;.

On @stringhandler's main question, about single-file and multi-file programs having an exact equivalent, I think yes, and that's the main reason flattening exists at all (#337, more detailed in linked issue). To show it concretely rather than just assert it: I compiled both of the following programs, and they produce the identical CMR:

fn add_32(a: u32, b: u32) -> u32 {
    let (_, res): (bool, u32) = jet::add_32(a, b);
    res
}

fn main() {
    let a: u32 = witness::A;
    let b: u32 = witness::B;
    let c: u32 = witness::C;

    assert!(jet::eq_32(c, add_32(a, b)));
}

And:

mod X {
    pub fn add_32(a: u32, b: u32) -> u32 {
        let (_, res): (bool, u32) = jet::add_32(a, b);
        res
    }
}

use crate::X::add_32;

fn main() {
    let a: u32 = witness::A;
    let b: u32 = witness::B;
    let c: u32 = witness::C;

    assert!(jet::eq_32(c, add_32(a, b)));
}

Both give CMR f4b723f55dd43e37755c7fc049b793fd2ffc3d82276e243d7d84c03897a2656e.

@LesterEvSe

Copy link
Copy Markdown
Collaborator Author

Get back to enums.
If we plan to rewrite the types, we'll have to rewrite the enums to accommodate that anyway. For now, I haven't taken type conversion into account and have restricted enums to be strictly nominal. In the future, it will be easier to relax this restriction than to do the opposite.

Regarding their usage in std (u32_conver_test.simf), simplicity-lending, and price-oracle, it would be much more convenient and optimized to use enums instead of custom match branching

@apoelstra

Copy link
Copy Markdown
Contributor

It's still better than having no nominal typing at all, but it wasn't the end goal.

It's not, because it creates behavior that we need to maintain, doesn't make sense to users, and which will be difficult to shoehorn into a properly-designd system.

I don't think we should keep grafting ad-hoc extensions onto the existing enum implementation, nor onto the existing module system. We should fix the types and module systems properly.

@schoen

schoen commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

I have no particular opinion about the architectural/design question here, but I just wanted to mention that the issue that this solves is blocking a new Simplex demo that I made based on last_will.simf, which now uses enum. The problem there is that Simplex itself automatically wraps programs under test in a module, causing the enum feature as a whole to be incompatible with Simplex projects.

I can confirm from testing that this PR does effectively remove that limitation in Simplex, and so, with other minor Simplex changes, it would unblock my demo. I would love to see some solution to this issue land in SimplicityHL so that I could publish that new demo as part of Simplex (it's a lot more sophisticated than the existing basic demo project there).

We've already been building various examples on the enum feature, so it's unfortunate that it has this kind of limitation and it would be great to find a way to remove it.

@apoelstra

Copy link
Copy Markdown
Contributor

The PR description, at least, should have some description of the issue it solves.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants