The GitHub Actions job "Fory CI" on fory.git/main has succeeded.
Run started by GitHub user chaokunyang (triggered by chaokunyang).

Head commit for run:
20f51a1d2992c6c877f28d360dcd95de43128a7e / Peiyang He 
<[email protected]>
fix(compiler): alias C++ union case types in metadata macros (#3814)

## Why?

The C++ compiler can emit union metadata macros that fail to compile
when a union case payload type contains a C++ template comma, e.g.
`std::unordered_map<K, V>`.

There are two affected paths:

- `FORY_UNION(...)` for unions with at most 16 cases.
- `FORY_UNION_IDS(...)` plus `FORY_UNION_CASE(...)` for larger unions.

Example IDL:

```
package probe.cpp_macro_fory_union;

union SmallChoice {
  map<string, any> by_name = 1;
  string name = 2;
}
```

Generated C++ code:

```c++
FORY_UNION(probe::cpp_macro_fory_union::SmallChoice,
  (by_name, std::unordered_map<std::string, std::any>, 
fory::F(1).map(fory::T::string(), fory::FieldNodeSpec{})),
  (name, std::string, fory::F(2))
);
```

Observed compile error:

```text
/home/hpy/fory/cpp/fory/serialization/union_serializer.h:1203:18: error: 
'FORY_UNION_CASE_META_fory' has not been declared
/tmp/fory_cpp_macro_pr_wql7zo9p/generated/probe_cpp_macro_fory_union.h:140:4: 
error: 'by_name' was not declared in this scope
/tmp/fory_cpp_macro_pr_wql7zo9p/generated/probe_cpp_macro_fory_union.h:140:54: 
error: expected primary-expression before ',' token
/home/hpy/fory/cpp/fory/serialization/union_serializer.h:1192:18: error: 
'FORY_UNION_CASE_TYPE_fory' was not declared in this scope; did you mean 
'FORY_UNION_CASE_TYPE_2'?
```

**Root cause**:

The generator passed **raw** C++ type names into `FORY_UNION` case
tuples.
`FORY_UNION` rendered each case as `(case_name, case_type, meta)`:


https://github.com/apache/fory/blob/23aa3f98ee56687c555c681a488a69d8cfbb5832/compiler/fory_compiler/generators/cpp.py#L1203-L1221

This is unsafe for template types such as
`std::unordered_map<std::string, std::any>`.

C++ macro preprocessing happens before the compiler understands that the
comma inside `<K, V>` belongs to a template argument list. The
preprocessor treats that comma as a macro argument separator.

`FORY_UNION` expects each case tuple to have either two entries `(name,
meta)` or three entries `(name, type, meta)`:


https://github.com/apache/fory/blob/23aa3f98ee56687c555c681a488a69d8cfbb5832/cpp/fory/serialization/union_serializer.h#L1179-L1207

When the generated tuple contains:

```cpp
(by_name, std::unordered_map<std::string, std::any>, meta)
```

the preprocessor sees more entries than intended because of the comma in
`std::unordered_map<std::string, std::any>`.
That breaks tuple-size selection and causes invalid macro names such as
`FORY_UNION_CASE_META_fory` or `FORY_UNION_CASE_TYPE_fory`.


## What does this PR do?

Fix this by generating a union-scoped type alias for case payload types
whose rendered C++ type
contains a comma, and use that alias in `FORY_UNION` and
`FORY_UNION_CASE` metadata.

The generated alias name is derived from the union case name using the
pattern:

`ForyCase` + PascalCase(case_name) + `Type`.

e.g.

```cpp
class SmallChoice final {
 public:
  using ForyCaseByNameType = std::unordered_map<std::string, std::any>;
  ...
};

FORY_UNION(probe::cpp_macro_fory_union::SmallChoice,
  (by_name, probe::cpp_macro_fory_union::SmallChoice::ForyCaseByNameType, 
fory::F(1).map(...)),
  (name, std::string, fory::F(2))
);
```

The macro now receives `SmallChoice::ForyCaseByNameType`, which contains
no template comma and can be parsed safely by the preprocessor.

Note: I will handle naming collisions universally in a new PR.

## Related issues

N/A.

## AI Contribution Checklist

- [X] Substantial AI assistance was used in this PR: `no`

## Does this PR introduce any user-facing change?

N/A.

## Benchmark

N/A.

Report URL: https://github.com/apache/fory/actions/runs/28699524724

With regards,
GitHub Actions via GitBox


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

Reply via email to