Skip to content

fix: generate a Debug impl for NewType/NewTypeDeref wrappers when the inner type only manually implements it - #3411

Open
dhmztr wants to merge 1 commit into
rust-lang:mainfrom
dhmztr:fix/newtype-alias-missing-debug-impl
Open

fix: generate a Debug impl for NewType/NewTypeDeref wrappers when the inner type only manually implements it#3411
dhmztr wants to merge 1 commit into
rust-lang:mainfrom
dhmztr:fix/newtype-alias-missing-debug-impl

Conversation

@dhmztr

@dhmztr dhmztr commented Jul 28, 2026

Copy link
Copy Markdown

Summary

Fixes #3268.

When using --impl-debug together with --default-alias-style=new_type or new_type_deref, a newtype wrapper around a type that only has a manual Debug impl (e.g. a union, which can never #[derive(Debug)] and always gets a hand-written impl instead) ends up with no Debug impl at all — neither derived nor manual. Any containing struct that references the wrapper still generates a manual Debug impl formatting the field with {:?}, so the generated code fails to compile:

error[E0277]: `UnionAlias` doesn't implement `Debug`

This is the exact repro and error from the issue.

Root cause

Type::codegen's AliasVariation::NewType | AliasVariation::NewTypeDeref branch only ever builds a #[derive(...)] list via derives_of_item. Unlike CompInfo::codegen (the regular struct/union codegen path), it never falls back to generating a manual impl Debug when Debug isn't in the derivable set.

Fix

Mirror the same "not derivable → generate a manual impl instead, if --impl-debug and friends allow it" logic that CompInfo::codegen already has (codegen/mod.rs:2588-2593 / 2931-2932), for the newtype wrapper case. The generated impl delegates via f.debug_tuple(...).field(&self.0).finish(), matching what #[derive(Debug)] would produce for a tuple struct (including correct {:#?} pretty-printing).

Test plan

  • Reproduced the exact compile failure from the issue against unmodified main (rustc confirms E0277, same as the report)
  • New regression test issue-3268-newtype-deref-union-debug.h/.rs, using the issue's exact repro
  • Confirmed the fixed output actually compiles (rustc --crate-type lib on the generated bindings)
  • Full bindgen-tests corpus passes aside from 2 pre-existing, unrelated failures also present on unmodified main (a toolchain-version-dependent const-generics codegen difference, and a dump_preprocessed_input test needing the clang CLI binary rather than just libclang)
  • cargo clippy -- -D warnings clean

Scope note

The issue's second comment describes a related-looking but distinct bug (a struct field is silently omitted from the generated Debug format string when its type is a stdint.h typedef like uint32_t). I wasn't able to reproduce that one with several plausible flag/header combinations in my environment, so I'm leaving it out of this PR rather than guessing at a fix for behavior I can't actually observe. Happy to take a look if someone can share a minimal, reliably-reproducing case.

…en the inner type only has a manual impl

`AliasVariation::NewType`/`NewTypeDeref` newtype wrapper structs only
ever got a `#[derive(...)]` attribute list built from
`derives_of_item`. If the wrapped type itself doesn't derive `Debug`
(e.g. a union, which always gets a hand-written `impl Debug` via
`--impl-debug` since unions can't derive it), the wrapper ended up
with no `Debug` impl at all - neither derived nor manual.

Any struct containing such a wrapper still generates a manual
`Debug` impl that formats the field with `{:?}`, which then fails to
compile with `` `Foo` doesn't implement `Debug` ``, since the
newtype's own `Debug` is missing entirely.

This mirrors the same "does this derive, and if not, do we need a
manual impl" logic that `CompInfo::codegen` already applies to
regular structs/unions, applied to the newtype wrapper case.

Fixes rust-lang#3268
Copilot AI review requested due to automatic review settings July 28, 2026 21:10

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

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.

impl_debug(true) and default_alias_style(NewTypeDeref) broken for C unions with typedef aliases

2 participants