Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ version = "0.1.0"
edition = "2024"
publish = false

[workspace.lints.rust]
warnings = "deny"

[workspace.lints.clippy]
all = "deny"
pedantic = "deny"
nursery = "deny"
cargo = "deny"
multiple_crate_versions = "allow"
Comment on lines +30 to +31

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Set a lower priority for the clippy::cargo group

With manifest lint tables, Cargo ignores table order and Clippy rejects a lint group and an overridden member at the same priority. This combination makes cargo clippy fail with clippy::lint_groups_priority before checking the crate because clippy::cargo and clippy::multiple_crate_versions both default to priority 0; the old CLI flags did not trigger that manifest-priority lint. Set the group to a lower priority, for example cargo = { level = "deny", priority = -1 }, so the allow can override it.

Useful? React with 👍 / 👎.


[workspace.dependencies]
anyhow = "1"
askama = { version = "0.16.0", default-features = false }
Expand Down
16 changes: 2 additions & 14 deletions lib/rust.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,6 @@
writePythonApplication,
}:
let
defaultClippyDeniedLints = [
"warnings"
"clippy::all"
"clippy::pedantic"
"clippy::nursery"
"clippy::cargo"
];

defaultClippyAllowedLints = [
"clippy::multiple_crate_versions"
];

defaultRustToolchain = rustToolchain;

