Skip to content

Generated FfiConverter methods fail to compile when an enum variant field is named "value" (shadows the converter's own parameter) #63

Description

@Levyks

Description

When a UniFFI enum has a variant with a field literally named value, the generated
Java FfiConverter fails to compile. The generated allocationSize and write
methods always name their own parameter value, and the record-pattern destructuring
for the variant also binds a local called value in the same scope — which Java
does not allow (a pattern variable cannot shadow an already-in-scope local/parameter).

Rust definition (minimal repro)

#[derive(uniffi::Enum)]
pub enum MyEnum {
    Foo,
    Bar,
    Baz { value: String },
}

Generated Java (uniffi-bindgen-java 0.4.2, UniFFI 0.29)

@Override
public long allocationSize(MyEnum value) {
    return switch (value) {
      case MyEnum.Foo() ->
        (4L);
      case MyEnum.Bar() ->
        (4L);
      case MyEnum.Baz(var value) ->
        (4L
        + FfiConverterString.INSTANCE.allocationSize(value));
    };
}

Compiler error

error: variable value is already defined in method allocationSize(MyEnum)
case MyEnum.Unknown(var value) ->
^
error: variable value is already defined in method write(MyEnum,ByteBuffer)
case MyEnum.Unknown(var value) ->
^

Root cause

The generator always names the top-level parameter of allocationSize/write/etc.
value. When a record-pattern destructures a variant whose field is also named
value, the pattern's binding variable collides with that parameter name in the same
method scope — which is illegal under Java's record pattern / pattern-matching
scoping rules (a pattern binding cannot reuse a name already bound in the enclosing
scope).

This means any UniFFI enum with a field named value (a fairly natural and common
name to pick) fails to generate compilable Java, with no diagnostic from
uniffi-bindgen-java itself — the failure only surfaces later at javac time.

Suggested fix

Something like renaming the outer method parameter (e.g. value__value /
self / a name guaranteed not to collide with any user-defined field), or renaming
pattern bindings with a generated-safe prefix, so field names chosen by the Rust API
author can never collide with the converter's internal parameter names.

Workaround

Renaming the conflicting Rust field (e.g. valuefoobar) avoids the collision,
but this shouldn't be necessary — the generator's own reserved names shouldn't leak
into what field names are usable in the source enum.

Versions

  • uniffi-bindgen-java: 0.4.2
  • uniffi-rs: 0.31

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions