This is an automated email from the ASF dual-hosted git repository.

chaokunyang pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/fory.git


The following commit(s) were added to refs/heads/main by this push:
     new 2ec562556 feat(compiler): handle nested container ref pointer options 
in C++ compiler correctly (#3735)
2ec562556 is described below

commit 2ec562556b8da88fa5eccad6671eab33649d2d50
Author: Peiyang He <[email protected]>
AuthorDate: Tue Jun 9 16:52:50 2026 +0800

    feat(compiler): handle nested container ref pointer options in C++ compiler 
correctly (#3735)
    
    ## Why?
    
    The C++ compiler should correctly apply ref pointer options for nested
    container element/value references.
    
    **Additional note**:
    
    When submitting [PR 3731](https://github.com/apache/fory/pull/3731), I
    did not notice that Fory currently only supports nested collection types
    in C++:
    
    
    
https://github.com/apache/fory/blob/33b0d6e8b73d1769d98824195b9155043266f3fe/docs/compiler/schema-idl.md?plain=1#L1414-L1418
    
    However, since that PR merely added a piece of defensive programming
    logic, it may not need to be reverted.
    
    Similar issues also exist in the Python and JavaScript compilers.
    However, since they do not support nested container types, I have not
    fixed them for now.
    
    ## What does this PR do?
    
    - Handle nested container ref pointer options correctly.
    - Add corresponding testcase.
    
    ## Related issues
    
    N/A.
    
    ## AI Contribution Checklist
    
    
    
    - [ ] Substantial AI assistance was used in this PR: `no`
    - [ ] If `yes`, I included a completed [AI Contribution
    
Checklist](https://github.com/apache/fory/blob/main/AI_POLICY.md#9-contributor-checklist-for-ai-assisted-prs)
    in this PR description and the required `AI Usage Disclosure`.
    - [ ] If `yes`, my PR description includes the required `ai_review`
    summary and screenshot evidence of the final clean AI review results
    from both fresh reviewers on the current PR diff or current HEAD after
    the latest code changes.
    
    
    
    ## Does this PR introduce any user-facing change?
    
    N/A.
    
    ## Benchmark
    
    N/A.
---
 compiler/fory_compiler/generators/cpp.py           | 62 +++++++++++++++++-----
 .../fory_compiler/tests/test_generated_code.py     | 43 +++++++++++++++
 2 files changed, 92 insertions(+), 13 deletions(-)

diff --git a/compiler/fory_compiler/generators/cpp.py 
b/compiler/fory_compiler/generators/cpp.py
index e156cba02..91e6b49fd 100644
--- a/compiler/fory_compiler/generators/cpp.py
+++ b/compiler/fory_compiler/generators/cpp.py
@@ -1468,13 +1468,20 @@ class CppGenerator(BaseGenerator):
             return type_name
 
         if isinstance(field_type, ListType):
+            effective_element_optional = element_optional or 
field_type.element_optional
+            effective_element_ref = element_ref or field_type.element_ref
+            effective_element_weak_ref = element_weak_ref
+            if field_type.element_ref:
+                effective_element_weak_ref = self.is_weak_ref(
+                    field_type.element_ref_options
+                )
             element_type = self.generate_namespaced_type(
                 field_type.element_type,
-                element_optional,
-                element_ref,
+                effective_element_optional,
+                effective_element_ref,
                 False,
                 False,
-                element_weak_ref,
+                effective_element_weak_ref,
                 False,
                 parent_stack,
             )
@@ -1513,13 +1520,18 @@ class CppGenerator(BaseGenerator):
             key_type = self.generate_namespaced_type(
                 field_type.key_type, False, False, False, False, parent_stack
             )
+            value_weak_ref = (
+                self.is_weak_ref(field_type.value_ref_options)
+                if field_type.value_ref
+                else False
+            )
             value_type = self.generate_namespaced_type(
                 field_type.value_type,
                 False,
                 field_type.value_ref,
                 False,
                 False,
-                weak_ref and field_type.value_ref,
+                value_weak_ref,
                 False,
                 parent_stack,
             )
@@ -1749,13 +1761,20 @@ class CppGenerator(BaseGenerator):
             return type_name
 
         elif isinstance(field_type, ListType):
+            effective_element_optional = element_optional or 
field_type.element_optional
+            effective_element_ref = element_ref or field_type.element_ref
+            effective_element_weak_ref = element_weak_ref
+            if field_type.element_ref:
+                effective_element_weak_ref = self.is_weak_ref(
+                    field_type.element_ref_options
+                )
             element_type = self.generate_type(
                 field_type.element_type,
-                element_optional,
-                element_ref,
+                effective_element_optional,
+                effective_element_ref,
                 False,
                 False,
-                element_weak_ref,
+                effective_element_weak_ref,
                 False,
                 parent_stack,
             )
@@ -1794,13 +1813,18 @@ class CppGenerator(BaseGenerator):
             key_type = self.generate_type(
                 field_type.key_type, False, False, False, False, parent_stack
             )
+            value_weak_ref = (
+                self.is_weak_ref(field_type.value_ref_options)
+                if field_type.value_ref
+                else False
+            )
             value_type = self.generate_type(
                 field_type.value_type,
                 False,
                 field_type.value_ref,
                 False,
                 False,
-                weak_ref and field_type.value_ref,
+                value_weak_ref,
                 False,
                 parent_stack,
             )
@@ -1898,14 +1922,21 @@ class CppGenerator(BaseGenerator):
 
         elif isinstance(field_type, ListType):
             includes.add("<vector>")
+            effective_element_optional = element_optional or 
field_type.element_optional
+            effective_element_ref = element_ref or field_type.element_ref
+            effective_element_weak_ref = element_weak_ref
+            if field_type.element_ref:
+                effective_element_weak_ref = self.is_weak_ref(
+                    field_type.element_ref_options
+                )
             self.collect_includes(
                 field_type.element_type,
-                element_optional,
-                element_ref,
+                effective_element_optional,
+                effective_element_ref,
                 includes,
                 False,
                 False,
-                element_weak_ref,
+                effective_element_weak_ref,
                 False,
             )
 
@@ -1924,9 +1955,14 @@ class CppGenerator(BaseGenerator):
 
         elif isinstance(field_type, MapType):
             includes.add("<unordered_map>")
+            value_weak_ref = (
+                self.is_weak_ref(field_type.value_ref_options)
+                if field_type.value_ref
+                else False
+            )
             if field_type.value_ref:
                 includes.add("<memory>")
-                if weak_ref:
+                if value_weak_ref:
                     includes.add('"fory/serialization/weak_ptr_serializer.h"')
             self.collect_includes(field_type.key_type, False, False, includes)
             self.collect_includes(
@@ -1936,7 +1972,7 @@ class CppGenerator(BaseGenerator):
                 includes,
                 False,
                 False,
-                weak_ref and field_type.value_ref,
+                value_weak_ref,
                 False,
             )
 
diff --git a/compiler/fory_compiler/tests/test_generated_code.py 
b/compiler/fory_compiler/tests/test_generated_code.py
index e319148d6..a1b08bff5 100644
--- a/compiler/fory_compiler/tests/test_generated_code.py
+++ b/compiler/fory_compiler/tests/test_generated_code.py
@@ -1126,6 +1126,49 @@ def 
test_cpp_generator_supports_decimal_fields_and_unions():
     assert "(amount, fory::serialization::Decimal, fory::F(1))" in cpp_output
 
 
+def test_cpp_nested_container_ref_uses_correct_pointer_type():
+    schema = parse_fdl(
+        dedent(
+            """
+            package gen;
+
+            message Node {
+                string value = 1;
+            }
+
+            message Request {
+                list<list<ref Node>> groups = 1;
+                map<string, map<string, ref Node>> nodes = 2;
+                list<list<ref(weak=true) Node>> weak_groups = 3;
+                map<string, map<string, ref(weak=true) Node>> weak_nodes = 4;
+            }
+            """
+        )
+    )
+
+    cpp_output = render_files(generate_files(schema, CppGenerator))
+    assert "std::vector<std::vector<std::shared_ptr<Node>>> groups_;" in 
cpp_output
+    assert "std::vector<std::vector<Node>> groups_;" not in cpp_output
+    assert (
+        "std::unordered_map<std::string, "
+        "std::unordered_map<std::string, std::shared_ptr<Node>>> nodes_;" in 
cpp_output
+    )
+    assert (
+        "std::vector<std::vector<fory::serialization::SharedWeak<Node>>> 
weak_groups_;"
+        in cpp_output
+    )
+    assert (
+        "std::unordered_map<std::string, "
+        "std::unordered_map<std::string, 
fory::serialization::SharedWeak<Node>>> "
+        "weak_nodes_;" in cpp_output
+    )
+    assert (
+        "std::unordered_map<std::string, "
+        "std::unordered_map<std::string, std::shared_ptr<Node>>> weak_nodes_;"
+        not in cpp_output
+    )
+
+
 def test_java_enum_generation_uses_fory_enum_ids():
     schema = parse_fdl(
         dedent(


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to