gluon icon indicating copy to clipboard operation
gluon copied to clipboard

Rust Enum in Struct in Enum causes bottom level enum constructor to change type?

Open crides opened this issue 4 years ago • 4 comments

Minimum example needed to reproduce

Basically I have types in Rust like these:

#[derive(Clone, Debug, VmType, Pushable, Getable)]
enum E1 {
    S1(S),
}

#[derive(Clone, Debug, VmType, Pushable, Getable)]
struct S {
    e: E2,
}

#[derive(Clone, Debug, VmType, Pushable, Getable)]
enum E2 {
    Num(i32),
}

And if I try to initialize E1 with:

let { E1, S, E2 } = import! test
let e1 = S1 { e = Num 3 }

Then I get the following:

error: Expected the following types to be equal
Expected: | Num : Int -> E1
Found: E2
1 errors were found during unification:
Types do not match:
    Expected: Int -> E1
    Found: Int -> <opaque>
  ┌─ test:3:23
  │
3 │     let e1 = S1 { e = Num 3 }
  │
  │                       ^^^^^

So it seems like suddenly E2's constructor(s) have changed (if E2 has multiple variants they all get changed). Note that this also happens in the repl*, but (assuming test is the module containing the types) when I try :t import! test it shows all types correctly, but if I try :t let { E1 } = import! test in S1 then it also shows the wrong type.

[*] The repl included in the test repo is basically the one taken from gluon, except Color is removed and the repl is run from a provided Thread.

crides avatar Jan 05 '21 04:01 crides

Seems like only 1 nested enum (i.e. enum in enum) is needed to trigger the same behaviour. The test repo has been updated to reflect that

crides avatar Jan 05 '21 09:01 crides

Defining recursive types is not possible by deriving VmType as is atm.

What you can do is define the types in gluon also and then use the #[gluon(vm_type = "...")] attribute to point to the type on the gluon side (by linking to its module path). Should be an example in the marshalling example.

Marwes avatar Jan 05 '21 13:01 Marwes

I'm not using recursive types here, but are nested foreign enums also not supported? Also In my use case, I want to pass the types from Gluon to Rust and from Rust to Gluon, so I have to use Getable and Pushable (is there another way?). It does seem like it's possible to define the same types in Gluon and then passing them to Rust functions, so I'll settle with that for now.

crides avatar Jan 05 '21 20:01 crides

My bad, misread it. Fixed in #902

Marwes avatar Jan 08 '21 23:01 Marwes