Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

format! debug fails even though Debug is implemented #72197

Closed
vitorenesduarte opened this issue May 14, 2020 · 5 comments
Closed

format! debug fails even though Debug is implemented #72197

vitorenesduarte opened this issue May 14, 2020 · 5 comments
Labels
C-bug Category: This is a bug.

Comments

@vitorenesduarte
Copy link

I tried this code:

use std::fmt::Debug;

trait Trait {
    type A: Debug;
}

struct S1 {}

impl Trait for S1 {
    type A = u64;
}

#[derive(Debug)]
struct S2<T: Trait> {
    a: T::A,
}

fn main() {
    let s = S2::<S1> { a: 10 };
    format!("{:?}", s);
}

When trying to compile it, I get:

error[E0277]: `S1` doesn't implement `std::fmt::Debug`
  --> src/main.rs:20:21
   |
20 |     format!("{:?}", s);
   |                     ^ `S1` cannot be formatted using `{:?}`
   |
   = help: the trait `std::fmt::Debug` is not implemented for `S1`
   = note: add `#[derive(Debug)]` or manually implement `std::fmt::Debug`
   = note: required because of the requirements on the impl of `std::fmt::Debug` for `S2<S1>`
   = note: required by `std::fmt::Debug::fmt

The[derive(Debug)] alone seems to work since the program compiles without the format!.

Meta

rustc --version --verbose:

rustc 1.43.1 (8d69840ab 2020-05-04)
binary: rustc
commit-hash: 8d69840ab92ea7f4d323420088dd8c9775f180cd
commit-date: 2020-05-04
host: x86_64-apple-darwin
release: 1.43.1
LLVM version: 9.0
@vitorenesduarte vitorenesduarte added the C-bug Category: This is a bug. label May 14, 2020
@vitorenesduarte
Copy link
Author

vitorenesduarte commented May 14, 2020

I've tried to remove the #[derive(Debug)] and add the obvious implementation. The code now compiles.

use std::fmt::{self, Debug};

trait Trait {
    type A: Debug;
}

struct S1 {}

impl Trait for S1 {
    type A = u64;
}

struct S2<T: Trait> {
    a: T::A,
}

impl<T: Trait> Debug for S2<T> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "{:?}", self)
    }
}

fn main() {
    let s = S2::<S1> { a: 10 };
    format!("{:?}", s);
}

However, when I run it, I get:

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

@DutchGhost
Copy link
Contributor

DutchGhost commented May 14, 2020

use std::fmt::Debug;

trait Trait {
    type A: Debug;
}

struct S1 {}

impl Trait for S1 {
    type A = u64;
}

#[derive(Debug)]
struct S2<T: Trait> {
    a: T::A,
}

The generated Debug impl expanded is:

#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::fmt::Debug + Trait> ::core::fmt::Debug for S2<T>
where
    T::A: ::core::fmt::Debug,
{
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        match *self {
            S2 { a: ref __self_0_0 } => {
                let mut debug_trait_builder = f.debug_struct("S2");
                let _ = debug_trait_builder.field("a", &&(*__self_0_0));
                debug_trait_builder.finish()
            }
        }
    }
}

SinceS1 does NOT implement Debug, S2<S1> does not either, so a call to format!() fails

@DutchGhost
Copy link
Contributor

DutchGhost commented May 14, 2020

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

Here you call write!("{}", self), which calls the debug implementation of S2<T>, which calls the debug impl of S2<T> which calls....infinite recursion!

@jonas-schievink
Copy link
Contributor

You are running into #26925 and #57965, so closing in favor of those

@vitorenesduarte
Copy link
Author

thread 'main' has overflowed its stack
fatal runtime error: stack overflow

Here you call write!("{}", self), which calls the debug implementation of S2<T>, which calls the debug impl of S2<T> which calls....infinite recursion!

Thanks for pointing it out. Replacing self with self.a solves the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug.
Projects
None yet
Development

No branches or pull requests

3 participants