git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH v2 01/10] doc: define unambiguous type mappings across C and Rust

From
Ezekiel Newren <ezekielnewren@gmail.com>
Date
Nov 6, 2025, 22:52 UTC
Message-ID
<CAH=ZcbA25eyMhQpvK7eh=ydZkg5RdzbdRFEdj-22T+d1VuTazA@mail.gmail.com>
In-Reply-To
<995f77a3-b94c-46df-87d3-22c7b2a3c762@gmail.com>
On Thu, Nov 6, 2025 at 2:55 AM Phillip Wood <phillip.wood123@gmail.com> wrote:
Show 11 quoted lines
>
> Hi Ezekiel
>
> On 29/10/2025 22:19, Ezekiel Newren via GitGitGadget wrote:
> > From: Ezekiel Newren <ezekielnewren@gmail.com>
> >
> > Document other nuances with crossing the FFI boundary. Other language
> > mappings may be added in the future.
>
> Thanks for adding this, I've left a few comments below. Overall I
> thought it was very well written.
Thanks.

I felt it was necessary since C vs Rust types keep coming up over and over again. I'm flexible with the wording of this document. I was just trying to convey a firm and clear stance on what is and isn't proper in Git.

Show 57 quoted lines
> I tried building an html version of
> this but even after adding it to the list of TECH_DOCS in
> Documentation/Makefile with
>
> diff --git a/Documentation/Makefile b/Documentation/Makefile
> index 47208269a2e..2699f0b24af 100644
> --- a/Documentation/Makefile
> +++ b/Documentation/Makefile
> @@ -143,6 +143,7 @@ TECH_DOCS += technical/shallow
>   TECH_DOCS += technical/sparse-checkout
>   TECH_DOCS += technical/sparse-index
>   TECH_DOCS += technical/trivial-merge
> +TECH_DOCS += technical/unambiguous-types
>   TECH_DOCS += technical/unit-tests
>   SP_ARTICLES += $(TECH_DOCS)
>   SP_ARTICLES += technical/api-index
>
> it fails with
>
> $ make -C Documentation/ technical/unambiguous-types.html
>                                        Merge branch
> 'ps/object-source-loose' into seen
> make: Entering directory '/home/phil/src/git/Documentation'
>      GEN asciidoc.conf
>      * new asciidoc flags
>      ASCIIDOC technical/unambiguous-types.html
> asciidoc: ERROR: unambiguous-types.adoc: line 139: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 162: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 177: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 187: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 199: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 213: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> asciidoc: ERROR: unambiguous-types.adoc: line 224: undefined filter
> attribute in command: source-highlight --gen-version -f xhtml -s
> {language} {src_numbered?--line-number=' '} {src_tab?--tab={src_tab}}
> {args=}
> make: *** [Makefile:396: technical/unambiguous-types.html] Error 1
> make: *** Deleting file 'technical/unambiguous-types.html'
> make: Leaving directory '/home/phil/src/git/Documentation'

I've never created documentation for Git before, so this helps. I'll incorporate your suggestions.

Show 12 quoted lines
> > +== Character types
> > +
> > +This is where C and Rust don't have a clean one-to-one mapping. A C `char` is
> > +an 8-bit type that is signless (neither signed nor unsigned)
>
> I found this a bit confusing. Isn't the signedness of "char"
> implementation defined rather than it being "signless"
>
> > which causes
> > +problems with e.g. `make DEVELOPER=1`.
>
> I'm not sure what this is referring to - maybe -Wsign-compare?

When I build Git with `make DEVELOPER=1` and I compare uint8_t with char it complains about a difference in signedness. When I compare int8_t with char it also complains about a difference in signedness. So it is implementation defined, but it's also neither signed nor unsigned according to DEVELOPER=1 since it complains either way.

Show 14 quoted lines
> > Rust's `char` type is an unsigned 32-bit
> > +integer that is used to describe Unicode code points. Even though a C `char`
> > +is the same width as `u8`, `char` should be converted to u8 where it is
> > +describing bytes in memory.
>
> I'm dreading the point where we start sharing "struct strbuf" with rust
> and have to change the "buf" member from "char*" to "uint8_t*". While it
> is not used in the xdiff code it is ubiquitous everywhere else and there
> are lots of places where be pass the "buf" member to functions expecting
> a "char*".
>
>         git grep -E '(\.|->)buf\W'
>
> has over 4000 matches

This is why I started in Xdiff since its code is mostly isolated. I think that we might have to bite the bullet and deal with the ugly mapping of char on the C side and u8 on the Rust side when dealing with strbuf. Maybe as we translate more of C into Rust someone will have a better suggestion. I think my ivec type would be better since strbuf is almost a special case of my ivec type, but dealing with strbuf is outside the scope of this patch series.

