mirror of
https://github.com/rust-lang/cargo
synced 2024-09-13 21:11:44 +00:00
Auto merge of #9953 - Aaron1011:nicer-incompat-report, r=ehuss
Make future-incompat-report output more user-friendly When the user enables `--future-incompat-report`, we now display a high-level summary of the problem, as well as several suggestions for fixing the affected crates. The command `cargo report future-incompatibilities` now takes a `--crate` option, which can be used to display a report (including the actual lint messages) for a single crate. When this option is not used, we display the report for all crates. Sample output from the `actix` crate: `> RUSTFLAGS="-Z future-incompat-test" ~/repos/cargo/target/debug/cargo build -Z future-incompat-report ` ``` Finished dev [unoptimized + debuginfo] target(s) in 2.09s warning: the following packages contain code that will be rejected by a future version of Rust: actix v0.11.1 (/home/aaron/repos/actix/actix), ahash v0.7.4, arc-swap v0.4.4, autocfg v1.0.0, crossbeam-utils v0.8.5, futures-macro v0.3.17, futures-util v0.3.17, lazy_static v1.4.0, libc v0.2.103, lock_api v0.4.5, log v0.4.8, mio v0.7.13, parking_lot_core v0.8.5, signal-hook-registry v1.2.0, smallvec v1.7.0, syn v1.0.77, tokio v1.12.0, tokio-util v0.6.8, unicode-xid v0.2.0, version_check v0.9.3 note: to see what the problems were, use the option `--future-incompat-report`, or run `cargo report future-incompatibilities --id 2` ``` `> RUSTFLAGS="-Z future-incompat-test" ~/repos/cargo/target/debug/cargo build -Z future-incompat-report --future-incompat-report -Z unstable-options` ``` Finished dev [unoptimized + debuginfo] target(s) in 2.12s warning: the following packages contain code that will be rejected by a future version of Rust: actix v0.11.1 (/home/aaron/repos/actix/actix), ahash v0.7.4, arc-swap v0.4.4, autocfg v1.0.0, crossbeam-utils v0.8.5, futures-macro v0.3.17, futures-util v0.3.17, lazy_static v1.4.0, libc v0.2.103, lock_api v0.4.5, log v0.4.8, mio v0.7.13, parking_lot_core v0.8.5, signal-hook-registry v1.2.0, smallvec v1.7.0, syn v1.0.77, tokio v1.12.0, tokio-util v0.6.8, unicode-xid v0.2.0, version_check v0.9.3 note: To solve this problem, you can try the following approaches: - Some affected dependencies have newer versions available. You may want to consider updating them to a newer version to see if the issue has been fixed. ahash v0.7.4 has the following newer versions available: 0.7.5 arc-swap v0.4.4 has the following newer versions available: 0.4.8, 1.1.0, 1.2.0, 1.3.0, 1.3.1, 1.3.2, 1.4.0 autocfg v1.0.0 has the following newer versions available: 1.0.1 log v0.4.8 has the following newer versions available: 0.4.11, 0.4.13, 0.4.14 signal-hook-registry v1.2.0 has the following newer versions available: 1.2.1, 1.2.2, 1.3.0, 1.4.0 syn v1.0.77 has the following newer versions available: 1.0.78, 1.0.79, 1.0.80 unicode-xid v0.2.0 has the following newer versions available: 0.2.1, 0.2.2 - If the issue is not solved by updating the dependencies, a fix has to be implemented by those dependencies. You can help with that by notifying the maintainers of this problem (e.g. by creating a bug report) or by proposing a fix to the maintainers (e.g. by creating a pull request): - actix:0.11.1 - Repository: https://github.com/actix/actix - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "actix:0.11.1" - ahash:0.7.4 - Repository: https://github.com/tkaitchuck/ahash - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "ahash:0.7.4" - arc-swap:0.4.4 - Repository: https://github.com/vorner/arc-swap - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "arc-swap:0.4.4" - autocfg:1.0.0 - Repository: https://github.com/cuviper/autocfg - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "autocfg:1.0.0" - crossbeam-utils:0.8.5 - Repository: https://github.com/crossbeam-rs/crossbeam - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "crossbeam-utils:0.8.5" - futures-macro:0.3.17 - Repository: https://github.com/rust-lang/futures-rs - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "futures-macro:0.3.17" - futures-util:0.3.17 - Repository: https://github.com/rust-lang/futures-rs - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "futures-util:0.3.17" - lazy_static:1.4.0 - Repository: https://github.com/rust-lang-nursery/lazy-static.rs - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "lazy_static:1.4.0" - libc:0.2.103 - Repository: https://github.com/rust-lang/libc - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "libc:0.2.103" - lock_api:0.4.5 - Repository: https://github.com/Amanieu/parking_lot - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "lock_api:0.4.5" - log:0.4.8 - Repository: https://github.com/rust-lang/log - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "log:0.4.8" - mio:0.7.13 - Repository: https://github.com/tokio-rs/mio - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "mio:0.7.13" - parking_lot_core:0.8.5 - Repository: https://github.com/Amanieu/parking_lot - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "parking_lot_core:0.8.5" - signal-hook-registry:1.2.0 - Repository: https://github.com/vorner/signal-hook - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "signal-hook-registry:1.2.0" - smallvec:1.7.0 - Repository: https://github.com/servo/rust-smallvec - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "smallvec:1.7.0" - syn:1.0.77 - Repository: https://github.com/dtolnay/syn - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "syn:1.0.77" - tokio:1.12.0 - Repository: https://github.com/tokio-rs/tokio - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "tokio:1.12.0" - tokio-util:0.6.8 - Repository: https://github.com/tokio-rs/tokio - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "tokio-util:0.6.8" - unicode-xid:0.2.0 - Repository: https://github.com/unicode-rs/unicode-xid - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "unicode-xid:0.2.0" - version_check:0.9.3 - Repository: https://github.com/SergioBenitez/version_check - Detailed warning command: `cargo report future-incompatibilities --id 3 --crate "version_check:0.9.3" - If waiting for an upstream fix is not an option, you can use the `[patch]` section in `Cargo.toml` to use your own version of the dependency. For more information, see: https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section note: this report can be shown with `cargo report future-incompatibilities -Z future-incompat-report --id 3` ``` `> RUSTFLAGS="-Z future-incompat-test" ~/repos/cargo/target/debug/cargo report future-incompatibilities -Z future-incompat-report --color never | head -n 100` ``` The following warnings were discovered during the build. These warnings are an indication that the packages contain code that will become an error in a future release of Rust. These warnings typically cover changes to close soundness problems, unintended or undocumented behavior, or critical problems that cannot be fixed in a backwards-compatible fashion, and are not expected to be in wide use. Each warning should contain a link for more information on what the warning means and how to resolve it. - Some affected dependencies have newer versions available. You may want to consider updating them to a newer version to see if the issue has been fixed. ahash v0.7.4 has the following newer versions available: 0.7.5 arc-swap v0.4.4 has the following newer versions available: 0.4.8, 1.1.0, 1.2.0, 1.3.0, 1.3.1, 1.3.2, 1.4.0 autocfg v1.0.0 has the following newer versions available: 1.0.1 log v0.4.8 has the following newer versions available: 0.4.11, 0.4.13, 0.4.14 signal-hook-registry v1.2.0 has the following newer versions available: 1.2.1, 1.2.2, 1.3.0, 1.4.0 syn v1.0.77 has the following newer versions available: 1.0.78, 1.0.79, 1.0.80 unicode-xid v0.2.0 has the following newer versions available: 0.2.1, 0.2.2 The package `actix v0.11.1 (/home/aaron/repos/actix/actix)` currently triggers the following future incompatibility lints: > warning: use of deprecated struct `utils::Condition`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:25:9 > | > 25 | impl<T> Condition<T> > | ^^^^^^^^^ > | > note: the lint level is defined here > --> actix/src/lib.rs:30:10 > | > 30 | #![allow(deprecated)] > | ^^^^^^^^^^ > > warning: use of deprecated struct `utils::Condition`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:42:21 > | > 42 | impl<T> Default for Condition<T> > | ^^^^^^^^^ > > warning: use of deprecated struct `utils::Condition`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:47:9 > | > 47 | Condition { > | ^^^^^^^^^ > > warning: use of deprecated struct `utils::Condition`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/lib.rs:120:28 > | > 120 | pub use crate::utils::{Condition, IntervalFunc, TimerFunc}; > | ^^^^^^^^^ > > warning: use of deprecated associated function `std::sync::atomic::AtomicUsize::compare_and_swap`: Use `compare_exchange` or `compare_exchange_weak` instead > --> actix/src/address/channel.rs:512:49 > | > 512 | let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst); > | ^^^^^^^^^^^^^^^^ > > warning: use of deprecated associated function `std::sync::atomic::AtomicUsize::compare_and_swap`: Use `compare_exchange` or `compare_exchange_weak` instead > --> actix/src/address/channel.rs:636:49 > | > 636 | let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst); > | ^^^^^^^^^^^^^^^^ > > warning: use of deprecated associated function `std::sync::atomic::AtomicUsize::compare_and_swap`: Use `compare_exchange` or `compare_exchange_weak` instead > --> actix/src/address/channel.rs:697:49 > | > 697 | let actual = self.inner.num_senders.compare_and_swap(curr, next, SeqCst); > | ^^^^^^^^^^^^^^^^ > > warning: use of deprecated field `utils::Condition::waiters`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:31:9 > | > 31 | self.waiters.push(tx); > | ^^^^^^^^^^^^ > > warning: use of deprecated field `utils::Condition::waiters`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:36:23 > | > 36 | for waiter in self.waiters { > | ^^^^^^^^^^^^ > > warning: use of deprecated field `utils::Condition::waiters`: Please use tokio::sync::oneshot::Sender instead. > --> actix/src/utils.rs:48:13 > | > 48 | waiters: Vec::new(), > | ^^^^^^^^^^^^^^^^^^^ > > warning: unused variable: `ctx` > --> actix/src/actor.rs:78:27 > | > 78 | fn started(&mut self, ctx: &mut Self::Context) {} > | ^^^ help: if this is intentional, prefix it with an underscore: `_ctx` > | > note: the lint level is defined here > --> actix/src/actor.rs:72:9 > | > 72 | #[allow(unused_variables)] > | ^^^^^^^^^^^^^^^^ ```
This commit is contained in:
commit
7fbbf4e8f2
|
@ -18,7 +18,8 @@ pub fn cli() -> App {
|
|||
"identifier of the report generated by a Cargo command invocation",
|
||||
)
|
||||
.value_name("id"),
|
||||
),
|
||||
)
|
||||
.arg_package("Package to display a report for"),
|
||||
)
|
||||
}
|
||||
|
||||
|
@ -38,7 +39,8 @@ fn report_future_incompatibilies(config: &Config, args: &ArgMatches<'_>) -> CliR
|
|||
let id = args
|
||||
.value_of_u32("id")?
|
||||
.unwrap_or_else(|| reports.last_id());
|
||||
let report = reports.get_report(id, config)?;
|
||||
let krate = args.value_of("package");
|
||||
let report = reports.get_report(id, config, krate)?;
|
||||
drop_println!(config, "{}", REPORT_PREAMBLE);
|
||||
drop(config.shell().print_ansi_stdout(report.as_bytes()));
|
||||
Ok(())
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
//! Support for future-incompatible warning reporting.
|
||||
|
||||
use crate::core::compiler::BuildContext;
|
||||
use crate::core::{Dependency, PackageId, Workspace};
|
||||
use crate::sources::SourceConfigMap;
|
||||
use crate::util::{iter_join, CargoResult, Config};
|
||||
use anyhow::{bail, format_err, Context};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::{BTreeSet, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::fmt::Write as _;
|
||||
use std::io::{Read, Write};
|
||||
|
||||
|
@ -77,8 +78,14 @@ pub struct OnDiskReports {
|
|||
struct OnDiskReport {
|
||||
/// Unique reference to the report for the `--id` CLI flag.
|
||||
id: u32,
|
||||
/// A message describing suggestions for fixing the
|
||||
/// reported issues
|
||||
suggestion_message: String,
|
||||
/// Report, suitable for printing to the console.
|
||||
report: String,
|
||||
/// Maps package names to the corresponding report
|
||||
/// We use a `BTreeMap` so that the iteration order
|
||||
/// is stable across multiple runs of `cargo`
|
||||
per_package: BTreeMap<String, String>,
|
||||
}
|
||||
|
||||
impl Default for OnDiskReports {
|
||||
|
@ -94,29 +101,22 @@ impl Default for OnDiskReports {
|
|||
impl OnDiskReports {
|
||||
/// Saves a new report.
|
||||
pub fn save_report(
|
||||
mut self,
|
||||
ws: &Workspace<'_>,
|
||||
suggestion_message: String,
|
||||
per_package_reports: &[FutureIncompatReportPackage],
|
||||
) -> OnDiskReports {
|
||||
let mut current_reports = match Self::load(ws) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
log::debug!(
|
||||
"saving future-incompatible reports failed to load current reports: {:?}",
|
||||
e
|
||||
);
|
||||
OnDiskReports::default()
|
||||
}
|
||||
};
|
||||
) {
|
||||
let report = OnDiskReport {
|
||||
id: current_reports.next_id,
|
||||
report: render_report(ws, per_package_reports),
|
||||
id: self.next_id,
|
||||
suggestion_message,
|
||||
per_package: render_report(per_package_reports),
|
||||
};
|
||||
current_reports.next_id += 1;
|
||||
current_reports.reports.push(report);
|
||||
if current_reports.reports.len() > MAX_REPORTS {
|
||||
current_reports.reports.remove(0);
|
||||
self.next_id += 1;
|
||||
self.reports.push(report);
|
||||
if self.reports.len() > MAX_REPORTS {
|
||||
self.reports.remove(0);
|
||||
}
|
||||
let on_disk = serde_json::to_vec(¤t_reports).unwrap();
|
||||
let on_disk = serde_json::to_vec(&self).unwrap();
|
||||
if let Err(e) = ws
|
||||
.target_dir()
|
||||
.open_rw(
|
||||
|
@ -137,7 +137,6 @@ impl OnDiskReports {
|
|||
&mut ws.config().shell(),
|
||||
);
|
||||
}
|
||||
current_reports
|
||||
}
|
||||
|
||||
/// Loads the on-disk reports.
|
||||
|
@ -176,7 +175,12 @@ impl OnDiskReports {
|
|||
self.reports.last().map(|r| r.id).unwrap()
|
||||
}
|
||||
|
||||
pub fn get_report(&self, id: u32, config: &Config) -> CargoResult<String> {
|
||||
pub fn get_report(
|
||||
&self,
|
||||
id: u32,
|
||||
config: &Config,
|
||||
package: Option<&str>,
|
||||
) -> CargoResult<String> {
|
||||
let report = self.reports.iter().find(|r| r.id == id).ok_or_else(|| {
|
||||
let available = iter_join(self.reports.iter().map(|r| r.id.to_string()), ", ");
|
||||
format_err!(
|
||||
|
@ -186,28 +190,56 @@ impl OnDiskReports {
|
|||
available
|
||||
)
|
||||
})?;
|
||||
let report = if config.shell().err_supports_color() {
|
||||
report.report.clone()
|
||||
|
||||
let mut to_display = report.suggestion_message.clone();
|
||||
to_display += "\n";
|
||||
|
||||
let package_report = if let Some(package) = package {
|
||||
report
|
||||
.per_package
|
||||
.get(package)
|
||||
.ok_or_else(|| {
|
||||
format_err!(
|
||||
"could not find package with ID `{}`\n
|
||||
Available packages are: {}\n
|
||||
Omit the `--package` flag to display a report for all packages",
|
||||
package,
|
||||
iter_join(report.per_package.keys(), ", ")
|
||||
)
|
||||
})?
|
||||
.to_string()
|
||||
} else {
|
||||
strip_ansi_escapes::strip(&report.report)
|
||||
report
|
||||
.per_package
|
||||
.values()
|
||||
.cloned()
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n")
|
||||
};
|
||||
to_display += &package_report;
|
||||
|
||||
let to_display = if config.shell().err_supports_color() {
|
||||
to_display
|
||||
} else {
|
||||
strip_ansi_escapes::strip(&to_display)
|
||||
.map(|v| String::from_utf8(v).expect("utf8"))
|
||||
.expect("strip should never fail")
|
||||
};
|
||||
Ok(report)
|
||||
Ok(to_display)
|
||||
}
|
||||
}
|
||||
|
||||
fn render_report(
|
||||
ws: &Workspace<'_>,
|
||||
per_package_reports: &[FutureIncompatReportPackage],
|
||||
) -> String {
|
||||
let mut per_package_reports: Vec<_> = per_package_reports.iter().collect();
|
||||
per_package_reports.sort_by_key(|r| r.package_id);
|
||||
let mut rendered = String::new();
|
||||
for per_package in &per_package_reports {
|
||||
fn render_report(per_package_reports: &[FutureIncompatReportPackage]) -> BTreeMap<String, String> {
|
||||
let mut report: BTreeMap<String, String> = BTreeMap::new();
|
||||
for per_package in per_package_reports {
|
||||
let package_spec = format!(
|
||||
"{}:{}",
|
||||
per_package.package_id.name(),
|
||||
per_package.package_id.version()
|
||||
);
|
||||
let rendered = report.entry(package_spec).or_default();
|
||||
rendered.push_str(&format!(
|
||||
"The package `{}` currently triggers the following future \
|
||||
incompatibility lints:\n",
|
||||
"The package `{}` currently triggers the following future incompatibility lints:\n",
|
||||
per_package.package_id
|
||||
));
|
||||
for item in &per_package.items {
|
||||
|
@ -218,25 +250,20 @@ fn render_report(
|
|||
.map(|l| format!("> {}\n", l)),
|
||||
);
|
||||
}
|
||||
rendered.push('\n');
|
||||
}
|
||||
if let Some(s) = render_suggestions(ws, &per_package_reports) {
|
||||
rendered.push_str(&s);
|
||||
}
|
||||
rendered
|
||||
report
|
||||
}
|
||||
|
||||
fn render_suggestions(
|
||||
ws: &Workspace<'_>,
|
||||
per_package_reports: &[&FutureIncompatReportPackage],
|
||||
) -> Option<String> {
|
||||
/// Returns a user-readable message explaining which of
|
||||
/// the packages in `package_ids` have updates available.
|
||||
/// This is best-effort - if an error occurs, `None` will be returned.
|
||||
fn get_updates(ws: &Workspace<'_>, package_ids: &BTreeSet<PackageId>) -> Option<String> {
|
||||
// This in general ignores all errors since this is opportunistic.
|
||||
let _lock = ws.config().acquire_package_cache_lock().ok()?;
|
||||
// Create a set of updated registry sources.
|
||||
let map = SourceConfigMap::new(ws.config()).ok()?;
|
||||
let package_ids: BTreeSet<_> = per_package_reports
|
||||
let package_ids: BTreeSet<_> = package_ids
|
||||
.iter()
|
||||
.map(|r| r.package_id)
|
||||
.filter(|pkg_id| pkg_id.source_id().is_registry())
|
||||
.collect();
|
||||
let source_ids: HashSet<_> = package_ids
|
||||
|
@ -251,7 +278,7 @@ fn render_suggestions(
|
|||
})
|
||||
.collect();
|
||||
// Query the sources for new versions.
|
||||
let mut suggestions = String::new();
|
||||
let mut updates = String::new();
|
||||
for pkg_id in package_ids {
|
||||
let source = match sources.get_mut(&pkg_id.source_id()) {
|
||||
Some(s) => s,
|
||||
|
@ -259,31 +286,169 @@ fn render_suggestions(
|
|||
};
|
||||
let dep = Dependency::parse(pkg_id.name(), None, pkg_id.source_id()).ok()?;
|
||||
let summaries = source.query_vec(&dep).ok()?;
|
||||
let versions = itertools::sorted(
|
||||
summaries
|
||||
.iter()
|
||||
.map(|summary| summary.version())
|
||||
.filter(|version| *version > pkg_id.version()),
|
||||
let mut updated_versions: Vec<_> = summaries
|
||||
.iter()
|
||||
.map(|summary| summary.version())
|
||||
.filter(|version| *version > pkg_id.version())
|
||||
.collect();
|
||||
updated_versions.sort();
|
||||
|
||||
let updated_versions = iter_join(
|
||||
updated_versions
|
||||
.into_iter()
|
||||
.map(|version| version.to_string()),
|
||||
", ",
|
||||
);
|
||||
let versions = versions.map(|version| version.to_string());
|
||||
let versions = iter_join(versions, ", ");
|
||||
if !versions.is_empty() {
|
||||
|
||||
if !updated_versions.is_empty() {
|
||||
writeln!(
|
||||
suggestions,
|
||||
updates,
|
||||
"{} has the following newer versions available: {}",
|
||||
pkg_id, versions
|
||||
pkg_id, updated_versions
|
||||
)
|
||||
.unwrap();
|
||||
}
|
||||
}
|
||||
if suggestions.is_empty() {
|
||||
None
|
||||
Some(updates)
|
||||
}
|
||||
|
||||
/// Writes a future-incompat report to disk, using the per-package
|
||||
/// reports gathered during the build. If requested by the user,
|
||||
/// a message is also displayed in the build output.
|
||||
pub fn save_and_display_report(
|
||||
bcx: &BuildContext<'_, '_>,
|
||||
per_package_future_incompat_reports: &[FutureIncompatReportPackage],
|
||||
) {
|
||||
if !bcx.config.cli_unstable().future_incompat_report {
|
||||
return;
|
||||
}
|
||||
let should_display_message = match bcx.config.future_incompat_config() {
|
||||
Ok(config) => config.should_display_message(),
|
||||
Err(e) => {
|
||||
crate::display_warning_with_error(
|
||||
"failed to read future-incompat config from disk",
|
||||
&e,
|
||||
&mut bcx.config.shell(),
|
||||
);
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
if per_package_future_incompat_reports.is_empty() {
|
||||
// Explicitly passing a command-line flag overrides
|
||||
// `should_display_message` from the config file
|
||||
if bcx.build_config.future_incompat_report {
|
||||
drop(
|
||||
bcx.config
|
||||
.shell()
|
||||
.note("0 dependencies had future-incompatible warnings"),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let current_reports = match OnDiskReports::load(bcx.ws) {
|
||||
Ok(r) => r,
|
||||
Err(e) => {
|
||||
log::debug!(
|
||||
"saving future-incompatible reports failed to load current reports: {:?}",
|
||||
e
|
||||
);
|
||||
OnDiskReports::default()
|
||||
}
|
||||
};
|
||||
let report_id = current_reports.next_id;
|
||||
|
||||
// Get a list of unique and sorted package name/versions.
|
||||
let package_ids: BTreeSet<_> = per_package_future_incompat_reports
|
||||
.iter()
|
||||
.map(|r| r.package_id)
|
||||
.collect();
|
||||
let package_vers: Vec<_> = package_ids.iter().map(|pid| pid.to_string()).collect();
|
||||
|
||||
if should_display_message || bcx.build_config.future_incompat_report {
|
||||
drop(bcx.config.shell().warn(&format!(
|
||||
"the following packages contain code that will be rejected by a future \
|
||||
version of Rust: {}",
|
||||
package_vers.join(", ")
|
||||
)));
|
||||
}
|
||||
|
||||
let updated_versions = get_updates(bcx.ws, &package_ids).unwrap_or(String::new());
|
||||
|
||||
let update_message = if !updated_versions.is_empty() {
|
||||
format!(
|
||||
"
|
||||
- Some affected dependencies have newer versions available.
|
||||
You may want to consider updating them to a newer version to see if the issue has been fixed.
|
||||
|
||||
{updated_versions}\n",
|
||||
updated_versions = updated_versions
|
||||
)
|
||||
} else {
|
||||
Some(format!(
|
||||
"The following packages appear to have newer versions available.\n\
|
||||
You may want to consider updating them to a newer version to see if the \
|
||||
issue has been fixed.\n\n{}",
|
||||
suggestions
|
||||
))
|
||||
String::new()
|
||||
};
|
||||
|
||||
let upstream_info = package_ids
|
||||
.iter()
|
||||
.map(|package_id| {
|
||||
let manifest = bcx.packages.get_one(*package_id).unwrap().manifest();
|
||||
format!(
|
||||
"
|
||||
- {name}
|
||||
- Repository: {url}
|
||||
- Detailed warning command: `cargo report future-incompatibilities --id {id} --package {name}`",
|
||||
name = format!("{}:{}", package_id.name(), package_id.version()),
|
||||
url = manifest
|
||||
.metadata()
|
||||
.repository
|
||||
.as_deref()
|
||||
.unwrap_or("<not found>"),
|
||||
id = report_id,
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let suggestion_message = format!(
|
||||
"
|
||||
To solve this problem, you can try the following approaches:
|
||||
|
||||
{update_message}
|
||||
- If the issue is not solved by updating the dependencies, a fix has to be
|
||||
implemented by those dependencies. You can help with that by notifying the
|
||||
maintainers of this problem (e.g. by creating a bug report) or by proposing a
|
||||
fix to the maintainers (e.g. by creating a pull request):
|
||||
{upstream_info}
|
||||
|
||||
- If waiting for an upstream fix is not an option, you can use the `[patch]`
|
||||
section in `Cargo.toml` to use your own version of the dependency. For more
|
||||
information, see:
|
||||
https://doc.rust-lang.org/cargo/reference/overriding-dependencies.html#the-patch-section
|
||||
",
|
||||
upstream_info = upstream_info,
|
||||
update_message = update_message,
|
||||
);
|
||||
|
||||
current_reports.save_report(
|
||||
bcx.ws,
|
||||
suggestion_message.clone(),
|
||||
per_package_future_incompat_reports,
|
||||
);
|
||||
|
||||
if bcx.build_config.future_incompat_report {
|
||||
drop(bcx.config.shell().note(&suggestion_message));
|
||||
drop(bcx.config.shell().note(&format!(
|
||||
"this report can be shown with `cargo report \
|
||||
future-incompatibilities -Z future-incompat-report --id {}`",
|
||||
report_id
|
||||
)));
|
||||
} else if should_display_message {
|
||||
drop(bcx.config.shell().note(&format!(
|
||||
"to see what the problems were, use the option \
|
||||
`--future-incompat-report`, or run `cargo report \
|
||||
future-incompatibilities --id {}`",
|
||||
report_id
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -50,7 +50,7 @@
|
|||
//! improved.
|
||||
|
||||
use std::cell::{Cell, RefCell};
|
||||
use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet};
|
||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||
use std::fmt::Write as _;
|
||||
use std::io;
|
||||
use std::marker;
|
||||
|
@ -72,7 +72,7 @@ use super::job::{
|
|||
use super::timings::Timings;
|
||||
use super::{BuildContext, BuildPlan, CompileMode, Context, Unit};
|
||||
use crate::core::compiler::future_incompat::{
|
||||
FutureBreakageItem, FutureIncompatReportPackage, OnDiskReports,
|
||||
self, FutureBreakageItem, FutureIncompatReportPackage,
|
||||
};
|
||||
use crate::core::resolver::ResolveBehavior;
|
||||
use crate::core::{PackageId, Shell, TargetKind};
|
||||
|
@ -871,7 +871,10 @@ impl<'cfg> DrainState<'cfg> {
|
|||
if !cx.bcx.build_config.build_plan {
|
||||
// It doesn't really matter if this fails.
|
||||
drop(cx.bcx.config.shell().status("Finished", message));
|
||||
self.emit_future_incompat(cx.bcx);
|
||||
future_incompat::save_and_display_report(
|
||||
cx.bcx,
|
||||
&self.per_package_future_incompat_reports,
|
||||
);
|
||||
}
|
||||
|
||||
None
|
||||
|
@ -881,76 +884,6 @@ impl<'cfg> DrainState<'cfg> {
|
|||
}
|
||||
}
|
||||
|
||||
fn emit_future_incompat(&mut self, bcx: &BuildContext<'_, '_>) {
|
||||
if !bcx.config.cli_unstable().future_incompat_report {
|
||||
return;
|
||||
}
|
||||
let should_display_message = match bcx.config.future_incompat_config() {
|
||||
Ok(config) => config.should_display_message(),
|
||||
Err(e) => {
|
||||
crate::display_warning_with_error(
|
||||
"failed to read future-incompat config from disk",
|
||||
&e,
|
||||
&mut bcx.config.shell(),
|
||||
);
|
||||
true
|
||||
}
|
||||
};
|
||||
|
||||
if self.per_package_future_incompat_reports.is_empty() {
|
||||
// Explicitly passing a command-line flag overrides
|
||||
// `should_display_message` from the config file
|
||||
if bcx.build_config.future_incompat_report {
|
||||
drop(
|
||||
bcx.config
|
||||
.shell()
|
||||
.note("0 dependencies had future-incompatible warnings"),
|
||||
);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// Get a list of unique and sorted package name/versions.
|
||||
let package_vers: BTreeSet<_> = self
|
||||
.per_package_future_incompat_reports
|
||||
.iter()
|
||||
.map(|r| r.package_id)
|
||||
.collect();
|
||||
let package_vers: Vec<_> = package_vers
|
||||
.into_iter()
|
||||
.map(|pid| pid.to_string())
|
||||
.collect();
|
||||
|
||||
if should_display_message || bcx.build_config.future_incompat_report {
|
||||
drop(bcx.config.shell().warn(&format!(
|
||||
"the following packages contain code that will be rejected by a future \
|
||||
version of Rust: {}",
|
||||
package_vers.join(", ")
|
||||
)));
|
||||
}
|
||||
|
||||
let on_disk_reports =
|
||||
OnDiskReports::save_report(bcx.ws, &self.per_package_future_incompat_reports);
|
||||
let report_id = on_disk_reports.last_id();
|
||||
|
||||
if bcx.build_config.future_incompat_report {
|
||||
let rendered = on_disk_reports.get_report(report_id, bcx.config).unwrap();
|
||||
drop(bcx.config.shell().print_ansi_stderr(rendered.as_bytes()));
|
||||
drop(bcx.config.shell().note(&format!(
|
||||
"this report can be shown with `cargo report \
|
||||
future-incompatibilities -Z future-incompat-report --id {}`",
|
||||
report_id
|
||||
)));
|
||||
} else if should_display_message {
|
||||
drop(bcx.config.shell().note(&format!(
|
||||
"to see what the problems were, use the option \
|
||||
`--future-incompat-report`, or run `cargo report \
|
||||
future-incompatibilities --id {}`",
|
||||
report_id
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_error(
|
||||
&self,
|
||||
shell: &mut Shell,
|
||||
|
|
|
@ -161,7 +161,7 @@ frequency = 'never'
|
|||
.env("RUSTFLAGS", "-Zfuture-incompat-test")
|
||||
.with_stderr_contains(FUTURE_OUTPUT)
|
||||
.with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: foo v0.0.0 [..]")
|
||||
.with_stderr_contains("The package `foo v0.0.0 ([..])` currently triggers the following future incompatibility lints:")
|
||||
.with_stderr_contains(" - foo:0.0.0[..]")
|
||||
.run();
|
||||
}
|
||||
}
|
||||
|
@ -202,16 +202,33 @@ fn test_multi_crate() {
|
|||
.env("RUSTFLAGS", "-Zfuture-incompat-test")
|
||||
.with_stderr_does_not_contain(FUTURE_OUTPUT)
|
||||
.with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2")
|
||||
// Check that we don't have the 'triggers' message shown at the bottom of this loop
|
||||
// Check that we don't have the 'triggers' message shown at the bottom of this loop,
|
||||
// and that we don't explain how to show a per-package report
|
||||
.with_stderr_does_not_contain("[..]triggers[..]")
|
||||
.with_stderr_does_not_contain("[..]--package[..]")
|
||||
.with_stderr_does_not_contain("[..]-p[..]")
|
||||
.run();
|
||||
|
||||
p.cargo(command).arg("-Zunstable-options").arg("-Zfuture-incompat-report").arg("--future-incompat-report")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.env("RUSTFLAGS", "-Zfuture-incompat-test")
|
||||
.with_stderr_contains("warning: the following packages contain code that will be rejected by a future version of Rust: first-dep v0.0.1, second-dep v0.0.2")
|
||||
.with_stderr_contains("The package `first-dep v0.0.1` currently triggers the following future incompatibility lints:")
|
||||
.with_stderr_contains("The package `second-dep v0.0.2` currently triggers the following future incompatibility lints:")
|
||||
.with_stderr_contains(" - first-dep:0.0.1")
|
||||
.with_stderr_contains(" - second-dep:0.0.2")
|
||||
.run();
|
||||
|
||||
p.cargo("report future-incompatibilities").arg("--package").arg("first-dep:0.0.1").arg("-Zunstable-options").arg("-Zfuture-incompat-report")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.with_stdout_contains("The package `first-dep v0.0.1` currently triggers the following future incompatibility lints:")
|
||||
.with_stdout_contains(FUTURE_OUTPUT)
|
||||
.with_stdout_does_not_contain("[..]second-dep-0.0.2/src[..]")
|
||||
.run();
|
||||
|
||||
p.cargo("report future-incompatibilities").arg("--package").arg("second-dep:0.0.2").arg("-Zunstable-options").arg("-Zfuture-incompat-report")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.with_stdout_contains("The package `second-dep v0.0.2` currently triggers the following future incompatibility lints:")
|
||||
.with_stdout_contains(FUTURE_OUTPUT)
|
||||
.with_stdout_does_not_contain("[..]first-dep-0.0.1/src[..]")
|
||||
.run();
|
||||
}
|
||||
|
||||
|
@ -263,7 +280,9 @@ fn test_multi_crate() {
|
|||
"The package `{}` currently triggers the following future incompatibility lints:",
|
||||
expected
|
||||
),
|
||||
lines.next().unwrap()
|
||||
lines.next().unwrap(),
|
||||
"Bad output:\n{}",
|
||||
output
|
||||
);
|
||||
let mut count = 0;
|
||||
while let Some(line) = lines.next() {
|
||||
|
@ -383,6 +402,9 @@ fn suggestions_for_updates() {
|
|||
Package::new("with_updates", "1.0.2")
|
||||
.file("src/lib.rs", "")
|
||||
.publish();
|
||||
Package::new("with_updates", "3.0.1")
|
||||
.file("src/lib.rs", "")
|
||||
.publish();
|
||||
Package::new("big_update", "2.0.0")
|
||||
.file("src/lib.rs", "")
|
||||
.publish();
|
||||
|
@ -396,22 +418,22 @@ fn suggestions_for_updates() {
|
|||
// in a long while?).
|
||||
p.cargo("update -p without_updates").run();
|
||||
|
||||
p.cargo("check -Zfuture-incompat-report")
|
||||
let update_message = "\
|
||||
- Some affected dependencies have newer versions available.
|
||||
You may want to consider updating them to a newer version to see if the issue has been fixed.
|
||||
|
||||
big_update v1.0.0 has the following newer versions available: 2.0.0
|
||||
with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2, 3.0.1
|
||||
";
|
||||
|
||||
p.cargo("check -Zfuture-incompat-report -Zunstable-options --future-incompat-report")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.env("RUSTFLAGS", "-Zfuture-incompat-test")
|
||||
.with_stderr_contains("[..]cargo report future-incompatibilities --id 1[..]")
|
||||
.with_stderr_contains(update_message)
|
||||
.run();
|
||||
|
||||
p.cargo("report future-incompatibilities")
|
||||
.masquerade_as_nightly_cargo()
|
||||
.with_stdout_contains(
|
||||
"\
|
||||
The following packages appear to have newer versions available.
|
||||
You may want to consider updating them to a newer version to see if the issue has been fixed.
|
||||
|
||||
big_update v1.0.0 has the following newer versions available: 2.0.0
|
||||
with_updates v1.0.0 has the following newer versions available: 1.0.1, 1.0.2
|
||||
",
|
||||
)
|
||||
.run();
|
||||
.with_stdout_contains(update_message)
|
||||
.run()
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue