Add two build_assert! lints, build_assert_not_inlined and build_assert_can_be_const#13
Open
mqqz wants to merge 12 commits intoRust-for-Linux:trunkfrom
Open
Add two build_assert! lints, build_assert_not_inlined and build_assert_can_be_const#13mqqz wants to merge 12 commits intoRust-for-Linux:trunkfrom
build_assert! lints, build_assert_not_inlined and build_assert_can_be_const#13mqqz wants to merge 12 commits intoRust-for-Linux:trunkfrom
Conversation
Move the mono-item forward/backward graph construction out of `infallible_allocation` into a shared `mono_graph` module. This keeps the graph-building logic in one place and makes it reusable for later analyses that need monomorphized use edges with span information. No intended behavioral change. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Recognize `build_assert` as a special item, preferring explicit `#[klint::diagnostic_item]` annotations and keeping a conservative kernel-specific fallback for older trees. This extends the existing diagnostic-item discovery pattern so later lints can identify `build_assert!` semantically instead of relying on ad-hoc matching. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Later build_assert lints need to identify the asserted condition semantically, not by depending on one particular macro expansion shape. Add the shared helper that: - finds `build_assert!` through diagnostic-item-backed macro ancestry - recovers the first macro argument span from the source call site This gives later lints a stable source-level handle on the condition even if the macro body changes. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
The `build_assert` analysis needs to track two things cleanly: - what values a local expression depends on - what requirement a function imposes on its callers including scoped restoration of local bindings. Keeping this data model separate makes the later analysis code more manageable and avoids mixing state mechanics with propagation logic. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Add the local analysis that decides whether a build_assert condition is effectively constant or still depends on caller-visible values. This includes: - expression dependency classification - local bindings and assignments - direct-call return dependency mapping - per-body summary computation Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Extends local analysis with MIR monomorphized graph to resolve indirect calls and handle value/requirement flows through helpers, `fn` pointers, and `dyn` dispatch. This adds: - indirect calls resolution using the monomorphized graph - `dyn`-dispatch `impl` methods matching back to source - function summary computation up to a fixed point Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
`ClosureDiag` is a generic adapter for building diagnostics inline from a closure rather than `infallible_allocation`-specific logic. Move it into `diagnostic` and make it `pub` so later lints can reuse it instead of defining it locally. No intended behavioural change. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
UI test coverage includes: - `const`-only and `const`-generic cases - runtime-dependent parameter flow - local helper return-value flow - wrapper macros - function pointer calls - `dyn` dispatch, including same-name trait-method cases Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Add user-facing documentation for the new `build_assert_not_inlined` lint in `doc/build_assert_not_inlined.md`. Including: - which kinds of value flow are tracked - where propagation stops - the distinction from `const`-only `build_assert` uses Add corresponding entry in the "Implemented Lints" section of README. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Add a lint for `build_assert!` uses whose condition is already effectively constant. When the asserted condition does not depend on runtime values, the lint suggests using a `const` assert instead of relying on `build_assert!`. This reuses the shared build_assert analysis and emits alongside `build_assert_not_inlined`. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
UI test coverage includes: - `literals` - `const` generics - wrapper macros - local `const`-only helpers Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
Add user-facing documentation for the new `build_assert_can_be_const` lint in `doc/build_assert_can_be_const.md`. Including: - const-only and const-generic `build_assert!` uses - wrapper-macro and local-helper cases - the distinction from runtime-dependent `build_assert!` uses Add corresponding entry in the "Implemented Lints" section of README, and cross-reference it from the `build_assert_not_inlined` docs. Signed-off-by: Mohamad Alsadhan <mo@sdhn.cc>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Apologies for dropping a sizeable PR here with no prior heads-up; there's no expectation to review it quickly. I’m very happy to split it into smaller pieces or reorganize it in whatever way would make it easier to review.
This is my attempt at adding two (very related) lints:
build_assert_not_inlined(from Warn onbuild_assertcalls without#[inline(always)]#7)build_assert_can_be_const(as suggested in this discussion)The implementation ended up needing a small analysis framework due to the non-local nature of the lints. Requirements can propagate through local helpers, wrappers, function pointers, and other indirect calls.
Implementation
The implementation is built around a shared
build_assert!analysis pipeline rather than two unrelated lint passes. The core idea is:identify
build_assert!reliablycollect explicit
#[klint::diagnostic_item]annotations from source, if an item is still missing, fallback to existing out-of-band inference.recover the asserted condition at the source level
build_assert!classify what that condition depends on
either
Constant,RuntimeorParam(FxHashset<usize>).summarize that per function
each function body is analyzed into a
FunctionSummary:requirement: whether non-constant values flow intobuild_assert!return_dependency: how the function’s return value depends on inputsconst_only_build_asserts: source spans of constant assertions that should trigger theconstlintwe keep recomputing summaries up to a fixed-point i.e. when no other dependencies can be inferred.
propagate requirements through local call relationships
I reused/refactored and extended the work done to generate a monomorphised use graph for
infallible_allocationintomono_graph.rsneeded to analyze calls.direct local calls:
build_assert!return dependencies:
indirect calls:
dyn-dispatch cases back to source callsitesemit either lint (or none) accordingly :)
Tests
UI coverage was added for both lints.
tests/ui/build_assert_not_inlined.rstests cover:constgeneric mixturesdyn-dispatchmatchtests/ui/build_assert_can_be_consttests cover:constexpressionsconstgenericsconst-returning helpersconst-onlymatchconst-only assertionsDocs were also added:
doc/build_assert_not_inlined.mddoc/build_assert_can_be_const.mdand README entries in the "Implemented Lints" section.
Closes: #7