Filed here because the MCP scope used by the assistant session that produced #407 cannot write to KSXGitHub/perfectionist. Forward upstream when convenient. See #408 for the underlying rustfmt contradiction that forced us to suppress this lint at all.
Summary
When perfectionist::macro_trailing_comma is suppressed at crate scope with #[expect], the rule does not register a fulfillment, so rustc's unfulfilled_lint_expectations lint fires. This makes the user-preferred #[expect] form unusable on its own, even though violations exist in the crate.
Reproduction
In a file with at least one vec! invocation that would trigger the rule (see #408 for the shapes that fire):
#![cfg_attr(dylint_lib = "perfectionist", feature(register_tool))]
#![cfg_attr(dylint_lib = "perfectionist", register_tool(perfectionist))]
#![cfg_attr(
dylint_lib = "perfectionist",
expect(
perfectionist::macro_trailing_comma,
reason = "rustfmt collapses single-element multi-line vec!"
)
)]
Running RUSTFLAGS="-D warnings" cargo dylint --all -- --all-features --all-targets reports:
error: this lint expectation is unfulfilled
--> tests/tree_builder.rs:6:9
|
6 | perfectionist::macro_trailing_comma,
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
The same crate without the #[expect] reports the underlying macro_trailing_comma violations, so the diagnostic is suppressible — but suppression appears to short-circuit the rule entirely instead of letting rustc track the fulfillment.
Expected behaviour
macro_trailing_comma should always emit its diagnostic with the appropriate span. rustc's #[expect] machinery is responsible for hiding the visible output and marking the expectation fulfilled. The rule should not early-exit when it sees a crate-level #[allow]/#[expect] of itself.
Current workaround in this repo
PR #407 pairs the #[expect] with #[allow(unfulfilled_lint_expectations, reason = "perfectionist's macro_trailing_comma short-circuits when its lint is allowed/expected at crate scope")], which defeats the point of preferring #[expect] over #[allow].
Documentation gap, additionally
The working suppression incantation is non-obvious and required several iterations during #407:
#![cfg_attr(dylint_lib = "perfectionist", feature(register_tool))]
#![cfg_attr(dylint_lib = "perfectionist", register_tool(perfectionist))]
#![cfg_attr(
dylint_lib = "perfectionist",
expect(perfectionist::<rule>, reason = "…")
)]
#![allow(unexpected_cfgs, reason = "dylint_lib is not in --check-cfg")]
Without register_tool, stable consumers hit error[E0710]: unknown tool name 'perfectionist'. Without the dylint_lib cfg gate, every non-dylint cargo check fails. A README section describing this recipe would save downstream consumers a lot of debugging.
Filed here because the MCP scope used by the assistant session that produced #407 cannot write to
KSXGitHub/perfectionist. Forward upstream when convenient. See #408 for the underlying rustfmt contradiction that forced us to suppress this lint at all.Summary
When
perfectionist::macro_trailing_commais suppressed at crate scope with#[expect], the rule does not register a fulfillment, so rustc'sunfulfilled_lint_expectationslint fires. This makes the user-preferred#[expect]form unusable on its own, even though violations exist in the crate.Reproduction
In a file with at least one
vec!invocation that would trigger the rule (see #408 for the shapes that fire):Running
RUSTFLAGS="-D warnings" cargo dylint --all -- --all-features --all-targetsreports:The same crate without the
#[expect]reports the underlyingmacro_trailing_commaviolations, so the diagnostic is suppressible — but suppression appears to short-circuit the rule entirely instead of letting rustc track the fulfillment.Expected behaviour
macro_trailing_commashould always emit its diagnostic with the appropriate span. rustc's#[expect]machinery is responsible for hiding the visible output and marking the expectation fulfilled. The rule should not early-exit when it sees a crate-level#[allow]/#[expect]of itself.Current workaround in this repo
PR #407 pairs the
#[expect]with#[allow(unfulfilled_lint_expectations, reason = "perfectionist's macro_trailing_comma short-circuits when its lint is allowed/expected at crate scope")], which defeats the point of preferring#[expect]over#[allow].Documentation gap, additionally
The working suppression incantation is non-obvious and required several iterations during #407:
Without
register_tool, stable consumers hiterror[E0710]: unknown tool name 'perfectionist'. Without thedylint_libcfg gate, every non-dylintcargo checkfails. A README section describing this recipe would save downstream consumers a lot of debugging.