Show 17 quoted lines
> > If a C `char` is not describing bytes, then it
> > +should be converted to a more accurate unambiguous type.
>
> That's a good point.
>
> > +While you could specify `char` in the C code and `u8` in Rust code, it's not as
> > +clear what the appropriate type is, but it would work across the FFI boundary.
> > +However the bigger problem comes from code generation tools like cbindgen and
> > +bindgen. When cbindgen see u8 in Rust it will generate uint8_t on the C side
> > +which will cause differ in signedness warnings/errors. Similarly if bindgen
> > +see `char` on the C side it will generate `std::ffi::c_char` which has its own
> > +problems.
>
> Yeah, we definitely don't want to be using "std::ffi::c_char" in our
> rust implementations. I do wonder if we might want to use it (or CStr)
> judiciously in function parameters and immediately convert it to u8 in
> the function body where the function is called from C though.
That's basically the design pattern I've been using.

In many of my translations from C to Rust I create a Rust stub function that takes pointer types and wraps them into safe types which then get handed off to a safe Rust function. I think that in the cases where CString/CStr is required the Rust stub function would create a &[u8] slice for the safe function to operate on.

Show 13 quoted lines
> > +=== Notes
> > +^1^ This is only true if stdbool.h (or equivalent) is used. +
> > +^2^ C does not enforce IEEE-754 compatibility, but Rust expects it. If the
> > +platform/arch for C does not follow IEEE-754 then this equivalence does not
> > +hold. Also, it's assumed that `float` is 32 bits and `double` is 64, but
> > +there may be a strange platform/arch where even this isn't true. +
> > +^3^ C also defines uintptr_t, but this should not be used in Git. +
> > +^4^ C also defines ssize_t and intptr_t, but these should not be used in Git. +
>
> [u]intptr_t and ssize_t are used in git already. As Junio has pointed
> out there are sane uses for these types but we don't want to use them in
> structs or function parameters where the struct or function is shared
> with rust.

You're right, I should update the phrasing. Something like: "These types shouldn't be used if their explicit purpose is for FFI. Whether as a field in a struct or part of a function signature." I'll update the wording.

Show 6 quoted lines
> > +
> > +== Problems with std::ffi::c_* types in Rust
> > +TL;DR: They're not guaranteed to match C types for all possible C
> > +compilers/platforms/architectures.
>
> Is this official policy of the rust project?

No, this is a personal inference based on logical deduction. The c_* definitions have changed over time with new Rust version releases, and Git targets more platforms/architectures than what Rust officially supports. While it's not guaranteed that it won't work everywhere. It's also not guaranteed to work everywhere either. On top of that we're targeting 1.63.0 who's c_* definitions are different in 1.89.0 which I show an example of with c_long_definition. Can anyone say with certainty that Rust got these mappings right or wrong for all possible C compilers/architectures/platforms? If so (which I highly doubt) could someone provide a link?

