-
Notifications
You must be signed in to change notification settings - Fork 2.4k
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
Implement future incompatibility report support #8825
Implement future incompatibility report support #8825
Conversation
r? @Eh2406 (rust_highfive has picked a reviewer for you, use r? to override) |
This can be tested on https://github.com/Aaron1011/arrayinto. The current output: Building:
Report:
|
src/cargo/core/compiler/mod.rs
Outdated
@@ -913,6 +915,10 @@ fn build_base_args( | |||
.env("RUSTC_BOOTSTRAP", "1"); | |||
} | |||
|
|||
if bcx.config.cli_unstable().future_incompat_report { |
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.
This check doesn't get taken into account by Cargo's caching - adding/removing this flag from cargo build
will not cause anything to rebuilt. I'm unsure how big of an issue this is, since all of this will go away once things get stabilized.
Thanks! I wouldn't worry about the caching of the As for errors, the answer is "it depends". Most of Cargo uses string-based errors with anyhow, and most errors are propagated with I would recommend moving the code in the Since this is modifying the It looks like you already found As for tests, in the short term I think it would be fine just to pick a warning that is unlikely to change soon. An alternative would be to create a fake rustc that emits the appropriate JSON (the tests do that in several places like this). But that wouldn't be testing that it actually integrates with the real rustc properly. Another alternative would be to embed a fake lint in rustc directly, but I'm not sure if that's necessary. As for handling canceled builds, it looks like you have support for that, which looks good to me. Is there a specific sequence of interactions that you are concerned about? Let me know if you have any specific questions or particular areas you'd like me to look at. There's also the new Contributor Guide which briefly provides some overviews of things like error handling. If there's something missing there, it may be useful to help highlight what needs expanding. |
If a user performed the following actions:
Then 'stale' warnings would be shown. I'm not sure that this really matters - I would expect people who really care about these warnings to have the commands run on CI, where they would always run to completion. |
Yea, I wouldn't worry to much about that specific sequence. We can always gauge later if people run into confusing situations or stale entries or whatever. It should be relatively easy to tweak and change this command. When reading the file, it might be good to be somewhat tolerant of errors (print anything if possible, and then display an error if it has problems deserializing it). That might help in case the file gets partially written or corrupted or was generated with a different version of Cargo that changes the format, but even that I wouldn't worry too much about. It's tough to predict every confusing circumstance, but here's one possibility:
I'm not sure how likely that is. I'm not too worried about it, but those are the kind of weird things that might confuse people. |
Oh, that's quite subtle. I think it would be a good idea to add a header (or footer) to the displayed message to tell the user which cargo command generated the report. |
Nice work! I have only one minor criticism about the implementation, which is that it only prints the offending crate's name and never prints the version. The RFC specifies that cargo shall print the version if there are multiple packages with that name in the cargo build graph. I'd personally extend it from the build graph to the entire DAG encoded in Cargo.lock, basically using the same logic that adds version numbers to crates in The reasoning why I asked for this to be added to the RFC was to make sure that users know which version is the offending one, so that they can base further actions on that. From the maintainer POV of crates that yield such warnings, it might even be very useful to have the version number printed all the time, because the warning might not happen at the latest version of the crate but an older one. If the report includes the older unmaintained version number, the maintainer can immediately close the issue report and tell people to update (if that's their choice, maybe they consider the older version branch still maintained, then they want to publish an upgrade). If there is no version number in the report, the maintainer has to ask first which version of the crate creates the warning, or investigate themselves whether the latest version of their crate creates that warning, or whether it's an older version. It's more helpful to be told by the users though, because that's the version the users care about. Maybe it's 3 semver breaks ago, one never knows (and it doesn't help that the download graph of crates.io only lists a limited number of versions). |
One of the reasons Cargo doesn't have the issues of reading files from old builds is that it's not something that Cargo does today, basically for all the reasons mentioned here because it's quite hard. A case like @ehuss mentions above seems pretty worrisome to me, and could perhaps be solved by adding a CLI flag to |
@pnkfelix What are your thoughts on @alexcrichton 's proposal? Would this require amending the RFC? |
Actually that's a good point @alexcrichton . If the |
This comment has been minimized.
This comment has been minimized.
3c2e8eb
to
c332fb6
Compare
cargo describe-future-incompatibilities
c332fb6
to
3bab550
Compare
@alexcrichton @est31: I've re-implemented this as a |
Oh, sorry, I just saw you sent an update here. I apologize, I did not post a comment sooner before you made some changes. We discussed this a little in our team meeting. There were two things that we discussed: The concern of the temporal nature of the cache: If the cache is deleted and recreated each time a command is run, there is some concern that it will be confusing if it fluctuates (based on what is built), and the time lag between seeing the notification, and the user running the command to display the report (during which other commands may have been run). I personally don't feel strongly about it, but would it be possible to change the on-disk representation to accommodate that concern? Perhaps it could retain the last N runs (maybe as separate files, or all in one file), and the command would by default display the last report, but have an option to display a specific (older) report? This is instead of using a flag as suggested above. Would you be willing to maybe go in that direction? The other thing we discussed was perhaps changing the top-level command name. I feel a little uncomfortable adding a lot of highly specific top-level cargo commands, since it can make it a little harder to document and for users to navigate. I was wondering what you think about changing it so that there is a I don't think in general that design tweaks need to go through any sort of process to amend the RFC. As long as the spirit of the original RFC is retained, I think it is up to each team to decide on the final implementation. |
Personally, I think this is very unlikely to be used:
|
f8e2c08
to
42112f0
Compare
}; | ||
// We always replay the output cache, | ||
// since it might contain future-incompat-report messages | ||
let work = replay_output_cache( |
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.
This runs the risk of slowing down incremental compiles since this may do nontrivial work for all upstream crates (which can be a lot), can you try to do some testing locally to see what the impact is?
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 tested with actix-web
(211 dependencies) - without running any kind of precise benchmarking, it looks like this may have increased the runtime of cargo build
(with a full cache) by a few hundredths of a second (0.08 to 0.09 seconds before, 0.11 to 0.12 seconds after).
I think this worst case for this change would be:
- Running
cargo build -vv
on a compilation graph with a significant number of normal upstream warnings. - Repeatedly running
cargo build
with the cache prepared bycargo build -vv
, which cauess Cargo to process and discard a large number of cached diagnostic messages.
However, this seems like a pretty unlikely scenarion, and I haven't been able to measure any kind of significant impact locally (testing with actix-web
again).
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.
Drive by comment, what system was this testing on? Can we check on windows?
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 tested on Arch Linux
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 agree that if we stick with this scheme that we'll want to test on Windows which typically has a slower filesystem than other platforms. Additionally the case I'm worried about is not when upstream compiles have output but rather they have no output so Cargo opens and closes a whole lot of files rapidly which can increase the latency of Cargo itself.
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.
Does this still need to happen unconditionally?
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.
Yes - we still want to display a note when running cargo build
without any arguments.
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.
This is another reason I would prefer to remove the flag on cargo build
in the initial implementation. I don't believe this change is necessary if it's a separate subcommand, right? If so that would make the performance issue moot.
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.
Hm ok I believe I'm wrong that this would change if there were only a subcommand. We'd still need to scrape files from past cached compilations to have the same report every time.
I don't think any testing of this has happened on Windows yet though?
The concern with a flag is that it may not be easy, or even possible to run cargo directly. For example, if it is wrapped in another build system (like In terms of the list, the intent is that the error message would specify exactly what you can run, maybe something like:
The user would copy and paste that, and see exactly which messages to display. If they ran the command without any options, it could just display the last report. I don't feel strongly about the difference, but I think the spirit of the RFC was to make it easy to view the report, regardless of what kind of environment cargo may be running in. |
@ehuss: It looks like @alexcrichton and @est31 both expressed a preference for a flag over a command. Is there any more work for me to do at the moment, or should I wait for a decision to be made? |
What about printing the path containing the report? Then you can just |
☔ The latest upstream changes (presumably #9175) made this pull request unmergeable. Please resolve the merge conflicts. |
51c872b
to
060e3e2
Compare
Rebased |
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.
Can you also add some brief documentation to unstable.md
?
I wanted to write a few more concerns about the implementation. I don't think any of these need to be addressed now, but I think they need to be considered eventually.
|
I'm concerned that this PR is adding an increasingly large amount of complexity to deal with a very unusual situation. See my previous comment #8825 (comment) - can you come up with a concrete sequence of commands that will actually cause a report to get overwritten with a different one (as opposed to an identical version of the existing report)? |
If I run
Can you help me understand what the complexity would be? I would expect it to just be a few lines of code. Something like: let mut on_disk_report = load_reports()?;
if on_disk_report.reports.len() > MAX_REPORTS {
on_disk_report.reports.remove(0);
}
let id = on_disk_report.reports.iter().max_by_key(|report| report.id).unwrap_or(0) + 1;
on_disk_report.reports.push(Report{id, contents});
on_disk_report.save()?; I'm fine if you don't want to implement it here, it can be done later. |
@ehuss: I'd like to implement that later, if it's okay with you. I think it would be good to get some version of this available on nightly, so that people can start testing this out in various scenarios. |
060e3e2
to
f0667ac
Compare
@ehuss: I've addressed your review comments. Could you add your other implementation concerns to the rustc tracking issue? |
☔ The latest upstream changes (presumably #9022) made this pull request unmergeable. Please resolve the merge conflicts. |
cc rust-lang/rust#71249 This implements the Cargo side of 'Cargo report future-incompat' Based on feedback from alexcrichton and est31, I'm implemented this a flag `--future-compat-report` on `cargo check/build/rustc`, rather than a separate `cargo describe-future-incompatibilities` command. This allows us to avoid writing additional information to disk (beyond the pre-existing recording of rustc command outputs). This PR contains: * Gating of all functionality behind `-Z report-future-incompat`. Without this flag, all user output is unchanged. * Passing `-Z emit-future-incompat-report` to rustc when `-Z report-future-incompat` is enabled * Parsing the rustc JSON future incompat report, and displaying it it a user-readable format. * Emitting a warning at the end of a build if any crates had future-incompat reports * A `--future-incompat-report` flag, which shows the full report for each affected crate. * Tests for all of the above. At the moment, we can use the `array_into_iter` to write a test. However, we might eventually get to a point where rustc is not currently emitting future-incompat reports for any lints. What would we want the cargo tests to do in this situation? This functionality didn't require any significant internal changes to Cargo, with one exception: we now process captured command output for all units, not just ones where we want to display warnings. This may result in a slightly longer time to run `cargo build/check/rustc` from a full cache. since we do slightly more work for each upstream dependency. Doing this seems unavoidable with the current architecture, since we need to process captured command outputs to detect any future-incompat-report messages that were emitted.
f0667ac
to
f03d47c
Compare
Yep, I think addressing those later is fine. I pushed a few minor changes and updated the tracking issue. Thanks! 🎉 @bors r+ |
📌 Commit 139ed73 has been approved by |
☀️ Test successful - checks-actions |
@Aaron1011 Thanks for your work on this! This feature will be a great tool for developing the standard library. |
cc rust-lang/rust#71249
This implements the Cargo side of 'Cargo report future-incompat'
Based on feedback from alexcrichton and est31, I'm implemented this a
flag
--future-compat-report
oncargo check/build/rustc
, rather thana separate
cargo describe-future-incompatibilities
command. Thisallows us to avoid writing additional information to disk (beyond the
pre-existing recording of rustc command outputs).
This PR contains:
-Z report-future-incompat
.Without this flag, all user output is unchanged.
-Z emit-future-incompat-report
to rustc when-Z report-future-incompat
is enabledit a user-readable format.
future-incompat reports
--future-incompat-report
flag, which shows the full report foreach affected crate.
At the moment, we can use the
array_into_iter
to write a test.However, we might eventually get to a point where rustc is not currently
emitting future-incompat reports for any lints. What would we want the
cargo tests to do in this situation?
This functionality didn't require any significant internal changes to
Cargo, with one exception: we now process captured command output for
all units, not just ones where we want to display warnings. This may
result in a slightly longer time to run
cargo build/check/rustc
froma full cache. since we do slightly more work for each upstream
dependency. Doing this seems unavoidable with the current architecture,
since we need to process captured command outputs to detect
any future-incompat-report messages that were emitted.