Why is the same version of `syn` compiled twice?

Running cargo build --timings shows that crate syn is compiled twice:

|1. |syn v2.0.89 |24.5s |15.5s (63%) |clone-impls, default, derive, extra-traits, full, parsing, printing, proc-macro, visit, visit-mut|
|2. |syn v2.0.89 |22.3s |15.8s (71%) |clone-impls, default, derive, full, parsing, printing, proc-macro|

I was under the impression that cargo's "feature unification" would unify these two.
Running commands like cargo tree -f "{p} {f}" only shows dependencies to first variant.

It's hard to tell without any information. Does cargo tree -e features -i syn provide more clues? I assume it's resolver 2?

I'm not sure how the features resolve in the presence of cfg(not(...)) attributes; I see there's a cfg(not(extra-traits)), but it's only minor (a non-public declarative macro).

1 Like

Thanks! Running your command shows that the issue is connected to mirror-mirror crate.
Can be reproduced by running:

cargo new syn_twice
cd syn_twice
cargo add mirror-mirror
cargo build --timings

Typically, syn would only be used in macros and only be needed at compile time. With something that calls itself a "powerful reflection library", I would be surprise to me if this "mirror-mirror" crate has an actual run-time use for syn as dependency, too. Nonetheless, your dependency tree uses more of syn's features at compile time, which is why this duplication happens. More work at compile time, but less code needing to be linked into your compiled binary :wink:

1 Like

Would it be because that crate uses a proc macro on top of using syn?

Yeah, it has both compile time and a runtime dependency to syn too.

1 Like