Previous: Phillip WoodNext: Phillip Wood
Message 41 of 118 in “Xdiff cleanup part2”
  1. 0/9 Xdiff cleanup part2Ezekiel Newren via GitGitGadget, Oct 15, 2025
  2. 1/9 xdiff: use ssize_t for dstart/dend, make them last in xdfile_tEzekiel Newren via GitGitGadget, Oct 15, 2025
  3. Phillip WoodOct 21, 2025
  4. Junio C HamanoOct 21, 2025
  5. Ezekiel NewrenOct 22, 2025
  6. Junio C HamanoOct 22, 2025
  7. Ezekiel NewrenOct 22, 2025
  8. 2/9 xdiff: make xrecord_t.ptr a uint8_t instead of charEzekiel Newren via GitGitGadget, Oct 15, 2025
  9. Kristoffer HaugsbakkOct 16, 2025
  10. Patrick SteinhardtOct 21, 2025
  11. Ezekiel NewrenOct 22, 2025
  12. Phillip WoodOct 21, 2025
  13. Junio C HamanoOct 21, 2025
  14. Phillip WoodOct 22, 2025
  15. Ezekiel NewrenOct 22, 2025
  16. 3/9 xdiff: use size_t for xrecord_t.sizeEzekiel Newren via GitGitGadget, Oct 15, 2025
  17. 4/9 xdiff: use unambiguous types in xdl_hash_record()Ezekiel Newren via GitGitGadget, Oct 15, 2025
  18. Patrick SteinhardtOct 21, 2025
  19. Ezekiel NewrenOct 22, 2025
  20. Patrick SteinhardtOct 23, 2025
  21. 5/9 xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hashEzekiel Newren via GitGitGadget, Oct 15, 2025
  22. Ezekiel NewrenOct 20, 2025
  23. Junio C HamanoOct 21, 2025
  24. Patrick SteinhardtOct 21, 2025
  25. Phillip WoodOct 21, 2025
  26. Chris TorekOct 21, 2025
  27. Ezekiel NewrenOct 22, 2025
  28. 6/9 xdiff: make xdfile_t.nrec a size_t instead of longEzekiel Newren via GitGitGadget, Oct 15, 2025
  29. 7/9 xdiff: make xdfile_t.nreff a size_t instead of longEzekiel Newren via GitGitGadget, Oct 15, 2025
  30. 8/9 xdiff: change rindex from long to size_t in xdfile_tEzekiel Newren via GitGitGadget, Oct 15, 2025
  31. Patrick SteinhardtOct 21, 2025
  32. Ezekiel NewrenOct 22, 2025
  33. Patrick SteinhardtOct 23, 2025
  34. 9/9 xdiff: rename rindex -> reference_indexEzekiel Newren via GitGitGadget, Oct 15, 2025
  35. Junio C HamanoOct 15, 2025
  36. Phillip WoodOct 21, 2025
  37. Junio C HamanoOct 21, 2025
  38. 00/10 Xdiff cleanup part2Ezekiel Newren via GitGitGadget, Oct 29, 2025
  39. 01/10 doc: define unambiguous type mappings across C and RustEzekiel Newren via GitGitGadget, Oct 29, 2025
  40. Phillip WoodNov 6, 2025
  41. Ezekiel NewrenNov 6, 2025
  42. Phillip WoodNov 9, 2025
  43. 02/10 xdiff: use ssize_t for dstart/dend, make them last in xdfile_tEzekiel Newren via GitGitGadget, Oct 29, 2025
  44. Phillip WoodNov 6, 2025
  45. Ezekiel NewrenNov 6, 2025
  46. 03/10 xdiff: make xrecord_t.ptr a uint8_t instead of charEzekiel Newren via GitGitGadget, Oct 29, 2025
  47. Phillip WoodNov 6, 2025
  48. Ezekiel NewrenNov 6, 2025
  49. Phillip WoodNov 6, 2025
  50. Ezekiel NewrenNov 6, 2025
  51. 04/10 xdiff: use size_t for xrecord_t.sizeEzekiel Newren via GitGitGadget, Oct 29, 2025
  52. 05/10 xdiff: use unambiguous types in xdl_hash_record()Ezekiel Newren via GitGitGadget, Oct 29, 2025
  53. 06/10 xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hashEzekiel Newren via GitGitGadget, Oct 29, 2025
  54. Phillip WoodNov 6, 2025
  55. Ezekiel NewrenNov 6, 2025
  56. 07/10 xdiff: make xdfile_t.nrec a size_t instead of longEzekiel Newren via GitGitGadget, Oct 29, 2025
  57. 08/10 xdiff: make xdfile_t.nreff a size_t instead of longEzekiel Newren via GitGitGadget, Oct 29, 2025
  58. 09/10 xdiff: change rindex from long to size_t in xdfile_tEzekiel Newren via GitGitGadget, Oct 29, 2025
  59. 10/10 xdiff: rename rindex -> reference_indexEzekiel Newren via GitGitGadget, Oct 29, 2025
  60. Junio C HamanoOct 30, 2025
  61. 00/10 Xdiff cleanup part2Ezekiel Newren via GitGitGadget, Nov 11, 2025
  62. 01/10 doc: define unambiguous type mappings across C and RustEzekiel Newren via GitGitGadget, Nov 11, 2025
  63. Junio C HamanoNov 11, 2025
  64. Junio C HamanoNov 11, 2025
  65. 02/10 xdiff: use ptrdiff_t for dstart/dendEzekiel Newren via GitGitGadget, Nov 11, 2025
  66. Junio C HamanoNov 11, 2025
  67. 03/10 xdiff: make xrecord_t.ptr a uint8_t instead of charEzekiel Newren via GitGitGadget, Nov 11, 2025
  68. Junio C HamanoNov 11, 2025
  69. 04/10 xdiff: use size_t for xrecord_t.sizeEzekiel Newren via GitGitGadget, Nov 11, 2025
  70. Junio C HamanoNov 11, 2025
  71. Ezekiel NewrenNov 14, 2025
  72. Junio C HamanoNov 14, 2025
  73. 05/10 xdiff: use unambiguous types in xdl_hash_record()Ezekiel Newren via GitGitGadget, Nov 11, 2025
  74. 06/10 xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hashEzekiel Newren via GitGitGadget, Nov 11, 2025
  75. Junio C HamanoNov 11, 2025
  76. Ezekiel NewrenNov 14, 2025
  77. Junio C HamanoNov 14, 2025
  78. 07/10 xdiff: make xdfile_t.nrec a size_t instead of longEzekiel Newren via GitGitGadget, Nov 11, 2025
  79. 08/10 xdiff: make xdfile_t.nreff a size_t instead of longEzekiel Newren via GitGitGadget, Nov 11, 2025
  80. 09/10 xdiff: change rindex from long to size_t in xdfile_tEzekiel Newren via GitGitGadget, Nov 11, 2025
  81. 10/10 xdiff: rename rindex -> reference_indexEzekiel Newren via GitGitGadget, Nov 11, 2025
  82. Junio C HamanoNov 11, 2025
  83. Ezekiel NewrenNov 14, 2025
  84. 00/10 Xdiff cleanup part2Ezekiel Newren via GitGitGadget, Nov 14, 2025
  85. 01/10 doc: define unambiguous type mappings across C and RustEzekiel Newren via GitGitGadget, Nov 14, 2025
  86. Ramsay JonesNov 15, 2025
  87. Ben KnobleNov 15, 2025
  88. Ramsay JonesNov 15, 2025
  89. Junio C HamanoNov 15, 2025
  90. D. Ben KnobleNov 15, 2025
  91. Junio C HamanoNov 15, 2025
  92. Junio C HamanoNov 17, 2025
  93. Ramsay JonesNov 17, 2025
  94. 02/10 xdiff: use ptrdiff_t for dstart/dendEzekiel Newren via GitGitGadget, Nov 14, 2025
  95. 03/10 xdiff: make xrecord_t.ptr a uint8_t instead of charEzekiel Newren via GitGitGadget, Nov 14, 2025
  96. Junio C HamanoNov 15, 2025
  97. Ezekiel NewrenNov 18, 2025
  98. 04/10 xdiff: use size_t for xrecord_t.sizeEzekiel Newren via GitGitGadget, Nov 14, 2025
  99. 05/10 xdiff: use unambiguous types in xdl_hash_record()Ezekiel Newren via GitGitGadget, Nov 14, 2025
  100. 06/10 xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hashEzekiel Newren via GitGitGadget, Nov 14, 2025
  101. 07/10 xdiff: make xdfile_t.nrec a size_t instead of longEzekiel Newren via GitGitGadget, Nov 14, 2025
  102. 08/10 xdiff: make xdfile_t.nreff a size_t instead of longEzekiel Newren via GitGitGadget, Nov 14, 2025
  103. 09/10 xdiff: change rindex from long to size_t in xdfile_tEzekiel Newren via GitGitGadget, Nov 14, 2025
  104. 10/10 xdiff: rename rindex -> reference_indexEzekiel Newren via GitGitGadget, Nov 14, 2025
  105. 00/10 Xdiff cleanup part2Ezekiel Newren via GitGitGadget, Nov 18, 2025
  106. 01/10 doc: define unambiguous type mappings across C and RustEzekiel Newren via GitGitGadget, Nov 18, 2025
  107. Ramsay JonesNov 18, 2025
  108. Junio C HamanoNov 19, 2025
  109. 02/10 xdiff: use ptrdiff_t for dstart/dendEzekiel Newren via GitGitGadget, Nov 18, 2025
  110. 03/10 xdiff: make xrecord_t.ptr a uint8_t instead of charEzekiel Newren via GitGitGadget, Nov 18, 2025
  111. 04/10 xdiff: use size_t for xrecord_t.sizeEzekiel Newren via GitGitGadget, Nov 18, 2025
  112. 05/10 xdiff: use unambiguous types in xdl_hash_record()Ezekiel Newren via GitGitGadget, Nov 18, 2025
  113. 06/10 xdiff: split xrecord_t.ha into line_hash and minimal_perfect_hashEzekiel Newren via GitGitGadget, Nov 18, 2025
  114. 07/10 xdiff: make xdfile_t.nrec a size_t instead of longEzekiel Newren via GitGitGadget, Nov 18, 2025
  115. 08/10 xdiff: make xdfile_t.nreff a size_t instead of longEzekiel Newren via GitGitGadget, Nov 18, 2025
  116. 09/10 xdiff: change rindex from long to size_t in xdfile_tEzekiel Newren via GitGitGadget, Nov 18, 2025
  117. 10/10 xdiff: rename rindex -> reference_indexEzekiel Newren via GitGitGadget, Nov 18, 2025
  118. Junio C HamanoNov 18, 2025

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.