Skip to content

refactor: compare foreign function declarations by resolved type - #1936

Open
ahomescu wants to merge 3 commits into
ahomescu/fix_reorganize_definitions/mismatched_extern_arityfrom
ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs
Open

refactor: compare foreign function declarations by resolved type#1936
ahomescu wants to merge 3 commits into
ahomescu/fix_reorganize_definitions/mismatched_extern_arityfrom
ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs

Conversation

@ahomescu

Copy link
Copy Markdown
Contributor

Stack created with GitHub Stacks CLIGive Feedback 💬

@ahomescu
ahomescu changed the base branch from ahomescu/fix_reorganize_definitions/preserve_extern_link_name to ahomescu/fix_reorganize_definitions/mismatched_extern_arity July 25, 2026 00:57
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 3e52313 to af3c69c Compare July 25, 2026 01:40
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from af3c69c to fedfec1 Compare July 25, 2026 01:57
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from fedfec1 to f4c8e2f Compare July 25, 2026 02:08
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from f4c8e2f to 47b3cf0 Compare July 25, 2026 02:11
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch 2 times, most recently from 732a60c to 10990b4 Compare July 25, 2026 02:35
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 10990b4 to 60a774f Compare July 25, 2026 05:09
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 60a774f to 2bff68f Compare July 25, 2026 05:33
@ahomescu
ahomescu changed the base branch from ahomescu/fix_reorganize_definitions/mismatched_extern_arity to ahomescu/fix_reorganize_definitions/deterministic_externs July 25, 2026 05:41
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 2bff68f to 2d099d0 Compare July 25, 2026 05:41
@ahomescu
ahomescu changed the base branch from ahomescu/fix_reorganize_definitions/deterministic_externs to ahomescu/fix_reorganize_definitions/mismatched_extern_arity July 25, 2026 05:42
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 2d099d0 to 0380037 Compare July 25, 2026 05:42
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch 3 times, most recently from f423c43 to 8e87153 Compare July 25, 2026 06:16
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch 2 times, most recently from 15e6ee0 to 7bb56b6 Compare July 25, 2026 06:43
@ahomescu
ahomescu requested a review from thedataking July 25, 2026 06:43
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch 2 times, most recently from 1499b5b to 25aef51 Compare July 30, 2026 00:19
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 25aef51 to 82e9b1b Compare July 30, 2026 00:31
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 82e9b1b to 00ecfb8 Compare July 30, 2026 22:54
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 00ecfb8 to 43f8815 Compare July 30, 2026 22:56
ahomescu added 3 commits July 30, 2026 15:57
Regression test: `test_reorganize_foreign_fn_type_identity`
(`tests/snapshots/reorganize_foreign_fn_type_identity.rs`). Each translation
unit has its own `buf`, and the two differ in field visibility, so the
transform correctly keeps them apart and renames the second to `buf_1`. Both
units then declare `fill(b: *mut buf)` — spelled identically, but naming a
different type in each unit.

`find_foreign_item` compares the two with `compatible_fn_prototypes`, which
resolves the parameter types through `opt_node_type`. A foreign item has no
body and so no typeck results to resolve against, and the comparison falls
through to `unnamed_equiv`, a purely syntactic check that sees `*mut buf`
against `*mut buf` and reports a match. The second declaration is dropped
and both call sites are pointed at the first, so the caller written against
`buf_1` now passes it to a function taking `*mut buf`:

    error[E0308]: mismatched types

This is the same defect that makes the output of `test_reorganize_definitions`
fail to compile, reduced to the two types and one function that cause it.
Comparing foreign functions by resolved type routed the comparison through
`structural_eq_tys_impl`, whose array arm lets a zero-length array match an
array of any length. That leniency is there for an `extern` array
declaration, which C lets omit the length that the definition gives, and
which we translate to a zero length; it does not hold inside a function
signature. `*mut [c_int; 0]` and `*mut [c_int; 4]` are distinct Rust types
with no coercion between them, so two declarations that differ only there
are not interchangeable at a call site.

`test_reorganize_foreign_fn_rename` regressed on exactly that: its two
`compute` declarations were collapsed into one and `b_call` was rewritten
to call a function it cannot pass its argument to, an `E0308` in the
output. The syntactic path this replaced happened to reject the pair
because it compared the written-out lengths.

`TypeCompare` now carries an `exact_array_lens` flag, off by default so
that the `extern` array declaration it exists for keeps matching its
definition, and on for `compatible_fn_sigs` and `compatible_fn_prototypes`.
An array length reached through a signature, including one nested in a
pointed-to struct, has to match exactly. No snapshot changed: the
`statfs64` unification and the `statvfs` separation from the previous
commit both still hold.
`find_foreign_item` decided whether two foreign functions were the same by
handing their `FnDecl`s to `compatible_fn_prototypes`. That resolves each
parameter through `opt_node_type`, but a foreign item has no body and so no
typeck results, so every lookup came back empty and the comparison fell
through to `unnamed_equiv` — a syntactic check with no notion of what a name
resolves to. Two declarations from different modules whose parameters were
merely spelled alike were reported identical, one was dropped, and its
callers were rewritten to a function taking a different type.

`compatible_foreign_fns` now asks `tcx` for each declaration's signature and
compares those with `compatible_fn_sigs`, which resolves the types properly.
`match_exports` already compared foreign functions against external ones
this way; this brings the crate-local comparison in line with it. The
syntactic path is kept as a fallback for a signature that will not resolve,
which is also why the arity check added earlier still matters.

Structurally identical types from different modules still compare equal, so
this only separates declarations that genuinely differ: the `statfs64`
declarations in `test_reorganize_definitions` are still unified with libc's,
while its two `statvfs` declarations are now kept apart, and its output
loses the two `E0308` errors. The remaining `E0603` there is a separate
defect, fixed next.
@ahomescu
ahomescu force-pushed the ahomescu/fix_reorganize_definitions/compare_extern_fn_sigs branch from 43f8815 to a7399e5 Compare July 30, 2026 22:58
@thedataking
thedataking requested a review from fw-immunant July 31, 2026 22:28
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.

1 participant