Skip to content

Commit 28f14ef

Browse files
committed
fix: Expand on precedence options
1 parent 660bcdb commit 28f14ef

File tree

1 file changed

+90
-34
lines changed

1 file changed

+90
-34
lines changed

text/3389-manifest-lint.md

Lines changed: 90 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -289,54 +289,110 @@ If we add lint/linter config in the future
289289

290290
## Lint Precedence
291291

292-
The priority field is meant to allow mimicking
292+
Currently, `rustc` allows lints to be controlled on the command-line with the
293+
last level for a lint winning. They may also be specified as attributes with
294+
the last instance winning. `cargo` adds the `RUSTFLAGS` environment variable
295+
and `config.toml` entry. On top of this, there are lint groups that act as
296+
aliases to sets of lints. These groups may be disjoint, supersets, or they may
297+
even intersect.
298+
299+
Example `RUSTFLAGS`:
293300
- `-Aclippy::all -Wclippy::doc_markdown`
294-
- `-D future-incompatible -A semicolon_in_expressions_from_macros`
301+
- `-Dfuture-incompatible -Asemicolon_in_expressions_from_macros`
295302

296-
We can't order lints based on the `level` as which we want first is dependent on the context (see above).
303+
In providing lint-level configuration in `Cargo.toml`, users will need to be
304+
able to set the lint level for group and then override individual lints within
305+
that group while interacting with the existing `RUSTFLAGS` system.
297306

298-
We can't rely on the order of the keys in the table as that is undefined in TOML.
307+
We have chosen **Option 6** with `priority` being in-scope for this RFC and
308+
warnings and auto-sorting as a future possibility.
299309

300-
For the most part, people won't need granularity, so we could instead start
301-
with a `priority: bool` field. This might get confusing to mix with numbers
302-
though (what does `false` and `true` map to?). There is also the problem that
303-
generally people will want to opt a specific lint into being low-priority (the
304-
group) and the leave the exceptions at default but making `priority = true` the
305-
default would read weird (everything is a priority but one or two items).
306-
307-
We could pass this to the tool and say "you figure it out" based on which is
308-
the most specific and least specific. This requires lint groups to be
309-
subsets or disjoint of each other to avoid ambiguity. While this might hold
310-
today, I'm a bit cautious of putting this requirement on us forever. For
311-
example, if we merged `cargo semver-check`, there are proposed lint groups
312-
based on what a lint's user-overideable semver-level is which couldn't be
313-
guaranteed to meet these requirements. On the implementation side, this will
314-
require a new channel to communicate these lints to the tools (unless we infer
315-
order for flags/config as well) and require them to organize their data in a
316-
way for it to inferred.
310+
**Option 1: Auto-sort**
311+
```rust
312+
[lints.rust]
313+
unsafe_code = "deny"
314+
allow_dead_code = "allow"
315+
all = "warn"
316+
```
317+
- Unable to handle if two intersecting groups are assigned different levels
317318

318-
We could use an array instead of a table:
319+
**Option 2: Ordered keys**
320+
```rust
321+
[lints.rust]
322+
all = "warn"
323+
allow_dead_code = "allow"
324+
unsafe_code = "deny"
325+
```
326+
- Relies on the order of keys in a TOML table which is undefined
327+
- Without standard ordering semantics, like with `[]`, users or formatters
328+
might naively reformat the table which would affect the semantics
319329

320-
Unconfigurable:
330+
**Option 3: Array of tables**
321331
```toml
332+
# inline table
322333
[lints]
323-
clippy = [
324-
{ all = "allow" },
325-
{ doc_markdown = "warn" },
334+
rust = [
335+
{ lint = "all", level = "warn" },
336+
{ lint = "allow_dead_code", level = "allow" },
337+
{ lint = "unsafe_code", level = "deny" },
326338
]
339+
# standard table
340+
[[lints.clippy]]
341+
lint = "all"
342+
level = "warn"
343+
[[lints.clippy]]
344+
lint = "cyclomatic_complexity"
345+
level = "allow"
327346
```
347+
- The syntax for this seems overly verbose
348+
- Complex, nested structures aren't the easiest to work with in TOML
328349

329-
Configurable:
350+
**Option 4: Compact array of tables**
330351
```toml
331-
[[lints.clippy.all]]
332-
level = "allow"
333-
[[lints.clippy.doc_markdown]]
334-
level = "warn"
352+
[tools.rust]
353+
lints = [
354+
{ warn = "all" },
355+
{ allow = "allow_dead_code" },
356+
{ deny = "unsafe_code" },
357+
]
358+
```
359+
- *Note:* `lints.rust = []` wasn't used as that won't work with linter configuration in the future
360+
- *Note:* Top-level table was changed to avoid `lints.rust.lints` redundancy and would allow us to open this up to more tools in the future
361+
- *Note:* `<level> = <lint>` (instead of the other way) to keep the keys finite so we can add more fields in the future
362+
- Mirrors the familiar `RUSTFLAGS` syntax
363+
- Complex, nested structures aren't the easiest to work with in TOML
364+
365+
**Option 5: `priority` field**
366+
```rust
367+
[lints.rust]
368+
all = { level = "warn", priority = -1 }
369+
allow_dead_code = "allow"
370+
unsafe_code = "deny"
335371
```
336-
Where the order is based on how to pass them on the command-line.
372+
- Difficult for the user to figure out there is a problem or how to address it
337373

338-
Complex TOML arrays tend to be less friendly to work with including the fact
339-
that TOML 1.0 does not allow multi-line inline tables.
374+
**Option 6: `priority` field with warnings and maybe auto-sort**
375+
```rust
376+
[lints.rust]
377+
all = "warn"
378+
allow_dead_code = "allow"
379+
unsafe_code = "deny"
380+
```
381+
- Option 1 (auto-sort) but using Option 5 (`priority` field) to break ties
382+
- Produces warnings to tell the user when `priority` may be needed
383+
- As `priority` is a low-level subset, we can start with that as an MVP. Later, we can add warnings for all the ambiguity cases. As we gain confidence in this, we can then add auto-sorting.
384+
385+
**Option 7: Explicit groups**
386+
```rust
387+
[lints.rust.groups]
388+
all = "warn"
389+
[lints.rust.lints]
390+
allow_dead_code = "allow"
391+
unsafe_code = "deny"
392+
```
393+
- Hard codes knowledge of `all`
394+
- Does not solve the intersecting group problem
395+
- Names aren't validated as being from a group without duplicating the work needed for Option 1 (auto-sort)
340396

341397
## Workspace Inheritance
342398

0 commit comments

Comments
 (0)