mirror of https://github.com/rust-lang/cargo
Compare commits
8 Commits
709dcc503e
...
0285258e10
Author | SHA1 | Date |
---|---|---|
Weihang Lo | 0285258e10 | |
bors | eee4ea2f5a | |
bors | c4e19cc890 | |
Eric Huss | 06fb65e753 | |
Scott Schafer | cf197fc499 | |
Scott Schafer | c3b104e11e | |
Weihang Lo | 0810627891 | |
Weihang Lo | 8410c1e99d |
|
@ -1147,11 +1147,26 @@ impl<'gctx> Workspace<'gctx> {
|
|||
}
|
||||
|
||||
pub fn emit_warnings(&self) -> CargoResult<()> {
|
||||
let ws_lints = self
|
||||
.root_maybe()
|
||||
.workspace_config()
|
||||
.inheritable()
|
||||
.and_then(|i| i.lints().ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
let ws_cargo_lints = ws_lints
|
||||
.get("cargo")
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.replace('-', "_"), v))
|
||||
.collect();
|
||||
|
||||
for (path, maybe_pkg) in &self.packages.packages {
|
||||
let path = path.join("Cargo.toml");
|
||||
if let MaybePackage::Package(pkg) = maybe_pkg {
|
||||
if self.gctx.cli_unstable().cargo_lints {
|
||||
self.emit_lints(pkg, &path)?
|
||||
self.emit_lints(pkg, &path, &ws_cargo_lints)?
|
||||
}
|
||||
}
|
||||
let warnings = match maybe_pkg {
|
||||
|
@ -1179,22 +1194,12 @@ impl<'gctx> Workspace<'gctx> {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn emit_lints(&self, pkg: &Package, path: &Path) -> CargoResult<()> {
|
||||
let ws_lints = self
|
||||
.root_maybe()
|
||||
.workspace_config()
|
||||
.inheritable()
|
||||
.and_then(|i| i.lints().ok())
|
||||
.unwrap_or_default();
|
||||
|
||||
let ws_cargo_lints = ws_lints
|
||||
.get("cargo")
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.map(|(k, v)| (k.replace('-', "_"), v))
|
||||
.collect();
|
||||
|
||||
pub fn emit_lints(
|
||||
&self,
|
||||
pkg: &Package,
|
||||
path: &Path,
|
||||
ws_cargo_lints: &manifest::TomlToolLints,
|
||||
) -> CargoResult<()> {
|
||||
let mut error_count = 0;
|
||||
let toml_lints = pkg
|
||||
.manifest()
|
||||
|
@ -1212,11 +1217,21 @@ impl<'gctx> Workspace<'gctx> {
|
|||
.map(|(name, lint)| (name.replace('-', "_"), lint))
|
||||
.collect();
|
||||
|
||||
// We should only be using workspace lints if the `[lints]` table is
|
||||
// present in the manifest, and `workspace` is set to `true`
|
||||
let ws_cargo_lints = pkg
|
||||
.manifest()
|
||||
.resolved_toml()
|
||||
.lints
|
||||
.as_ref()
|
||||
.is_some_and(|l| l.workspace)
|
||||
.then(|| ws_cargo_lints);
|
||||
|
||||
check_im_a_teapot(
|
||||
pkg,
|
||||
&path,
|
||||
&normalized_lints,
|
||||
&ws_cargo_lints,
|
||||
ws_cargo_lints,
|
||||
&mut error_count,
|
||||
self.gctx,
|
||||
)?;
|
||||
|
@ -1224,7 +1239,7 @@ impl<'gctx> Workspace<'gctx> {
|
|||
pkg,
|
||||
&path,
|
||||
&normalized_lints,
|
||||
&ws_cargo_lints,
|
||||
ws_cargo_lints,
|
||||
&mut error_count,
|
||||
self.gctx,
|
||||
)?;
|
||||
|
@ -1232,7 +1247,7 @@ impl<'gctx> Workspace<'gctx> {
|
|||
pkg,
|
||||
&path,
|
||||
&normalized_lints,
|
||||
&ws_cargo_lints,
|
||||
ws_cargo_lints,
|
||||
&mut error_count,
|
||||
self.gctx,
|
||||
)?;
|
||||
|
|
|
@ -50,6 +50,7 @@ use rustfix::CodeFix;
|
|||
use semver::Version;
|
||||
use tracing::{debug, trace, warn};
|
||||
|
||||
use crate::core::compiler::CompileKind;
|
||||
use crate::core::compiler::RustcTargetData;
|
||||
use crate::core::resolver::features::{DiffMap, FeatureOpts, FeatureResolver, FeaturesFor};
|
||||
use crate::core::resolver::{HasDevUnits, Resolve, ResolveBehavior};
|
||||
|
@ -78,6 +79,14 @@ const EDITION_ENV_INTERNAL: &str = "__CARGO_FIX_EDITION";
|
|||
/// **Internal only.**
|
||||
/// For passing [`FixOptions::idioms`] through to cargo running in proxy mode.
|
||||
const IDIOMS_ENV_INTERNAL: &str = "__CARGO_FIX_IDIOMS";
|
||||
/// **Internal only.**
|
||||
/// The sysroot path.
|
||||
///
|
||||
/// This is for preventing `cargo fix` from fixing rust std/core libs. See
|
||||
///
|
||||
/// * <https://github.com/rust-lang/cargo/issues/9857>
|
||||
/// * <https://github.com/rust-lang/rust/issues/88514#issuecomment-2043469384>
|
||||
const SYSROOT_INTERNAL: &str = "__CARGO_FIX_RUST_SRC";
|
||||
|
||||
pub struct FixOptions {
|
||||
pub edition: bool,
|
||||
|
@ -97,6 +106,8 @@ pub fn fix(
|
|||
) -> CargoResult<()> {
|
||||
check_version_control(gctx, opts)?;
|
||||
|
||||
let mut target_data =
|
||||
RustcTargetData::new(original_ws, &opts.compile_opts.build_config.requested_kinds)?;
|
||||
if opts.edition {
|
||||
let specs = opts.compile_opts.spec.to_package_id_specs(&original_ws)?;
|
||||
let members: Vec<&Package> = original_ws
|
||||
|
@ -105,7 +116,7 @@ pub fn fix(
|
|||
.collect();
|
||||
migrate_manifests(original_ws, &members)?;
|
||||
|
||||
check_resolver_change(&original_ws, opts)?;
|
||||
check_resolver_change(&original_ws, &mut target_data, opts)?;
|
||||
}
|
||||
let mut ws = Workspace::new(&root_manifest, gctx)?;
|
||||
ws.set_resolve_honors_rust_version(Some(original_ws.resolve_honors_rust_version()));
|
||||
|
@ -129,6 +140,11 @@ pub fn fix(
|
|||
wrapper.env(IDIOMS_ENV_INTERNAL, "1");
|
||||
}
|
||||
|
||||
let sysroot = &target_data.info(CompileKind::Host).sysroot;
|
||||
if sysroot.is_dir() {
|
||||
wrapper.env(SYSROOT_INTERNAL, sysroot);
|
||||
}
|
||||
|
||||
*opts
|
||||
.compile_opts
|
||||
.build_config
|
||||
|
@ -395,7 +411,11 @@ fn add_feature_for_unused_deps(pkg: &Package, parent: &mut dyn toml_edit::TableL
|
|||
fixes
|
||||
}
|
||||
|
||||
fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<()> {
|
||||
fn check_resolver_change<'gctx>(
|
||||
ws: &Workspace<'gctx>,
|
||||
target_data: &mut RustcTargetData<'gctx>,
|
||||
opts: &FixOptions,
|
||||
) -> CargoResult<()> {
|
||||
let root = ws.root_maybe();
|
||||
match root {
|
||||
MaybePackage::Package(root_pkg) => {
|
||||
|
@ -422,12 +442,10 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
|
|||
// 2018 without `resolver` set must be V1
|
||||
assert_eq!(ws.resolve_behavior(), ResolveBehavior::V1);
|
||||
let specs = opts.compile_opts.spec.to_package_id_specs(ws)?;
|
||||
let mut target_data =
|
||||
RustcTargetData::new(ws, &opts.compile_opts.build_config.requested_kinds)?;
|
||||
let mut resolve_differences = |has_dev_units| -> CargoResult<(WorkspaceResolve<'_>, DiffMap)> {
|
||||
let ws_resolve = ops::resolve_ws_with_opts(
|
||||
ws,
|
||||
&mut target_data,
|
||||
target_data,
|
||||
&opts.compile_opts.build_config.requested_kinds,
|
||||
&opts.compile_opts.cli_features,
|
||||
&specs,
|
||||
|
@ -438,7 +456,7 @@ fn check_resolver_change(ws: &Workspace<'_>, opts: &FixOptions) -> CargoResult<(
|
|||
let feature_opts = FeatureOpts::new_behavior(ResolveBehavior::V2, has_dev_units);
|
||||
let v2_features = FeatureResolver::resolve(
|
||||
ws,
|
||||
&mut target_data,
|
||||
target_data,
|
||||
&ws_resolve.targeted_resolve,
|
||||
&ws_resolve.pkg_set,
|
||||
&opts.compile_opts.cli_features,
|
||||
|
@ -744,7 +762,8 @@ fn rustfix_crate(
|
|||
// We'll generate new errors below.
|
||||
file.errors_applying_fixes.clear();
|
||||
}
|
||||
(last_output, last_made_changes) = rustfix_and_fix(&mut files, rustc, filename, gctx)?;
|
||||
(last_output, last_made_changes) =
|
||||
rustfix_and_fix(&mut files, rustc, filename, args, gctx)?;
|
||||
if current_iteration == 0 {
|
||||
first_output = Some(last_output.clone());
|
||||
}
|
||||
|
@ -801,6 +820,7 @@ fn rustfix_and_fix(
|
|||
files: &mut HashMap<String, FixedFile>,
|
||||
rustc: &ProcessBuilder,
|
||||
filename: &Path,
|
||||
args: &FixArgs,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<(Output, bool)> {
|
||||
// If not empty, filter by these lints.
|
||||
|
@ -865,10 +885,17 @@ fn rustfix_and_fix(
|
|||
continue;
|
||||
};
|
||||
|
||||
let file_path = Path::new(&file_name);
|
||||
// Do not write into registry cache. See rust-lang/cargo#9857.
|
||||
if Path::new(&file_name).starts_with(home_path) {
|
||||
if file_path.starts_with(home_path) {
|
||||
continue;
|
||||
}
|
||||
// Do not write into standard library source. See rust-lang/cargo#9857.
|
||||
if let Some(sysroot) = args.sysroot.as_deref() {
|
||||
if file_path.starts_with(sysroot) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if !file_names.clone().all(|f| f == &file_name) {
|
||||
trace!("rejecting as it changes multiple files: {:?}", suggestion);
|
||||
|
@ -1025,6 +1052,8 @@ struct FixArgs {
|
|||
other: Vec<OsString>,
|
||||
/// Path to the `rustc` executable.
|
||||
rustc: PathBuf,
|
||||
/// Path to host sysroot.
|
||||
sysroot: Option<PathBuf>,
|
||||
}
|
||||
|
||||
impl FixArgs {
|
||||
|
@ -1096,6 +1125,11 @@ impl FixArgs {
|
|||
.saturating_next()
|
||||
});
|
||||
|
||||
// ALLOWED: For the internal mechanism of `cargo fix` only.
|
||||
// Shouldn't be set directly by anyone.
|
||||
#[allow(clippy::disallowed_methods)]
|
||||
let sysroot = env::var_os(SYSROOT_INTERNAL).map(PathBuf::from);
|
||||
|
||||
Ok(FixArgs {
|
||||
file,
|
||||
prepare_for_edition,
|
||||
|
@ -1103,6 +1137,7 @@ impl FixArgs {
|
|||
enabled_edition,
|
||||
other,
|
||||
rustc,
|
||||
sysroot,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -88,7 +88,7 @@ impl Lint {
|
|||
pub fn level(
|
||||
&self,
|
||||
pkg_lints: &TomlToolLints,
|
||||
ws_lints: &TomlToolLints,
|
||||
ws_lints: Option<&TomlToolLints>,
|
||||
edition: Edition,
|
||||
) -> (LintLevel, LintLevelReason) {
|
||||
self.groups
|
||||
|
@ -188,7 +188,7 @@ fn level_priority(
|
|||
default_level: LintLevel,
|
||||
edition_lint_opts: Option<(Edition, LintLevel)>,
|
||||
pkg_lints: &TomlToolLints,
|
||||
ws_lints: &TomlToolLints,
|
||||
ws_lints: Option<&TomlToolLints>,
|
||||
edition: Edition,
|
||||
) -> (LintLevel, LintLevelReason, i8) {
|
||||
let (unspecified_level, reason) = if let Some(level) = edition_lint_opts
|
||||
|
@ -211,7 +211,7 @@ fn level_priority(
|
|||
LintLevelReason::Package,
|
||||
defined_level.priority(),
|
||||
)
|
||||
} else if let Some(defined_level) = ws_lints.get(name) {
|
||||
} else if let Some(defined_level) = ws_lints.and_then(|l| l.get(name)) {
|
||||
(
|
||||
defined_level.level().into(),
|
||||
LintLevelReason::Workspace,
|
||||
|
@ -234,7 +234,7 @@ pub fn check_im_a_teapot(
|
|||
pkg: &Package,
|
||||
path: &Path,
|
||||
pkg_lints: &TomlToolLints,
|
||||
ws_lints: &TomlToolLints,
|
||||
ws_lints: Option<&TomlToolLints>,
|
||||
error_count: &mut usize,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<()> {
|
||||
|
@ -306,7 +306,7 @@ pub fn check_implicit_features(
|
|||
pkg: &Package,
|
||||
path: &Path,
|
||||
pkg_lints: &TomlToolLints,
|
||||
ws_lints: &TomlToolLints,
|
||||
ws_lints: Option<&TomlToolLints>,
|
||||
error_count: &mut usize,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<()> {
|
||||
|
@ -390,7 +390,7 @@ pub fn unused_dependencies(
|
|||
pkg: &Package,
|
||||
path: &Path,
|
||||
pkg_lints: &TomlToolLints,
|
||||
ws_lints: &TomlToolLints,
|
||||
ws_lints: Option<&TomlToolLints>,
|
||||
error_count: &mut usize,
|
||||
gctx: &GlobalContext,
|
||||
) -> CargoResult<()> {
|
||||
|
|
|
@ -90,13 +90,15 @@ impl<T> SleepTracker<T> {
|
|||
#[test]
|
||||
fn returns_in_order() {
|
||||
let mut s = SleepTracker::new();
|
||||
s.push(3, 3);
|
||||
s.push(30_000, 30_000);
|
||||
s.push(1, 1);
|
||||
s.push(6, 6);
|
||||
s.push(5, 5);
|
||||
s.push(2, 2);
|
||||
s.push(10000, 10000);
|
||||
assert_eq!(s.len(), 6);
|
||||
std::thread::sleep(Duration::from_millis(100));
|
||||
assert_eq!(s.to_retry(), &[1, 2, 3, 5, 6]);
|
||||
assert_eq!(s.len(), 2);
|
||||
std::thread::sleep(Duration::from_millis(2));
|
||||
assert_eq!(s.to_retry(), &[1]);
|
||||
assert!(s.to_retry().is_empty());
|
||||
let next = s.time_to_next().expect("should be next");
|
||||
assert!(
|
||||
next < Duration::from_millis(30_000),
|
||||
"{next:?} should be less than 30s"
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1906,6 +1906,333 @@ warning: `foo` (lib) generated 1 warning (run `cargo fix --lib -p foo` to apply
|
|||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn fix_in_rust_src() {
|
||||
// Tests what happens if rustc emits a suggestion to modify the standard
|
||||
// library in rust source. This should never happen, and indicates a bug in
|
||||
// rustc. However, there are several known bugs in rustc where it does this
|
||||
// (often involving macros), so `cargo fix` has a guard that says if the
|
||||
// suggestion points to rust source under sysroot to not apply it.
|
||||
//
|
||||
// See https://github.com/rust-lang/cargo/issues/9857 for some other
|
||||
// examples.
|
||||
//
|
||||
// This test uses a simulated rustc which replays a suggestion via a JSON
|
||||
// message that points into rust-src. This does not use the real rustc
|
||||
// because as the bugs are fixed in the real rustc, that would cause this
|
||||
// test to stop working.
|
||||
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[package]
|
||||
name = "foo"
|
||||
edition = "2021"
|
||||
"#,
|
||||
)
|
||||
.file(
|
||||
"src/lib.rs",
|
||||
r#"
|
||||
pub fn bug_report<W: std::fmt::Write>(w: &mut W) -> std::fmt::Result {
|
||||
if true {
|
||||
writeln!(w, "`;?` here ->")?;
|
||||
} else {
|
||||
writeln!(w, "but not here")
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
"#,
|
||||
)
|
||||
.build();
|
||||
p.cargo("fetch").run();
|
||||
|
||||
// Since this is a substitution into a Rust string (representing a JSON
|
||||
// string), deal with backslashes like on Windows.
|
||||
let sysroot = paths::sysroot().replace("\\", "/");
|
||||
|
||||
// This is a fake rustc that will emit a JSON message when the `foo` crate
|
||||
// builds that tells cargo to modify a file it shouldn't.
|
||||
let rustc = project()
|
||||
.at("rustc-replay")
|
||||
.file("Cargo.toml", &basic_manifest("rustc-replay", "1.0.0"))
|
||||
.file("src/main.rs",
|
||||
&r##"
|
||||
fn main() {
|
||||
let pkg_name = match std::env::var("CARGO_PKG_NAME") {
|
||||
Ok(pkg_name) => pkg_name,
|
||||
Err(_) => {
|
||||
let r = std::process::Command::new("rustc")
|
||||
.args(std::env::args_os().skip(1))
|
||||
.status();
|
||||
std::process::exit(r.unwrap().code().unwrap_or(2));
|
||||
}
|
||||
};
|
||||
if pkg_name == "foo" {
|
||||
eprintln!("{}", r#"{
|
||||
"$message_type": "diagnostic",
|
||||
"message": "mismatched types",
|
||||
"code":
|
||||
{
|
||||
"code": "E0308",
|
||||
"explanation": "Expected type did not match the received type.\n\nErroneous code examples:\n\n```compile_fail,E0308\nfn plus_one(x: i32) -> i32 {\n x + 1\n}\n\nplus_one(\"Not a number\");\n// ^^^^^^^^^^^^^^ expected `i32`, found `&str`\n\nif \"Not a bool\" {\n// ^^^^^^^^^^^^ expected `bool`, found `&str`\n}\n\nlet x: f32 = \"Not a float\";\n// --- ^^^^^^^^^^^^^ expected `f32`, found `&str`\n// |\n// expected due to this\n```\n\nThis error occurs when an expression was used in a place where the compiler\nexpected an expression of a different type. It can occur in several cases, the\nmost common being when calling a function and passing an argument which has a\ndifferent type than the matching type in the function declaration.\n"
|
||||
},
|
||||
"level": "error",
|
||||
"spans":
|
||||
[
|
||||
{
|
||||
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
|
||||
"byte_start": 23568,
|
||||
"byte_end": 23617,
|
||||
"line_start": 670,
|
||||
"line_end": 670,
|
||||
"column_start": 9,
|
||||
"column_end": 58,
|
||||
"is_primary": true,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))",
|
||||
"highlight_start": 9,
|
||||
"highlight_end": 58
|
||||
}
|
||||
],
|
||||
"label": "expected `()`, found `Result<(), Error>`",
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion":
|
||||
{
|
||||
"span":
|
||||
{
|
||||
"file_name": "lib.rs",
|
||||
"byte_start": 144,
|
||||
"byte_end": 171,
|
||||
"line_start": 5,
|
||||
"line_end": 5,
|
||||
"column_start": 9,
|
||||
"column_end": 36,
|
||||
"is_primary": false,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": " writeln!(w, \"but not here\")",
|
||||
"highlight_start": 9,
|
||||
"highlight_end": 36
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion": null
|
||||
},
|
||||
"macro_decl_name": "writeln!",
|
||||
"def_site_span":
|
||||
{
|
||||
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
|
||||
"byte_start": 23434,
|
||||
"byte_end": 23454,
|
||||
"line_start": 665,
|
||||
"line_end": 665,
|
||||
"column_start": 1,
|
||||
"column_end": 21,
|
||||
"is_primary": false,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": "macro_rules! writeln {",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 21
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion": null
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"file_name": "lib.rs",
|
||||
"byte_start": 75,
|
||||
"byte_end": 177,
|
||||
"line_start": 2,
|
||||
"line_end": 6,
|
||||
"column_start": 5,
|
||||
"column_end": 6,
|
||||
"is_primary": false,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": " if true {",
|
||||
"highlight_start": 5,
|
||||
"highlight_end": 14
|
||||
},
|
||||
{
|
||||
"text": " writeln!(w, \"`;?` here ->\")?;",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 38
|
||||
},
|
||||
{
|
||||
"text": " } else {",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 13
|
||||
},
|
||||
{
|
||||
"text": " writeln!(w, \"but not here\")",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 36
|
||||
},
|
||||
{
|
||||
"text": " }",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 6
|
||||
}
|
||||
],
|
||||
"label": "expected this to be `()`",
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion": null
|
||||
}
|
||||
],
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"message": "use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller",
|
||||
"code": null,
|
||||
"level": "help",
|
||||
"spans":
|
||||
[
|
||||
{
|
||||
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
|
||||
"byte_start": 23617,
|
||||
"byte_end": 23617,
|
||||
"line_start": 670,
|
||||
"line_end": 670,
|
||||
"column_start": 58,
|
||||
"column_end": 58,
|
||||
"is_primary": true,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": " $dst.write_fmt($crate::format_args_nl!($($arg)*))",
|
||||
"highlight_start": 58,
|
||||
"highlight_end": 58
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": "?",
|
||||
"suggestion_applicability": "HasPlaceholders",
|
||||
"expansion":
|
||||
{
|
||||
"span":
|
||||
{
|
||||
"file_name": "lib.rs",
|
||||
"byte_start": 144,
|
||||
"byte_end": 171,
|
||||
"line_start": 5,
|
||||
"line_end": 5,
|
||||
"column_start": 9,
|
||||
"column_end": 36,
|
||||
"is_primary": false,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": " writeln!(w, \"but not here\")",
|
||||
"highlight_start": 9,
|
||||
"highlight_end": 36
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion": null
|
||||
},
|
||||
"macro_decl_name": "writeln!",
|
||||
"def_site_span":
|
||||
{
|
||||
"file_name": "__SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs",
|
||||
"byte_start": 23434,
|
||||
"byte_end": 23454,
|
||||
"line_start": 665,
|
||||
"line_end": 665,
|
||||
"column_start": 1,
|
||||
"column_end": 21,
|
||||
"is_primary": false,
|
||||
"text":
|
||||
[
|
||||
{
|
||||
"text": "macro_rules! writeln {",
|
||||
"highlight_start": 1,
|
||||
"highlight_end": 21
|
||||
}
|
||||
],
|
||||
"label": null,
|
||||
"suggested_replacement": null,
|
||||
"suggestion_applicability": null,
|
||||
"expansion": null
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"children":
|
||||
[],
|
||||
"rendered": null
|
||||
}
|
||||
],
|
||||
"rendered": "error[E0308]: mismatched types\n --> lib.rs:5:9\n |\n2 | / if true {\n3 | | writeln!(w, \"`;?` here ->\")?;\n4 | | } else {\n5 | | writeln!(w, \"but not here\")\n | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`\n6 | | }\n | |_____- expected this to be `()`\n |\n = note: expected unit type `()`\n found enum `Result<(), std::fmt::Error>`\n = note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)\nhelp: consider using a semicolon here\n |\n6 | };\n | +\nhelp: you might have meant to return this value\n |\n5 | return writeln!(w, \"but not here\");\n | ++++++ +\nhelp: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller\n --> __SYSROOT__/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58\n |\n67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?\n | +\n\n"
|
||||
}"#.replace("\n", ""));
|
||||
|
||||
std::process::exit(2);
|
||||
}
|
||||
}
|
||||
"##.replace("__SYSROOT__", &sysroot))
|
||||
.build();
|
||||
rustc.cargo("build").run();
|
||||
let rustc_bin = rustc.bin("rustc-replay");
|
||||
|
||||
// The output here should not say `Fixed`.
|
||||
//
|
||||
// It is OK to compare the full diagnostic output here because the text is
|
||||
// hard-coded in rustc-replay. Normally tests should not be checking the
|
||||
// compiler output.
|
||||
p.cargo("fix --lib --allow-no-vcs --broken-code")
|
||||
.env("__CARGO_FIX_YOLO", "1")
|
||||
.env("RUSTC", &rustc_bin)
|
||||
.with_status(101)
|
||||
.with_stderr(r#"[CHECKING] foo v0.0.0 ([..])
|
||||
error[E0308]: mismatched types
|
||||
--> lib.rs:5:9
|
||||
|
|
||||
2 | / if true {
|
||||
3 | | writeln!(w, "`;?` here ->")?;
|
||||
4 | | } else {
|
||||
5 | | writeln!(w, "but not here")
|
||||
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `Result<(), Error>`
|
||||
6 | | }
|
||||
| |_____- expected this to be `()`
|
||||
|
|
||||
= note: expected unit type `()`
|
||||
found enum `Result<(), std::fmt::Error>`
|
||||
= note: this error originates in the macro `writeln` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
help: consider using a semicolon here
|
||||
|
|
||||
6 | };
|
||||
| +
|
||||
help: you might have meant to return this value
|
||||
|
|
||||
5 | return writeln!(w, "but not here");
|
||||
| ++++++ +
|
||||
help: use the `?` operator to extract the `Result<(), std::fmt::Error>` value, propagating a `Result::Err` value to the caller
|
||||
--> [..]/lib/rustlib/src/rust/library/core/src/macros/mod.rs:670:58
|
||||
|
|
||||
67| $dst.write_fmt($crate::format_args_nl!($($arg)*))?
|
||||
| +
|
||||
|
||||
[ERROR] could not compile `foo` (lib) due to 1 previous error
|
||||
"#)
|
||||
.run();
|
||||
}
|
||||
|
||||
// This fixes rust-lang/rust#123304.
|
||||
// If that lint stops emitting duplicate suggestions,
|
||||
// we might need to find a substitution.
|
||||
|
|
|
@ -982,3 +982,43 @@ error: `im_a_teapot` is specified
|
|||
)
|
||||
.run();
|
||||
}
|
||||
|
||||
#[cargo_test]
|
||||
fn dont_always_inherit_workspace_lints() {
|
||||
let p = project()
|
||||
.file(
|
||||
"Cargo.toml",
|
||||
r#"
|
||||
[workspace]
|
||||
members = ["foo"]
|
||||
|
||||
[workspace.lints.cargo]
|
||||
im-a-teapot = "warn"
|
||||
"#,
|
||||
)
|
||||
.file(
|
||||
"foo/Cargo.toml",
|
||||
r#"
|
||||
cargo-features = ["test-dummy-unstable"]
|
||||
|
||||
[package]
|
||||
name = "foo"
|
||||
version = "0.0.1"
|
||||
edition = "2015"
|
||||
authors = []
|
||||
im-a-teapot = true
|
||||
"#,
|
||||
)
|
||||
.file("foo/src/lib.rs", "")
|
||||
.build();
|
||||
|
||||
p.cargo("check -Zcargo-lints")
|
||||
.masquerade_as_nightly_cargo(&["cargo-lints"])
|
||||
.with_stderr(
|
||||
"\
|
||||
[CHECKING] foo v0.0.1 ([CWD]/foo)
|
||||
[FINISHED] [..]
|
||||
",
|
||||
)
|
||||
.run();
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue