-
-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
Make uniqueify_with generate deterministic macro names, to fix build failures #2797
Conversation
The following code will fail to compile after this change, because we made two identical macro calls and they get hashed to the same value. Which makes me think we should just hash as many things as we can get our hands on -- until Span::source_file / line / column are stabilised. #[macro_use]
extern crate rocket;
#[get("/")]
fn index() -> &'static str {
"GET"
}
mod module {
#[get("/")]
pub fn index() -> &'static str {
"whatever"
}
}
#[launch]
fn rocket() -> _ {
rocket::build().mount("/", routes![index])
}
|
One thing you can try is hashing the debug output of the relevant That being said, I'm not sure this is sufficient to avoid collisions. In particular, will this work if the route is generated by a declarative macro? |
cb9f324
to
8a1bb81
Compare
Good idea! It seems to have worked. That test case now compiles. I guess I should add it as an actual test case. |
Can you add both that test and a test that generates routes from a macro_rules macro? |
Done. I think that should cover it. |
core/codegen/src/syn_ext.rs
Outdated
// Use rustc_hash because it's deterministic, whereas the DefaultHasher | ||
// in std is nondeterministic. This prevents problems where compiling |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't believe this is necessarily true. DefaultHasher::new()
always returns a SipHasher
with keys of 0
, so it should always hash to the same values and should thus be deterministic.
Overview
In a nutshell, some slightly exotic ways of compiling rocket with rustc fail due to nondeterminism in
rocket_codegen
leading to rustc correctly noticing that you've compiled two incompatible versions ofrocket
. The nondeterminsim is inIdentExt::uniqueify_with
.I believe you can fix this by just doing it deterministically. I don't think it needs to be random. Reviewers please help determine if the things that are hashed for the route macro are enough to avoid collisions in the generated code. Specifically these. My gut feeling is you will also want the HTTP method to be hashed.
Rocket/core/codegen/src/attribute/route/mod.rs
Lines 211 to 215 in 2a1afd1
Background -- rocket
See this for why random identifiers are being generated at all. #964
It currently does so using a combination of
and some deterministic ones
#[route]
macrorocket_codegen::export! { macro_rules! name {... } }
The randomness seems like someone tried really hard to make it as random as possible. I don't think anything but the DefaultHasher's initialization was necessary to achieve that, and I put it to you that no randomness is required at all.
Background -- rustc
--cfg
flag,--Cmetadata
flag, all the dependencies, or something like that.My particular circumstances that led to experiencing this issue are:
rustc
on every crate -- one for metadata only, and one for codegen.cargo check
metadata is not reused forcargo build
and when you do runcargo build
, the metadata + codegen outputs are produced during the same rustc invocation. (Incidentally this is why runningcargo check
does not make a subsequentcargo build
any faster.)The build errors you get look like
found possibly newer version of crate rocket which thing depends on
. Almost all of the mentions of this error online are due to people compiling libstd / libcore from scratch and linking the wrong version, or compiler developers mixing different stages. Rustc does very reliably compute SVH, so generally when it's telling you this, it's not lying.Side note
Apart from the build failure, not ever being able to build identical copies of rocket / rocket applications is a problem if your build tool does caching and yeets the build products off to be used on other machines. That's a whole other can of beans.
Illustration
Not a repro because too many steps and buck2 is complicated. But I reduced rocket down to a few lines of code to discover the cause of the build failure, so may as well show you.
Notable compile steps:
And the binary build fails as below: