Skip to content

Conversation

@chaokunyang
Copy link
Collaborator

@chaokunyang chaokunyang commented Dec 30, 2025

Why?

Currently Rust uses a boolean write_ref_info/read_ref_info parameter which only distinguishes between "write ref flag" vs "don't write ref flag". This doesn't support:

  • Nullable types without ref tracking (like Option<T> where T is not a shared ref)
  • Explicit control over shared reference tracking per field via #[fory(ref=false)] attribute
  • Alignment with Go's RefMode design which has three modes: None, NullOnly, Tracking

What does this PR do?

1. Add RefMode enum to replace boolean write_ref_info/read_ref_info

#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
#[repr(u8)]
pub enum RefMode {
    #[default]
    None = 0,      // No ref flag written/read (primitives, non-nullable types)
    NullOnly = 1,  // Write NULL(-3) or NOT_NULL(-1), no ref tracking
    Tracking = 2,  // Full ref tracking with REF(-2) and REF_VALUE(0) flags
}

2. Update Serializer trait signature

fn fory_write(&self, context: &mut WriteContext, ref_mode: RefMode, write_type_info: bool, has_generics: bool) -> Result<(), Error>
fn fory_read(context: &mut ReadContext, ref_mode: RefMode, read_type_info: bool) -> Result<Self, Error>

3. Per-field RefMode determination in derive macro

  • Type classification: primitive → None, Option → NullOnly, Rc/Arc/Weak → Tracking
  • Field meta attributes respected: #[fory(ref=false)] to disable tracking, #[fory(nullable)] for null support
  • All field types (including trait objects like Box<dyn Any>, Rc<dyn Trait>, etc.) now respect field attributes

4. Add FieldRefMode enum with ToTokens impl for cleaner macro code generation

pub(crate) enum FieldRefMode {
    None,
    NullOnly,
    Tracking,
}

impl ToTokens for FieldRefMode {
    fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) {
        // Generates fory_core::RefMode::None/NullOnly/Tracking
    }
}

5. Add determine_field_ref_mode(field) helper

Combines type classification with field meta attributes to determine the correct RefMode for each field, respecting #[fory(ref=false)] and #[fory(nullable)] annotations.

Related issues

Closes #3097

Does this PR introduce any user-facing change?

  • Does this PR introduce any public API change?
    • Serializer::fory_write and Serializer::fory_read now take RefMode instead of bool
    • New RefMode enum exported from fory_core
  • Does this PR introduce any binary protocol compatibility change?
    • No, the wire format is unchanged

Benchmark

No performance regression expected - the RefMode enum comparison (ref_mode != RefMode::None) compiles to the same machine code as the previous boolean comparison.

@chaokunyang chaokunyang force-pushed the use_ref_mode_to_fine_grained_rust_ref_tracking branch 2 times, most recently from 4aa38c3 to f9ad808 Compare December 30, 2025 07:49
@chaokunyang chaokunyang mentioned this pull request Dec 30, 2025
17 tasks
@chaokunyang chaokunyang force-pushed the use_ref_mode_to_fine_grained_rust_ref_tracking branch from f9ad808 to 92ac5ff Compare December 30, 2025 07:59
@chaokunyang chaokunyang merged commit 8e36f0a into apache:main Dec 30, 2025
53 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Rust] RefMode based Fine-Grained Ref Tracking for Rust

2 participants