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. value → foobar) 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
Description
When a UniFFI enum has a variant with a field literally named
value, the generatedJava
FfiConverterfails to compile. The generatedallocationSizeandwritemethods always name their own parameter
value, and the record-pattern destructuringfor the variant also binds a local called
valuein the same scope — which Javadoes not allow (a pattern variable cannot shadow an already-in-scope local/parameter).
Rust definition (minimal repro)
Generated Java (uniffi-bindgen-java 0.4.2, UniFFI 0.29)
Compiler error
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 namedvalue, the pattern's binding variable collides with that parameter name in the samemethod 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 commonname to pick) fails to generate compilable Java, with no diagnostic from
uniffi-bindgen-java itself — the failure only surfaces later at
javactime.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 renamingpattern 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.
value→foobar) 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.2uniffi-rs: 0.31