dtolnay / proc-macro-workshop

Learn to write Rust procedural macros  [Rust Latam conference, Montevideo Uruguay, March 2019]
Apache License 2.0
4k stars 1.01k forks source link

What is best way to print whole path #63

Closed gftea closed 1 year ago

gftea commented 1 year ago

Hi

For a Path type for Error::Fmt, how to print it exactly same as the code? When I convert it to tokenstream, then print it, it has space between path segments and punct.

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: Error::Fmt should sort before Error::Io
  --> tests/06-pattern-path.rs:33:13
   |
33 |             Error::Fmt(e) => write!(f, "{}", e),
   |             ^^^^^^^^^^
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error: Error :: Fmt should sort before Error :: Io
  --> tests/06-pattern-path.rs:33:13
   |
33 |             Error::Fmt(e) => write!(f, "{}", e),
   |             ^^^^^^^^^^

At present, I have to use quite a long expression to get the string

path
.segments
.iter()
.map(|seg| seg.ident.to_string())
.collect::<Vec<_>>()
.join("::");
dtolnay commented 1 year ago

That implementation looks fine to me.

Here is what I have in the reference solution, but it is effectively equivalent:

use crate::compare::Path;

impl Display for Path {
    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
        for (i, segment) in self.segments.iter().enumerate() {
            if i > 0 {
                formatter.write_str("::")?;
            }
            segment.fmt(formatter)?;
        }
        Ok(())
    }
}