Continuing the discussion from Linting and match ergonomics:
The very condensed version of all the match ergonomics discussions lately is that we want a way to enforce that a project’s code contains little comfort code and favours explicitness. This simplifies reviews e.g. in the (human!) safety critical sectors, because one does not need to know much about inference, autoderef, autoref, method resolution, … to figure out what a single line of code is doing.
Nonexhaustive list of lints that this category could contain:
- prefer
Type::method(x, y, z) <Type as Trait>::method(x, y, z) over x.method(y, z)
- prefer
let y: &u32 = &***x; over let y: &u32 = x; for some x which can be autodereferenced to an &u32
- prefer
let &S(ref foo) = bar; over let S(foo) = bar; for reference type bar
- except if explicitly requested like in
let S(foo) = &bar;
- prefer
let x: Type = y; over let x = y;. This can be fully automatically suggested and applied by rustfix. So the user can code with inference, and the clippy suggests inserting type annotations with the inferred types.
-
let x = |a| a + 1; and similar unnameable types are excluded of course. This might be fixed later by requiring let x: impl FnOnce(i32) -> i32 = |a| a + 1; or by requiring type annotations for closure arguments. We should probably not require both, as that is very verbose.
- prefer
foo::<T, U>(args) over foo(args). Inferring generic arguments can cause subtle changes. E.g. transmute(foo) will still work after foo's type changes as long as the size doesn’t change.