2
2
name = " patchy-bin"
3
3
version = " 1.3.0"
4
4
edition = " 2024"
5
- license = " MIT"
5
+ license = " MIT OR Apache-2.0 "
6
6
readme = " ./docs/README.md"
7
7
keywords = [" git" , " github" , " fork" , " patchy" ]
8
8
categories = [" development-tools" , " command-line-utilities" ]
@@ -58,12 +58,24 @@ inherits = "release"
58
58
codegen-units = 1
59
59
lto = " fat"
60
60
61
+ # ### lints ####
62
+
63
+ [lints .rustdoc ]
64
+ # it is usually sufficient to include the README
65
+ missing_crate_level_docs = " warn"
66
+ unescaped_backticks = " warn"
67
+
61
68
[lints .clippy ]
62
- # enable all lints (other than restriction: https://rust-lang.github.io/rust-clippy/master/index.html?groups=restriction#blanket_clippy_restriction_lints), then selectively disable
69
+ # enable all lints but:
70
+ # - selectively *enable* rules from `restriction`
71
+ # - selectively *disable* other rules that are annoying
72
+
63
73
pedantic = { priority = -1 , level = " warn" }
64
74
nursery = { priority = -1 , level = " warn" }
65
75
cargo = { priority = -1 , level = " warn" }
66
76
77
+ # # ENABLED
78
+
67
79
# Rust Analyzer's "fill match arms" code action is bugged and will not use "Self",
68
80
# so temporarily turn it off until that issue gets resolved
69
81
use_self = " allow"
@@ -78,84 +90,111 @@ missing_const_for_fn = "allow"
78
90
# we're not a crate: documenting all errors is not necessary
79
91
missing_errors_doc = " allow"
80
92
# placing an arbitrary limit on how many lines we can have is unnecessary
93
+ # if we have a function that's 300 lines long we should probably split it, right?
94
+ # but what if there's not really a good place to split it. Placing a piece of code
95
+ # into a function creates an extra abstraction. Each abstraction has a mental cost.
81
96
too_many_lines = " allow"
82
97
# it can't detect if the code has a condition to stop the iterator
83
98
maybe_infinite_iter = " allow"
84
99
100
+ # # DISABLED
101
+
85
102
# === Restrictions ===
86
103
# == safety ==
87
104
88
- # Each ' unsafe' block should always contain exactly 1 unsafe operation
89
- # with clear documentation why the invariants are upheld.
90
- undocumented_unsafe_blocks = " deny "
91
- unnecessary_safety_comment = " deny "
92
- unnecessary_safety_doc = " deny "
93
- multiple_unsafe_ops_per_block = " deny "
94
- # not specifying representation may cause undefined behaviour
95
- default_union_representation = " deny "
105
+ # unsafe blocks need to have their invariants upheld
106
+ undocumented_unsafe_blocks = " warn "
107
+ unnecessary_safety_comment = " warn "
108
+ unnecessary_safety_doc = " warn "
109
+ # each `unsafe` block must just have 1 unsafe operation
110
+ multiple_unsafe_ops_per_block = " warn "
111
+ # not specifying representation may cause UB
112
+ default_union_representation = " warn "
96
113
97
114
# == correctness ==
98
115
# Program may behave unexpectedly
99
116
100
- create_dir = " deny"
101
- filetype_is_file = " deny"
117
+ # usually creating a directory including all of its parents is the desired behaviour
118
+ create_dir = " warn"
119
+ # is_file doesn't cover special file types nor symlinks
120
+ filetype_is_file = " warn"
102
121
# may cause memory leaks
103
- mem_forget = " deny"
104
- assertions_on_result_states = " deny"
122
+ mem_forget = " warn"
123
+ # removes valuable information
124
+ assertions_on_result_states = " warn"
105
125
# The conversion might include a dangerous cast that might go undetected due to the type being inferred.
106
- as_pointer_underscore = " deny"
107
- as_underscore = " deny"
126
+ as_pointer_underscore = " warn"
127
+ # its better to be specific
128
+ as_underscore = " warn"
108
129
# bloats the binary size with unneeded files
109
- doc_include_without_cfg = " deny "
130
+ doc_include_without_cfg = " warn "
110
131
# casting a function to a pointer is likely a mistake
111
- fn_to_numeric_cast_any = " deny "
112
- # integer division discards the remainder and is likely a mistake
113
- integer_division = " deny "
114
- lossy_float_literal = " deny "
115
- wildcard_enum_match_arm = " deny "
132
+ fn_to_numeric_cast_any = " warn "
133
+ # "exact" float value that cannot be represented
134
+ lossy_float_literal = " warn "
135
+ # new enum variants added by the library updates can be missed
136
+ wildcard_enum_match_arm = " warn "
116
137
117
138
# == performance ==
118
139
119
- # .to_string() is problematic because it does through the whole Display pipeline
120
- str_to_string = " warn"
140
+ # type information is valuable, lets not lose it
121
141
non_zero_suggestions = " warn"
122
142
mutex_atomic = " warn"
123
143
rc_mutex = " warn"
124
144
rc_buffer = " warn"
125
145
# prefer using pattern matching
126
146
string_lit_chars_any = " warn"
127
- missing_asserts_for_indexing = " warn"
128
- pathbuf_init_then_push = " warn"
129
147
130
- # == readabilty ==
148
+ # == readability ==
131
149
150
+ # functional path composition is nice
151
+ pathbuf_init_then_push = " warn"
152
+ # must use e.g. 123_i32 instead of 123i32
132
153
unseparated_literal_suffix = " warn"
154
+ # Foo { a: _, b, c: _ } => Foo { b, .. }
133
155
unneeded_field_pattern = " warn"
156
+ # use std::io::{self} => use std::io
134
157
unnecessary_self_imports = " warn"
158
+ # Err(x)? => return Err(x)
135
159
try_err = " warn"
160
+ # (0..3).map(|_| x) => iter::repeat(x).take(3)
136
161
map_with_unused_argument_over_ranges = " warn"
137
162
# better be explicit with .clone()
138
163
string_to_string = " warn"
139
164
# no need to be extra verbose, and makes code easier to modify as well
140
165
redundant_type_annotations = " warn"
141
166
# having multiple layout styles can be confusing
167
+ # I prefer mod.rs because the whole module is encapsulated in 1 directory
168
+ # instead of a my_module/ and a my_module.rs, which is 1 file + 1 directory
169
+ # always use: mod.rs
142
170
self_named_module_files = " warn"
143
171
# having an explicit, even if just containing a comment,
144
172
# "else" branch improves readability
145
173
else_if_without_else = " warn"
146
174
# explicit annotation of ! for functions that never return
147
175
# due to having infinite loops
148
176
infinite_loop = " warn"
149
- semicolon_outside_block = " warn"
177
+ # for consistency: { x }; => { x; }
178
+ semicolon_inside_block = " warn"
179
+ # idiomatic to put tests into #[cfg(test)]
150
180
tests_outside_test_module = " warn"
181
+ # #[allow] => #[expect]
151
182
allow_attributes = " warn"
183
+ # always must specify a reason why we're opting out of a lint
152
184
allow_attributes_without_reason = " warn"
185
+ # do not use raw strings if we don't have to
153
186
needless_raw_strings = " warn"
187
+ # makes for confusing code
154
188
mixed_read_write_in_expression = " warn"
189
+ # when panicking its important to know what happened and why,
190
+ # and a helpful message helps a LOT with that.
155
191
missing_assert_message = " warn"
192
+ # using index [] is more clear and concise
156
193
get_unwrap = " warn"
157
194
if_then_some_else_none = " warn"
195
+ # turbofish ::<> can't be used to specify the type of an impl Trait parameter
158
196
impl_trait_in_params = " warn"
197
+ # throws away the error
159
198
map_err_ignore = " warn"
160
199
# explicit imports
161
200
alloc_instead_of_core = " warn"
@@ -165,18 +204,34 @@ cfg_not_test = "warn"
165
204
# we instantly might think "expensive". But cloning a pointer isn't. It's
166
205
# good to be explicit
167
206
clone_on_ref_ptr = " warn"
207
+ # more readable to use hex literals sometimes
168
208
decimal_literal_representation = " warn"
209
+ # instead use: Infallible {} => !
210
+ empty_enum = " warn"
211
+ # enum A { B(), C } => enum A { B, C }
169
212
empty_enum_variants_with_brackets = " warn"
213
+ # struct A() => struct A
170
214
empty_structs_with_brackets = " warn"
215
+ # having error types named Error can be confusing
171
216
error_impl_error = " warn"
217
+ # use x86_intel instead
172
218
inline_asm_x86_att_syntax = " warn"
219
+ # splitting the implementation for a type makes code harder to navigate
173
220
multiple_inherent_impl = " warn"
221
+ # pub(in super) => pub(super)
174
222
pub_without_shorthand = " warn"
223
+ # use the same name as the trait method's default names when implement the trait
175
224
renamed_function_params = " warn"
225
+ # unnecessary pattern binding can be confusing
226
+ # example: A { a, .. } => A { a } where A = struct A { a: usize }
176
227
rest_pat_in_fully_bound_structs = " warn"
177
228
# same name from a trait and one not from a trait can be confusing
178
229
same_name_method = " warn"
179
230
# more explicit and avoids polluting the scope
231
+ # example: use std::io::Write => use std::io::Write as _ if Write only used for its methods
180
232
unused_trait_names = " warn"
233
+ # simpler and more obvious deref:
234
+ # example: &vec[..] => &*vec
181
235
deref_by_slicing = " warn"
236
+ # use fs::read instead of intermediate values
182
237
verbose_file_reads = " warn"
0 commit comments