Repository navigation
Translate size_t/ssize_t as usize/isize - #185
Merged
Merged
Conversation
lucic71
marked this pull request as draft
June 10, 2026 14:01
lucic71
marked this pull request as ready for review
June 10, 2026 18:17
joaotgouveia
pushed a commit
to joaotgouveia/cpp2rust
that referenced
this pull request
Oct 27, 2026
This PR translates `size_t/ssize_t` as `usize/isize` instead of
`u64/i64`. All tests and rules are affected by this change. That's why
this PR is very big. However the core of this change is quite small.
In `rules/` I had to change every `u64/i64` with `usize/isize`. This
makes the rules cleaner because we get rid of artificial `as usize`
casts in arguments and artificial `as u64` casts in return values.
In `libcc2rs/` I changed the arguments of some transalted functions
(malloc, fwrite, etc) from u64 to usize. I also added usize/isize
branches for VaArg.
In `cpp2rust/` the change has 3 parts:
1. I put usize/isize in `addBuiltinTypes`. This adds rules for: `size_t
/ size_type / __size_t -> usize` and `ssize_t -> isize`. __size_t is an
internal type that describes the return value of sizeof
2. `ToString` desugars its type by default, so I gave it a flag to leave
scalars alone, and made `search(QualType)` look for the sugared type
before the desugared one:
```cpp
std::string ToString(clang::QualType qual_type,
ScalarSugar sugar = ScalarSugar::kDesugar);
```
This is needed because size_t isn't a real type, just a typedef over an
integer.
3. In `Converter`, I added an extra default argument to `Convert`,
`ConvertRValue` and `ConvertFreshRValue`:
`std::optional<clang::QualType> implicit_convert_to`. In Clang, both
`size_t` and `unsigned long` are represented as the same type, but in
Rust, `usize` and `u64` are different types, an implicit cast between
the two is not allowed. To solve this, `Convert` is the single point of
adding a cast between 2 types that share the same underlying type in C
but have different types in Rust, this is decided by
`NeedsImplicitScalarCast`.
Callers of `Convert` have to pass the optional `implicit_convert_to` in
order to trigger the scalar cast. Callers pass the target type, for
example `ConvertFreshRValue(rhs, lhs->getType());` in ConvertAssignment,
and `Convert` takes care of the explicit Rust call if needed. Binary
operations do the same using GetOperandImplicitConversionTarget, which
converts both arguments to the same Rust type.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR translates
size_t/ssize_tasusize/isizeinstead ofu64/i64. All tests and rules are affected by this change. That's why this PR is very big. However the core of this change is quite small.In
rules/I had to change everyu64/i64withusize/isize. This makes the rules cleaner because we get rid of artificialas usizecasts in arguments and artificialas u64casts in return values.In
libcc2rs/I changed the arguments of some transalted functions (malloc, fwrite, etc) from u64 to usize. I also added usize/isize branches for VaArg.In
cpp2rust/the change has 3 parts:addBuiltinTypes. This adds rules for:size_t / size_type / __size_t -> usizeandssize_t -> isize. __size_t is an internal type that describes the return value of sizeofToStringdesugars its type by default, so I gave it a flag to leave scalars alone, and madesearch(QualType)look for the sugared type before the desugared one:This is needed because size_t isn't a real type, just a typedef over an integer.
Converter, I added an extra default argument toConvert,ConvertRValueandConvertFreshRValue:std::optional<clang::QualType> implicit_convert_to. In Clang, bothsize_tandunsigned longare represented as the same type, but in Rust,usizeandu64are different types, an implicit cast between the two is not allowed. To solve this,Convertis the single point of adding a cast between 2 types that share the same underlying type in C but have different types in Rust, this is decided byNeedsImplicitScalarCast.Callers of
Converthave to pass the optionalimplicit_convert_toin order to trigger the scalar cast. Callers pass the target type, for exampleConvertFreshRValue(rhs, lhs->getType());in ConvertAssignment, andConverttakes care of the explicit Rust call if needed. Binary operations do the same using GetOperandImplicitConversionTarget, which converts both arguments to the same Rust type.