defaultRustsecAdvisoryDb = pkgs.fetchFromGitHub {
Expand All @@ -49,8 +37,8 @@ let
enable = true;
package = clippyPackage;
cargoArgs = [ "--all-targets" ];
deniedLints = defaultClippyDeniedLints;
allowedLints = defaultClippyAllowedLints;
deniedLints = [ ];
allowedLints = [ ];
Comment thread
andrewgazelka marked this conversation as resolved.
Comment on lines +40 to +41

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Default lint policy now contradicts the remaining repo-package test

Changing the shared default clippy.deniedLints to [] applies to every rust.resolvePolicy caller, including the repo package workspace exposed through repoPackages.*.passthru.policy. The PR updates the cargoUnitWorkspace assertion to expect an empty list, but the existing tests/default.nix repo-package assertion still expects warnings and the clippy groups, so the repo eval/lint check will fail. Either update that remaining assertion to the new Cargo.toml-owned contract or keep an explicit strict policy for repo packages.

};
tests = {
enable = true;
Expand Down
3 changes: 3 additions & 0 deletions modules/services/resource-monitor/stats-writer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,7 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
3 changes: 3 additions & 0 deletions packages/agents-md/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/code-tokenizer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition.workspace = true
publish.workspace = true
description = "Tantivy tokenizer that splits identifiers on camelCase, snake_case, and kebab-case boundaries"

[lints]
workspace = true

[dependencies]
strip-ansi-escapes.workspace = true
tantivy.workspace = true
3 changes: 3 additions & 0 deletions packages/dag-runner/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/file-search/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition.workspace = true
publish.workspace = true
description = "BM25 file indexer and searcher built on Tantivy"

[lints]
workspace = true

[lib]
name = "file_search"
path = "src/lib.rs"
Expand Down
3 changes: 3 additions & 0 deletions packages/ix-dev-diagnose/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ publish.workspace = true
description = "Collect JSON diagnostics for ix.dev HTTPS reachability"
license = "MIT"

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
base64.workspace = true
Expand Down
3 changes: 3 additions & 0 deletions packages/mcp/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/minecraft/nbt/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/minecraft/sync-managed/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
anyhow.workspace = true
clap = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/nix-cargo-unit/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@ description = "Render Cargo unit graphs as composable Nix derivations"
license = "MIT"
publish.workspace = true

[lints]
workspace = true

[dependencies]
askama = { workspace = true, default-features = false, features = ["derive", "std"] }
clap = { workspace = true, features = ["derive"] }
Expand Down
12 changes: 12 additions & 0 deletions packages/nix-cargo-unit/src/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ pub struct Unit {
pub profile: Profile,
#[serde(default)]
pub features: Vec<String>,
#[serde(default)]
pub lint_rustflags: Vec<String>,
#[serde(default)]
pub check_cfg_args: Vec<String>,
Comment on lines +26 to +29

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Populate lint flags from manifests instead

When the real Cargo unit graph is used, these fields are absent: Cargo's unit_graph::SerializedUnit still serializes only pkg_id, target, profile, platform, mode, features, is_std, and dependencies, and a local cargo +1.95.0 build --unit-graph -Z unstable-options with [lints] produced no lint_rustflags or check_cfg_args. Because the new fields default to empty here, every generated unit silently drops the workspace manifest lints, so nix-cargo-unit builds no longer deny warnings after the Nix-side defaults were removed.

Useful? React with 👍 / 👎.

pub mode: UnitMode,
#[serde(default)]
pub dependencies: Vec<Dependency>,
Expand Down Expand Up @@ -679,6 +683,14 @@ fn write_unit_identity(hasher: &mut sha2::Sha256, unit: &Unit) {
hasher.update(flag.as_bytes());
hasher.update(b"\0");
}
for flag in &unit.lint_rustflags {
hasher.update(flag.as_bytes());
hasher.update(b"\0");
}
for arg in &unit.check_cfg_args {
hasher.update(arg.as_bytes());
hasher.update(b"\0");
}
hasher.update(unit.mode.as_str().as_bytes());
hasher.update(b"\0");
if let Some(platform) = &unit.platform {
Expand Down
95 changes: 93 additions & 2 deletions packages/nix-cargo-unit/src/render.rs
Original file line number Diff line number Diff line change
Expand Up @@ -695,7 +695,7 @@ fn render_rustc_build_phase(
append_build_script_flag_reader(&mut script, &run_ref, unit);
}

push_rustc_args(&mut script, unit, &prepared.hashes[index]);
push_rustc_args(&mut script, unit, &prepared.hashes[index])?;
append_target_linker_arg(&mut script, unit);
append_extra_rustc_args(&mut script, unit);

Expand Down Expand Up @@ -814,7 +814,7 @@ fn collects_unused_crate_dependencies(unit: &Unit, options: &RenderOptions) -> b
options.deny_unused_crate_dependencies && !unit.is_external()
}

fn push_rustc_args(script: &mut String, unit: &Unit, hash: &str) {
fn push_rustc_args(script: &mut String, unit: &Unit, hash: &str) -> Result<()> {
push_arg(script, "--crate-name");
push_arg(script, &unit.target.name.replace('-', "_"));
push_arg(script, "--edition");
Expand Down Expand Up @@ -878,6 +878,12 @@ fn push_rustc_args(script: &mut String, unit: &Unit, hash: &str) {
for rustflag in &unit.profile.rustflags {
push_arg(script, rustflag);
}
for rustflag in &unit.lint_rustflags {
push_arg(script, rustflag);
Comment on lines 878 to +882

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve Cargo's lint flag precedence

For packages that set profile rustflags to override a manifest lint level, this renders the flags in the opposite order from Cargo: Cargo appends manifest lint flags before profile rustflags, while this puts profile.rustflags first and then lint_rustflags. Since rustc uses the later lint level for the same lint, generated unit builds can fail or pass differently from cargo build whenever profile rustflags adjust a lint configured in [lints].

Useful? React with 👍 / 👎.

}
for arg in &unit.check_cfg_args {
push_arg(script, arg);
}
Comment on lines +884 to +886

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Forward build-script check-cfg declarations

For crates that enable unexpected_cfgs and have a build script emit a dynamic cfg, Cargo forwards both cargo::rustc-cfg=has_foo and its matching cargo::rustc-check-cfg=cfg(has_foo) to the final rustc command. This only appends the static unit check_cfg_args, while the build-script reader later consumes rustc-cfg but not rustc-check-cfg, so generated builds reject valid build-script cfgs as unexpected even though cargo build accepts them.

Useful? React with 👍 / 👎.

for feature in &unit.features {
push_arg(script, "--cfg");
push_arg(script, &format!("feature=\"{feature}\""));
Expand All @@ -896,6 +902,8 @@ fn push_rustc_args(script: &mut String, unit: &Unit, hash: &str) {
push_arg(script, "--cap-lints");
push_arg(script, "warn");
}

Ok(())
}

fn lto_for_unit(unit: &Unit) -> Option<&'static str> {
Expand Down Expand Up @@ -2280,6 +2288,12 @@ fn render_doctest_command(
push_rustdoc_arg(&mut script, &unit.target.name.replace('-', "_"));
push_rustdoc_arg(&mut script, "--edition");
push_rustdoc_arg(&mut script, &unit.target.edition);
for rustflag in &unit.lint_rustflags {
push_rustdoc_arg(&mut script, rustflag);
}
for arg in &unit.check_cfg_args {
push_rustdoc_arg(&mut script, arg);
}
for feature in &unit.features {
push_rustdoc_arg(&mut script, "--cfg");
push_rustdoc_arg(&mut script, &format!("feature=\"{feature}\""));
Expand Down Expand Up @@ -3246,6 +3260,8 @@ version = "0.1.0"
"edition": "2024"
},
"profile": { "name": "release", "opt_level": "3", "rustflags": ["-C", "target-feature=+sse2"] },
"lint_rustflags": ["--deny=warnings", "--warn=unexpected_cfgs"],
"check_cfg_args": ["--check-cfg", "cfg(docsrs,test)"],
"features": [],
"mode": "build",
"dependencies": [
Expand Down Expand Up @@ -3280,6 +3296,10 @@ version = "0.1.0"
assert!(rendered.contains("doctest_runtime_library_paths=()"));
assert!(rendered.contains("rustdoc_args+=( \"''${build_script_rustdoc_args[@]}\" )"));
assert!(rendered.contains("doctest_build_args+=( '-C' )"));
assert!(rendered.contains("rustdoc_args+=( '--deny=warnings' )"));
assert!(rendered.contains("rustdoc_args+=( '--warn=unexpected_cfgs' )"));
assert!(rendered.contains("rustdoc_args+=( '--check-cfg' )"));
assert!(rendered.contains("rustdoc_args+=( 'cfg(docsrs,test)' )"));
assert!(rendered.contains("rustdoc_args+=( --doctest-build-arg \"$doctest_build_arg\" )"));
assert!(rendered.contains("case \"$link_search_path\" in"));
assert!(rendered.contains(
Expand Down Expand Up @@ -4491,4 +4511,75 @@ version = "0.1.0"
assert!(rendered.contains("export \"$cargo_metadata_env=$cargo_metadata_value\""));
fs::remove_dir_all(workspace).unwrap();
}

#[test]
fn unit_graph_lint_flags_render_as_rustc_args() {
let workspace = std::env::temp_dir().join(format!(
"nix-cargo-unit-lint-flags-test-{}",
std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.map_or(0, |duration| duration.as_nanos())
));
let _ = fs::remove_dir_all(&workspace);
fs::create_dir_all(workspace.join("src")).unwrap();
fs::write(workspace.join("src/lib.rs"), "pub fn marker() {}\n").unwrap();

let src_path = workspace.join("src/lib.rs");
let pkg_id = format!("path+file://{}#linted@0.1.0", workspace.display());
let graph: UnitGraph = serde_json::from_value(serde_json::json!({
"version": 1,
"units": [{
"pkg_id": pkg_id,
"target": {
"kind": ["lib"],
"crate_types": ["lib"],
"name": "linted",
"src_path": src_path,
"edition": "2024"
},
"profile": { "name": "dev", "opt_level": "0" },
"lint_rustflags": [
"--deny=clippy::all",
"--forbid=unsafe_code",
"--warn=unexpected_cfgs",
"--warn=clippy::pedantic",
"--check-cfg",
"cfg(ix_test)"
],
"check_cfg_args": [
"--check-cfg",
"cfg(docsrs,test)",
"--check-cfg",
"cfg(feature, values(\"alpha\", \"beta\"))"
],
"mode": "build",
"dependencies": []
}],
"roots": [0]
}))
.unwrap();

let rendered = render_units_nix(
&graph,
&RenderOptions {
workspace_root: workspace.clone(),
vendor_root: None,
cargo_lock_sources: CargoLockSources::default(),
content_addressed: false,
toolchain_id: None,
deny_unused_crate_dependencies: false,
},
)
.unwrap();

assert!(rendered.contains("rustc_args+=( '--deny=clippy::all' )"));
assert!(rendered.contains("rustc_args+=( '--forbid=unsafe_code' )"));
assert!(rendered.contains("rustc_args+=( '--warn=clippy::pedantic' )"));
assert!(rendered.contains("rustc_args+=( '--warn=unexpected_cfgs' )"));
assert!(rendered.contains("rustc_args+=( '--check-cfg' )"));
assert!(rendered.contains("rustc_args+=( 'cfg(docsrs,test)' )"));
assert!(rendered.contains("rustc_args+=( 'cfg(feature, values(\"alpha\", \"beta\"))' )"));
assert!(rendered.contains("rustc_args+=( 'cfg(ix_test)' )"));
fs::remove_dir_all(workspace).unwrap();
}
}
3 changes: 3 additions & 0 deletions packages/oci-image-builder/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ version.workspace = true
edition.workspace = true
publish.workspace = true

[lints]
workspace = true

[dependencies]
chrono = { workspace = true, default-features = false, features = ["clock", "std"] }
serde = { workspace = true, features = ["derive"] }
Expand Down
3 changes: 3 additions & 0 deletions packages/repo-walker/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ edition.workspace = true
publish.workspace = true
description = "Iterator over text files in a directory tree, honoring .gitignore and skipping known binary extensions"

[lints]
workspace = true

[dependencies]
ignore.workspace = true

Expand Down
10 changes: 2 additions & 8 deletions tests/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2946,14 +2946,8 @@ let
let
denied = cargoUnitWorkspace.policy.clippy.deniedLints;
in
builtins.all (lint: builtins.elem lint denied) [
"warnings"
"clippy::all"
"clippy::pedantic"
"clippy::nursery"
"clippy::cargo"
];
message = "cargo-unit clippy checks should deny the shared strict lint set by default";
denied == [ ];
message = "cargo-unit clippy policy should defer default lint levels to Cargo.toml";
}
{
assertion = cargoUnitWorkspace.policyChecks ? cargoMachete;
Expand Down
Loading