santiagomed commented on code in PR #3414:
URL: https://github.com/apache/thrift/pull/3414#discussion_r3127429489


##########
compiler/cpp/src/thrift/generate/t_rs_generator.cc:
##########
@@ -1699,10 +1699,37 @@ void t_rs_generator::render_struct_sync_read(const 
string& struct_name,
 
     for (members_iter = members.begin(); members_iter != members.end(); 
++members_iter) {
       t_field* tfield = (*members_iter);
+      t_type* resolved = get_true_type(tfield->get_type());
+      bool is_union_field = resolved->is_struct() && 
((t_struct*)resolved)->is_union();
       f_gen_ << indent() << rust_safe_field_id(tfield->get_key()) << " => {" 
<< '\n';
       indent_up();
-      render_type_sync_read("val", tfield->get_type());
-      f_gen_ << indent() << struct_field_read_temp_variable(tfield) << " = 
Some(val);" << '\n';
+      if (is_union_field) {
+        // Union fields: catch "received empty union" errors from unknown
+        // variants and treat them as None for forward compatibility.
+        // This matches how Java, Go, and Python Thrift handle unknown
+        // union fields -- they skip silently instead of failing.
+        //
+        // Use the resolved (non-Box) type for the method call since
+        // Box<T>::method() is not valid Rust syntax for turbofish.
+        string resolved_type = to_rust_type(resolved);
+        bool is_boxed_union = to_rust_type(tfield->get_type()) != 
resolved_type;
+        string read_call(resolved_type + "::read_from_in_protocol(i_prot)");
+        string val_expr = is_boxed_union ? "Box::new(val)" : "val";
+        f_gen_ << indent() << "match " << read_call << " {" << '\n';
+        indent_up();
+        f_gen_ << indent() << "Ok(val) => { " << 
struct_field_read_temp_variable(tfield) << " = Some(" << val_expr << "); }," << 
'\n';
+        f_gen_ << indent() << "Err(thrift::Error::Protocol(ref e)) if 
e.message.contains(\"received empty union\") => {" << '\n';

Review Comment:
   I added `ProtocolErrorKind::EmptyUnion = 7` to the runtime library and 
updated both sides of the codegen to use it. The union deserializer now emits 
`EmptyUnion` instead of `InvalidData`, and the struct-level catch arm matches 
on `e.kind == ProtocolErrorKind::EmptyUnion` instead of the string check. Also 
added an integration test covering the unknown variant path.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to