feat: add Cargo.toml lint profiles for relaxed and strict baselines#11
feat: add Cargo.toml lint profiles for relaxed and strict baselines#11RolandJentschETAS wants to merge 12 commits into
Conversation
Add recommended [lints.rust], [lints.clippy], and [profile.release] settings as Cargo.toml template files in the clippy/relaxed and clippy/strict directories. These profiles were previously documented inline in the SCORE docs (eclipse-score/score PR #2984) and are now maintained centrally here per reviewer feedback.
Add a comment in both Cargo.toml profiles pointing back to https://eclipse-score.github.io/score/contribute/development/rust/coding_guidelines.html and a sentence in README.md pointing to the same page for context.
|
See also eclipse-score/score#2984 |
PLeVasseur
left a comment
There was a problem hiding this comment.
Hey there @RolandJentschETAS 👋 thanks for pinging me on this.
Have to say upfront that I'm not super familiar with Bazel and that my understanding is that Rust modules in S-CORE should be "Bazel-first" or something like this (maybe wrong). That colored the kinds of feedback I tried to provide. If that's off-base, then please feel free to let me know. =)
I'm leaving this as Request changes, but pretty sure I don't have any rights to actually block on this, nor do I really want to as a guest reviewer. I wanted to make my intent clear on the request for updates tho ✌️
| # Lint groups first (lower priority). | ||
| "-Wunused", | ||
| # Specific lints. | ||
| "-Dunsafe_op_in_unsafe_fn", |
There was a problem hiding this comment.
RELAXED_RUSTC_FLAGS does not match lint-profiles/relaxed/Cargo.toml here. The relaxed Cargo profile sets:
unsafe_op_in_unsafe_fn = "warn"but the Bazel flag list uses:
"-Dunsafe_op_in_unsafe_fn",That makes the Bazel relaxed profile stricter than the Cargo relaxed profile, while the README says the current strict/relaxed split is this lint's level.
Could we change this to -Wunsafe_op_in_unsafe_fn? It would also be useful to add a small check that keeps STRICT_RUSTC_FLAGS / RELAXED_RUSTC_FLAGS in sync with the corresponding [lints.rust] tables, either in this PR or as a follow-up issue if you prefer to keep this change minimal.
I verified the behavior with a temporary consumer:
- Cargo relaxed profile:
cargo checksucceeds with anunsafe_op_in_unsafe_fnwarning. - Cargo strict profile:
cargo checkfails, as expected. - Bazel
RELAXED_RUSTC_FLAGS:bazel build //:unsafe_relaxedfails because the flag list passes-Dunsafe_op_in_unsafe_fn. - Bazel
STRICT_RUSTC_FLAGS:bazel build //:unsafe_strictalso fails, as expected.
So this appears isolated to the Bazel relaxed mapping; the Cargo relaxed profile behaved as expected in the probe.
There was a problem hiding this comment.
Good catch, thanks for the thorough probe. Fixed: RELAXED_RUSTC_FLAGS now uses -Wunsafe_op_in_unsafe_fn, so the Bazel relaxed profile matches the Cargo relaxed profile (warn). Strict stays at -D. I also added an automated sync check (see the workflow thread) so this class of drift fails CI.
| ## Clippy policy levels | ||
| - `clippy/strict/clippy.toml`: ASIL-B–oriented settings for safety-critical code (enables `pedantic`/`nursery`, disallows `panic`/`unwrap`/`expect`, forbids debug/print macros, and enforces size/complexity thresholds). | ||
| ## Rust lint policy levels | ||
| - `clippy/strict/clippy.toml`: ASIL-B–oriented settings for safety-critical code (enables `pedantic`/`nursery`, checks private items, disallows `panic`/`unwrap`/`expect`, forbids debug/print macros, and enforces size/complexity thresholds). |
There was a problem hiding this comment.
I think the strict-policy intent described here is good, but I do not think clippy/strict/clippy.toml by itself enforces most of the lint levels named in this sentence. The file currently only seems to configure Clippy options:
msrv = "1.90.0"
check-private-items = trueLints such as unwrap_used, expect_used, panic, dbg_macro, and print_stdout need to be enforced through Cargo [lints.clippy], crate attributes, Clippy command-line flags, or Bazel rules_rust lint configuration.
Could we either narrow the README wording to say that clippy.toml configures Clippy options, not these lint levels, or add a Bazel-native lint config for the claimed strict/relaxed Clippy levels?
For the Bazel-native path, rules_rust appears to support this through rust_lint_config(...) plus the lint_config attribute on Rust targets. I tested that locally with a temporary consumer: using only the strict clippy.toml, probes containing dynamic unwrap(), expect(), panic!(), println!, and dbg! passed under bazel build --config=clippy-strict. When I attached a rust_lint_config with the corresponding Clippy lint levels via lint_config, rust_clippy rejected the same probes.
If adding Bazel-native strict/relaxed lint targets is more than you want in this PR, I think documenting the current limitation here and opening a follow-up issue for rust_lint_config support would also resolve the immediate documentation mismatch and let you land this one.
There was a problem hiding this comment.
Agreed, the wording overstated it. Reworded the "Rust lint policy levels" section to make clear that clippy.toml only configures Clippy options (msrv, check-private-items, thresholds), while the actual lint levels (unwrap_used, panic, print_stdout, etc.) come from the Cargo [lints.clippy]/[lints.rust] tables in lint-profiles/, or from rustc-lints/flags.bzl for Bazel-first repos. Bazel-native rust_lint_config enforcement is a good follow-up; tracking it as a separate issue rather than expanding this PR.
| ## How to use lint policies in consumers | ||
| - Wire configs in your repo’s `.bazelrc` (mirrors `tests/.bazelrc`): | ||
| ``` | ||
| build:clippy-strict --@rules_rust//rust/settings:clippy.toml=@score_rust_policies//clippy/strict:clippy.toml |
There was a problem hiding this comment.
The README says this mirrors tests/.bazelrc, but the config names differ:
- README uses
build:clippy-strictandbuild:clippy-relaxed. tests/.bazelrcusesbuild:strictandbuild:relaxed.- The validation instructions later use
bazel build --config=strictand--config=relaxed.
Could we make the names consistent? Otherwise a consumer copying the README cannot compare directly against the test workspace, and the example commands do not match the example config definitions.
There was a problem hiding this comment.
Unified everything on clippy-strict/clippy-relaxed: tests/.bazelrc, the workflow, and the README validation commands now use the same names, so a consumer can copy directly from the README and compare against the test workspace.
| bazel-test: | ||
| runs-on: ubuntu-latest | ||
| env: | ||
| USE_BAZEL_VERSION: 8.6.0 |
There was a problem hiding this comment.
The workflow currently builds //:sample_clippy with the strict and relaxed Clippy configs, but it does not appear to exercise the new lint-profiles/{strict,relaxed}/Cargo.toml files or rustc-lints/flags.bzl.
This matters because the PR currently seems to contain a concrete Cargo/Bazel drift bug: lint-profiles/relaxed/Cargo.toml sets unsafe_op_in_unsafe_fn = "warn", while RELAXED_RUSTC_FLAGS uses -Dunsafe_op_in_unsafe_fn.
Could we add at least a small check that compares the Cargo [lints.rust] levels against STRICT_RUSTC_FLAGS and RELAXED_RUSTC_FLAGS? That would catch the current drift without requiring a large integration test.
It would also be useful, either here or in follow-up issues, to verify that the strict/relaxed profiles differ only where intended and that the exported Bazel labels for the new files are loadable by a consumer workspace. If this PR grows Bazel-native Clippy lint support via rust_lint_config, then a small consumer probe for representative Clippy denies such as unwrap_used, expect_used, panic, print_stdout, and dbg_macro would be a good regression test for that path too.
There was a problem hiding this comment.
Added tools/check_lint_sync.py, run as a CI step, which translates each Cargo [lints.rust] table into rustc flags and diffs them against STRICT_RUSTC_FLAGS/RELAXED_RUSTC_FLAGS. It catches exactly the -D vs -W drift you found (verified locally: passes now, fails if I reintroduce the bug). A full Bazel-native Clippy-deny regression test (unwrap_used, expect_used, etc. via rust_lint_config) is tracked as a follow-up.
| # License: Apache-2.0 (see LICENSE.md). | ||
|
|
||
| msrv = "1.90.0" No newline at end of file | ||
| msrv = "1.90.0" |
There was a problem hiding this comment.
Can we clarify the intended MSRV here? clippy/strict/clippy.toml sets msrv = "1.90.0", while the test workspace pins Rust 1.85.0 in tests/MODULE.bazel.
My understanding is that Clippy msrv normally represents the minimum Rust version the codebase supports. If the policy MSRV and the tested toolchain intentionally differ, it would help to document that relationship so consumers know which compiler version the policy is meant to target.
Could we either align these values, lower the Clippy msrv to the currently tested toolchain, or add a short note explaining why they intentionally differ? A broader compiler-version matrix could also be tracked as a follow-up issue if that is outside the intended scope of this PR.
There was a problem hiding this comment.
Documented the relationship in both clippy.toml files: msrv is the policy's target minimum supported Rust version and is intentionally independent of the toolchain pinned in tests/MODULE.bazel (1.85.0), which only validates config wiring. Happy to align them to a single value instead if you'd prefer — let me know which direction.
| try_err = "warn" | ||
| wildcard_enum_match_arm = "warn" | ||
|
|
||
| # Deny |
There was a problem hiding this comment.
The relaxed profile still denies several lints, including missing_panics_doc, undocumented_unsafe_blocks, wildcard_imports, and declare_interior_mutable_const. That may be exactly the right SCORE policy, but the README describes relaxed as suitable for tooling, generators, and tests where controlled panics/unwraps/debug printing are acceptable.
Could we document the intended boundary a bit more explicitly? In particular, it would help to say which safety/security lints remain hard errors even in the relaxed profile, and which lints are intentionally downgraded for tooling/test code.
This does not necessarily need to block this PR if the current deny list is intentional. If the boundary is still being worked out, a short README note plus a follow-up issue for the full strict/relaxed policy matrix would be enough from my perspective.
There was a problem hiding this comment.
Added a "Relaxed profile boundary" section to the README spelling out which safety/doc lints stay hard errors even in relaxed (missing_panics_doc, undocumented_unsafe_blocks, wildcard_imports, declare_interior_mutable_const), and that unsafe_op_in_unsafe_fn is the only rustc level that differs between strict and relaxed today. The full policy matrix is deferred to the coding-guidelines doc.
| missing_docs = "warn" | ||
| unused_results = "warn" | ||
| let_underscore_drop = "warn" | ||
| non_exhaustive_omitted_patterns = "warn" |
There was a problem hiding this comment.
non_exhaustive_omitted_patterns = "warn" currently produces an unknown lint warning on stable Rust in my probes:
warning: unknown lint: `non_exhaustive_omitted_patterns`
= note: the `non_exhaustive_omitted_patterns` lint is unstable
The same warning appears through the Bazel rustc flag list (-Wnon_exhaustive_omitted_patterns) with the PR's rules_rust toolchain. That means adopting the policy can inject a warning before user code is considered, which seems problematic for a safety-oriented policy that may expect warning-free builds.
Could we gate this lint by supported toolchain, remove it from the default stable baseline until it is available without #![feature(non_exhaustive_omitted_patterns_lint)], or document that this part of the profile requires nightly/unstable lint support? Given the surrounding guidance appears to favor stable toolchains, I would suggest not enabling this lint in the default stable profiles.
There was a problem hiding this comment.
Agreed it shouldn't inject a warning into a warning-free safety build on stable. Commented it out in both Cargo profiles and removed -Wnon_exhaustive_omitted_patterns from both flag lists, with a note to re-enable only on nightly (#![feature(non_exhaustive_omitted_patterns_lint)]).
Add recommended [lints.rust], [lints.clippy], and [profile.release] settings as Cargo.toml template files in the clippy/relaxed and clippy/strict directories.
These profiles were previously documented inline in the SCORE docs (eclipse-score/score PR #2984) and are now maintained centrally here per reviewer feedback.