]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
migrate: `nonstandard_style.rs`
[rust.git] / compiler / rustc_lint / src / lints.rs
1 use rustc_errors::{fluent, AddSubdiagnostic, Applicability, DecorateLint, EmissionGuarantee};
2 use rustc_hir::def_id::DefId;
3 use rustc_macros::{LintDiagnostic, SessionSubdiagnostic};
4 use rustc_middle::ty::{Predicate, Ty, TyCtxt};
5 use rustc_span::{symbol::Ident, Span, Symbol};
6
7 use crate::LateContext;
8
9 #[derive(LintDiagnostic)]
10 #[diag(lint_non_camel_case_type)]
11 pub struct NonCamelCaseType<'a> {
12     pub sort: &'a str,
13     pub name: &'a str,
14     #[subdiagnostic]
15     pub sub: NonCamelCaseTypeSub,
16 }
17
18 #[derive(SessionSubdiagnostic)]
19 pub enum NonCamelCaseTypeSub {
20     #[label(label)]
21     Label {
22         #[primary_span]
23         span: Span,
24     },
25     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
26     Suggestion {
27         #[primary_span]
28         span: Span,
29         replace: String,
30     },
31 }
32
33 #[derive(LintDiagnostic)]
34 #[diag(lint_non_snake_case)]
35 pub struct NonSnakeCaseDiag<'a> {
36     pub sort: &'a str,
37     pub name: &'a str,
38     pub sc: String,
39     #[subdiagnostic]
40     pub sub: NonSnakeCaseDiagSub,
41 }
42
43 pub enum NonSnakeCaseDiagSub {
44     Label { span: Span },
45     Help,
46     RenameOrConvertSuggestion { span: Span, suggestion: Ident },
47     ConvertSuggestion { span: Span, suggestion: String },
48     SuggestionAndNote { span: Span },
49 }
50
51 impl AddSubdiagnostic for NonSnakeCaseDiagSub {
52     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
53         match self {
54             NonSnakeCaseDiagSub::Label { span } => {
55                 diag.span_label(span, fluent::label);
56             }
57             NonSnakeCaseDiagSub::Help => {
58                 diag.help(fluent::help);
59             }
60             NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
61                 diag.span_suggestion(
62                     span,
63                     fluent::convert_suggestion,
64                     suggestion,
65                     Applicability::MaybeIncorrect,
66                 );
67             }
68             NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
69                 diag.span_suggestion(
70                     span,
71                     fluent::rename_or_convert_suggestion,
72                     suggestion,
73                     Applicability::MaybeIncorrect,
74                 );
75             }
76             NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
77                 diag.note(fluent::cannot_convert_note);
78                 diag.span_suggestion(
79                     span,
80                     fluent::rename_suggestion,
81                     "",
82                     Applicability::MaybeIncorrect,
83                 );
84             }
85         };
86     }
87 }
88
89 #[derive(LintDiagnostic)]
90 #[diag(lint_non_upper_case_global)]
91 pub struct NonUpperCaseGlobal<'a> {
92     pub sort: &'a str,
93     pub name: &'a str,
94     #[subdiagnostic]
95     pub sub: NonUpperCaseGlobalSub,
96 }
97
98 #[derive(SessionSubdiagnostic)]
99 pub enum NonUpperCaseGlobalSub {
100     #[label(label)]
101     Label {
102         #[primary_span]
103         span: Span,
104     },
105     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
106     Suggestion {
107         #[primary_span]
108         span: Span,
109         replace: String,
110     },
111 }
112
113 #[derive(LintDiagnostic)]
114 #[diag(lint_noop_method_call)]
115 #[note]
116 pub struct NoopMethodCallDiag<'a> {
117     pub method: Symbol,
118     pub receiver_ty: Ty<'a>,
119     #[label]
120     pub label: Span,
121 }
122
123 #[derive(LintDiagnostic)]
124 #[diag(lint_pass_by_value)]
125 pub struct PassByValueDiag {
126     pub ty: String,
127     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
128     pub suggestion: Span,
129 }
130
131 #[derive(LintDiagnostic)]
132 #[diag(lint_redundant_semicolons)]
133 pub struct RedundantSemicolonsDiag {
134     pub multiple: bool,
135     #[suggestion(code = "", applicability = "maybe-incorrect")]
136     pub suggestion: Span,
137 }
138
139 pub struct DropTraitConstraintsDiag<'a> {
140     pub predicate: Predicate<'a>,
141     pub tcx: TyCtxt<'a>,
142     pub def_id: DefId,
143 }
144
145 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropTraitConstraintsDiag<'a> {
146     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
147         let mut diag = diag.build(fluent::lint_drop_trait_constraints);
148         diag.set_arg("predicate", self.predicate);
149         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
150         diag.emit();
151     }
152 }
153
154 pub struct DropGlue<'a> {
155     pub tcx: TyCtxt<'a>,
156     pub def_id: DefId,
157 }
158
159 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropGlue<'a> {
160     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
161         let mut diag = diag.build(fluent::lint_drop_glue);
162         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
163         diag.emit();
164     }
165 }
166
167 #[derive(LintDiagnostic)]
168 #[diag(lint_range_endpoint_out_of_range)]
169 pub struct RangeEndpointOutOfRange<'a> {
170     pub ty: &'a str,
171     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
172     pub suggestion: Span,
173     pub start: String,
174     pub literal: u128,
175     pub suffix: &'a str,
176 }
177
178 #[derive(LintDiagnostic)]
179 #[diag(lint_overflowing_bin_hex)]
180 pub struct OverflowingBinHex<'a> {
181     pub ty: &'a str,
182     pub lit: String,
183     pub dec: u128,
184     pub actually: String,
185     #[subdiagnostic]
186     pub sign: OverflowingBinHexSign,
187     #[subdiagnostic]
188     pub sub: Option<OverflowingBinHexSub<'a>>,
189 }
190
191 pub enum OverflowingBinHexSign {
192     Positive,
193     Negative,
194 }
195
196 impl AddSubdiagnostic for OverflowingBinHexSign {
197     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
198         match self {
199             OverflowingBinHexSign::Positive => {
200                 diag.note(fluent::positive_note);
201             }
202             OverflowingBinHexSign::Negative => {
203                 diag.note(fluent::negative_note);
204                 diag.note(fluent::negative_becomes_note);
205             }
206         }
207     }
208 }
209
210 #[derive(SessionSubdiagnostic)]
211 pub enum OverflowingBinHexSub<'a> {
212     #[suggestion(
213         suggestion,
214         code = "{sans_suffix}{suggestion_ty}",
215         applicability = "machine-applicable"
216     )]
217     Suggestion {
218         #[primary_span]
219         span: Span,
220         suggestion_ty: &'a str,
221         sans_suffix: &'a str,
222     },
223     #[help(help)]
224     Help { suggestion_ty: &'a str },
225 }
226
227 pub struct OverflowingInt<'a> {
228     pub ty: &'a str,
229     pub lit: String,
230     pub min: i128,
231     pub max: u128,
232     pub suggestion_ty: Option<&'a str>,
233 }
234
235 // FIXME: refactor with `Option<&'a str>` in macro
236 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> {
237     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
238         let mut diag = diag.build(fluent::lint_overflowing_int);
239         diag.set_arg("ty", self.ty);
240         diag.set_arg("lit", self.lit);
241         diag.set_arg("min", self.min);
242         diag.set_arg("max", self.max);
243         diag.note(fluent::note);
244         if let Some(suggestion_ty) = self.suggestion_ty {
245             diag.set_arg("suggestion_ty", suggestion_ty);
246             diag.help(fluent::help);
247         }
248         diag.emit();
249     }
250 }
251
252 #[derive(LintDiagnostic)]
253 #[diag(lint_only_cast_u8_to_char)]
254 pub struct OnlyCastu8ToChar {
255     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
256     pub span: Span,
257     pub literal: u128,
258 }
259
260 #[derive(LintDiagnostic)]
261 #[diag(lint_overflowing_uint)]
262 #[note]
263 pub struct OverflowingUInt<'a> {
264     pub ty: &'a str,
265     pub lit: String,
266     pub min: u128,
267     pub max: u128,
268 }
269
270 #[derive(LintDiagnostic)]
271 #[diag(lint_overflowing_literal)]
272 #[note]
273 pub struct OverflowingLiteral<'a> {
274     pub ty: &'a str,
275     pub lit: String,
276 }
277
278 #[derive(LintDiagnostic)]
279 #[diag(lint_unused_comparisons)]
280 pub struct UnusedComparisons;
281
282 #[derive(LintDiagnostic)]
283 #[diag(lint_variant_size_differences)]
284 pub struct VariantSizeDifferencesDiag {
285     pub largest: u64,
286 }
287
288 #[derive(LintDiagnostic)]
289 #[diag(lint_atomic_ordering_load)]
290 #[help]
291 pub struct AtomicOrderingLoad;
292
293 #[derive(LintDiagnostic)]
294 #[diag(lint_atomic_ordering_store)]
295 #[help]
296 pub struct AtomicOrderingStore;
297
298 #[derive(LintDiagnostic)]
299 #[diag(lint_atomic_ordering_fence)]
300 #[help]
301 pub struct AtomicOrderingFence;
302
303 #[derive(LintDiagnostic)]
304 #[diag(lint_atomic_ordering_invalid)]
305 #[help]
306 pub struct InvalidAtomicOrderingDiag {
307     pub method: Symbol,
308     #[label]
309     pub fail_order_arg_span: Span,
310 }
311
312 #[derive(LintDiagnostic)]
313 #[diag(lint_unused_op)]
314 pub struct UnusedOp<'a> {
315     pub op: &'a str,
316     #[label]
317     pub label: Span,
318     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
319     pub suggestion: Span,
320 }
321
322 #[derive(LintDiagnostic)]
323 #[diag(lint_unused_result)]
324 pub struct UnusedResult<'a> {
325     pub ty: Ty<'a>,
326 }
327
328 // FIXME(davidtwco): this isn't properly translatable becauses of the
329 // pre/post strings
330 #[derive(LintDiagnostic)]
331 #[diag(lint_unused_closure)]
332 #[note]
333 pub struct UnusedClosure<'a> {
334     pub count: usize,
335     pub pre: &'a str,
336     pub post: &'a str,
337 }
338
339 // FIXME(davidtwco): this isn't properly translatable becauses of the
340 // pre/post strings
341 #[derive(LintDiagnostic)]
342 #[diag(lint_unused_generator)]
343 #[note]
344 pub struct UnusedGenerator<'a> {
345     pub count: usize,
346     pub pre: &'a str,
347     pub post: &'a str,
348 }
349
350 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
351 // strings
352 pub struct UnusedDef<'a, 'b> {
353     pub pre: &'a str,
354     pub post: &'a str,
355     pub cx: &'a LateContext<'b>,
356     pub def_id: DefId,
357     pub note: Option<Symbol>,
358 }
359
360 // FIXME: refactor with `Option<String>` in macro
361 impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> {
362     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
363         let mut diag = diag.build(fluent::lint_unused_def);
364         diag.set_arg("pre", self.pre);
365         diag.set_arg("post", self.post);
366         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
367         // check for #[must_use = "..."]
368         if let Some(note) = self.note {
369             diag.note(note.as_str());
370         }
371         diag.emit();
372     }
373 }
374
375 #[derive(LintDiagnostic)]
376 #[diag(lint_path_statement_drop)]
377 pub struct PathStatementDrop {
378     #[subdiagnostic]
379     pub sub: PathStatementDropSub,
380 }
381
382 #[derive(SessionSubdiagnostic)]
383 pub enum PathStatementDropSub {
384     #[suggestion(
385         suggestion,
386         code = "drop({snippet});",
387         applicability = "machine-applicable"
388     )]
389     Suggestion {
390         #[primary_span]
391         span: Span,
392         snippet: String,
393     },
394     #[help(help)]
395     Help {
396         #[primary_span]
397         span: Span,
398     },
399 }
400
401 #[derive(LintDiagnostic)]
402 #[diag(lint_path_statement_no_effect)]
403 pub struct PathStatementNoEffect;
404
405 #[derive(LintDiagnostic)]
406 #[diag(lint_unused_delim)]
407 pub struct UnusedDelim<'a> {
408     pub delim: &'static str,
409     pub item: &'a str,
410     #[subdiagnostic]
411     pub suggestion: Option<UnusedDelimSuggestion>,
412 }
413
414 #[derive(Subdiagnostic)]
415 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
416 pub struct UnusedDelimSuggestion {
417     #[suggestion_part(code = "{start_replace}")]
418     pub start_span: Span,
419     pub start_replace: &'static str,
420     #[suggestion_part(code = "{end_replace}")]
421     pub end_span: Span,
422     pub end_replace: &'static str,
423 }
424
425 #[derive(LintDiagnostic)]
426 #[diag(lint_unused_import_braces)]
427 pub struct UnusedImportBracesDiag {
428     pub node: Symbol,
429 }
430
431 #[derive(LintDiagnostic)]
432 #[diag(lint_unused_allocation)]
433 pub struct UnusedAllocationDiag;
434
435 #[derive(LintDiagnostic)]
436 #[diag(lint_unused_allocation_mut)]
437 pub struct UnusedAllocationMutDiag;