Skip to content

feat: add Cargo.toml lint profiles for relaxed and strict baselines#11

Open
RolandJentschETAS wants to merge 12 commits into
mainfrom
improve_rust_coding_guidelines
Open

feat: add Cargo.toml lint profiles for relaxed and strict baselines#11
RolandJentschETAS wants to merge 12 commits into
mainfrom
improve_rust_coding_guidelines

Conversation

@RolandJentschETAS

Copy link
Copy Markdown

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 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.
@RolandJentschETAS

Copy link
Copy Markdown
Author

See also eclipse-score/score#2984

@PLeVasseur PLeVasseur left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 ✌️

Comment thread rustc-lints/flags.bzl Outdated
# Lint groups first (lower priority).
"-Wunused",
# Specific lints.
"-Dunsafe_op_in_unsafe_fn",

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 check succeeds with an unsafe_op_in_unsafe_fn warning.
  • Cargo strict profile: cargo check fails, as expected.
  • Bazel RELAXED_RUSTC_FLAGS: bazel build //:unsafe_relaxed fails because the flag list passes -Dunsafe_op_in_unsafe_fn.
  • Bazel STRICT_RUSTC_FLAGS: bazel build //:unsafe_strict also fails, as expected.

So this appears isolated to the Bazel relaxed mapping; the Cargo relaxed profile behaved as expected in the probe.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

Comment thread README.md Outdated
## 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).

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 = true

Lints 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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

Comment thread README.md
## 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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

The README says this mirrors tests/.bazelrc, but the config names differ:

  • README uses build:clippy-strict and build:clippy-relaxed.
  • tests/.bazelrc uses build:strict and build:relaxed.
  • The validation instructions later use bazel build --config=strict and --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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

Comment thread clippy/strict/clippy.toml
# License: Apache-2.0 (see LICENSE.md).

msrv = "1.90.0" No newline at end of file
msrv = "1.90.0"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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.

Comment thread lint-profiles/strict/Cargo.toml Outdated
missing_docs = "warn"
unused_results = "warn"
let_underscore_drop = "warn"
non_exhaustive_omitted_patterns = "warn"

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

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)]).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants