Skip to content

Issue with non-lifetime trait used ion associated type in HRTB context #66817

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

Closed
Lucretiel opened this issue Nov 27, 2019 · 1 comment
Closed

Comments

@Lucretiel
Copy link
Contributor

Consider this example (playground):

use std::fmt::{self, Display, Formatter};

// This struct provides a `Display` implementation that iterates over
// &collection, writing each element in sequence.
pub struct Concat<C> {
    collection: C,
}

impl<C> Display for Concat<C>
    where for <'a> &'a C: IntoIterator,
    for <'a> <&'a C as IntoIterator>::Item: Display,
{
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        self.collection.into_iter().try_for_each(move |element| {
            element.fmt(f)
        })
    }
}

fn main() {
    let collection = vec![1u32, 2, 3, 4, 5, 6];
    let concat = Concat { collection };
    println!("{}", concat);
}

We define a struct, Concat, that provides a Display implementation by immutably iterating over collection and writing each element to f in sequence. This trait implementation depends on the following trait bounds:

for<'a> &'a C: IntoIterator,  // immutable iteration
for<'a> <&'a C as IntoIterator>::Item: Display  // Items are displayable

However, the latter trait bound appears to not be binding correctly, as the example code fails to compile with the following error:

error[E0277]: `<&'a std::vec::Vec<u32> as std::iter::IntoIterator>::Item` doesn't implement `std::fmt::Display`
  --> src/main.rs:23:20
   |
23 |     println!("{}", concat);
   |                    ^^^^^^ `<&'a std::vec::Vec<u32> as std::iter::IntoIterator>::Item` cannot be formatted with the default formatter
   |
   = help: the trait `for<'a> std::fmt::Display` is not implemented for `<&'a std::vec::Vec<u32> as std::iter::IntoIterator>::Item`
   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
   = note: required because of the requirements on the impl of `std::fmt::Display` for `Concat<std::vec::Vec<u32>>`
   = note: required by `std::fmt::Display::fmt`

It's worth noting that the code does compile if you don't include the usage in main. I've tried a lot of variations on this code, but the issue seems to boil down to the fact that Rust seems to consider for<'a> Display different than display.

I posted this issue on stackoverflow, and got a response with the following workaround:

mod private {
    use std::fmt;
    pub trait Display<'a>: fmt::Display {}
    impl<'a, T> Display<'a> for T where T: fmt::Display {}
}

impl<C> fmt::Display for Concat<C>
where
    for<'a> &'a Container: IntoIterator,
    for<'a> <&'a Container as IntoIterator>::Item: private::Display<'a>,
...

In summary, there appears to be an issue with binding an associated type to a trait in an HRTB context.

@Lucretiel
Copy link
Contributor Author

Did some searching; this is a duplicate of #56556

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

No branches or pull requests

1 participant