]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
431ded9cd5f2d976bc5c31ef98b1b1f030e5a2f5
[rust.git] / compiler / rustc_lint / src / lints.rs
1 use rustc_errors::{fluent, AddToDiagnostic, Applicability, DecorateLint, EmissionGuarantee};
2 use rustc_hir::def_id::DefId;
3 use rustc_macros::{LintDiagnostic, Subdiagnostic};
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_array_into_iter)]
11 pub struct ArrayIntoIterDiag<'a> {
12     pub target: &'a str,
13     #[suggestion(use_iter_suggestion, code = "iter", applicability = "machine-applicable")]
14     pub suggestion: Span,
15     #[subdiagnostic]
16     pub sub: Option<ArrayIntoIterDiagSub>,
17 }
18
19 #[derive(Subdiagnostic)]
20 pub enum ArrayIntoIterDiagSub {
21     #[suggestion(remove_into_iter_suggestion, code = "", applicability = "maybe-incorrect")]
22     RemoveIntoIter {
23         #[primary_span]
24         span: Span,
25     },
26     #[multipart_suggestion(use_explicit_into_iter_suggestion, applicability = "maybe-incorrect")]
27     UseExplicitIntoIter {
28         #[suggestion_part(code = "IntoIterator::into_iter(")]
29         start_span: Span,
30         #[suggestion_part(code = ")")]
31         end_span: Span,
32     },
33 }
34
35 #[derive(LintDiagnostic)]
36 #[diag(lint_enum_intrinsics_mem_discriminant)]
37 pub struct EnumIntrinsicsMemDiscriminate<'a> {
38     pub ty_param: Ty<'a>,
39     #[note]
40     pub note: Span,
41 }
42
43 #[derive(LintDiagnostic)]
44 #[diag(lint_enum_intrinsics_mem_variant)]
45 #[note]
46 pub struct EnumIntrinsicsMemVariant<'a> {
47     pub ty_param: Ty<'a>,
48 }
49
50 #[derive(LintDiagnostic)]
51 #[diag(lint_cstring_ptr)]
52 #[note]
53 #[help]
54 pub struct CStringPtr {
55     #[label(as_ptr_label)]
56     pub as_ptr: Span,
57     #[label(unwrap_label)]
58     pub unwrap: Span,
59 }
60 #[derive(LintDiagnostic)]
61 #[diag(lint_identifier_non_ascii_char)]
62 pub struct IdentifierNonAsciiChar;
63
64 #[derive(LintDiagnostic)]
65 #[diag(lint_identifier_uncommon_codepoints)]
66 pub struct IdentifierUncommonCodepoints;
67
68 #[derive(LintDiagnostic)]
69 #[diag(lint_confusable_identifier_pair)]
70 pub struct ConfusableIdentifierPair {
71     pub existing_sym: Symbol,
72     pub sym: Symbol,
73     #[label]
74     pub label: Span,
75 }
76
77 #[derive(LintDiagnostic)]
78 #[diag(lint_mixed_script_confusables)]
79 #[note(includes_note)]
80 #[note]
81 pub struct MixedScriptConfusables {
82     pub set: String,
83     pub includes: String,
84 }
85
86 pub struct NonFmtPanicUnused {
87     pub count: usize,
88     pub suggestion: Option<Span>,
89 }
90
91 impl<G: EmissionGuarantee> DecorateLint<'_, G> for NonFmtPanicUnused {
92     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
93         let mut diag = diag.build(fluent::lint_non_fmt_panic_unused);
94         diag.set_arg("count", self.count);
95         diag.note(fluent::note);
96         if let Some(span) = self.suggestion {
97             diag.span_suggestion(
98                 span.shrink_to_hi(),
99                 fluent::add_args_suggestion,
100                 ", ...",
101                 Applicability::HasPlaceholders,
102             );
103             diag.span_suggestion(
104                 span.shrink_to_lo(),
105                 fluent::add_fmt_suggestion,
106                 "\"{}\", ",
107                 Applicability::MachineApplicable,
108             );
109         }
110         diag.emit();
111     }
112 }
113
114 #[derive(LintDiagnostic)]
115 #[diag(lint_non_fmt_panic_braces)]
116 #[note]
117 pub struct NonFmtPanicBraces {
118     pub count: usize,
119     #[suggestion(code = "\"{{}}\", ", applicability = "machine-applicable")]
120     pub suggestion: Option<Span>,
121 }
122
123 #[derive(LintDiagnostic)]
124 #[diag(lint_non_camel_case_type)]
125 pub struct NonCamelCaseType<'a> {
126     pub sort: &'a str,
127     pub name: &'a str,
128     #[subdiagnostic]
129     pub sub: NonCamelCaseTypeSub,
130 }
131
132 #[derive(Subdiagnostic)]
133 pub enum NonCamelCaseTypeSub {
134     #[label(label)]
135     Label {
136         #[primary_span]
137         span: Span,
138     },
139     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
140     Suggestion {
141         #[primary_span]
142         span: Span,
143         replace: String,
144     },
145 }
146
147 #[derive(LintDiagnostic)]
148 #[diag(lint_non_snake_case)]
149 pub struct NonSnakeCaseDiag<'a> {
150     pub sort: &'a str,
151     pub name: &'a str,
152     pub sc: String,
153     #[subdiagnostic]
154     pub sub: NonSnakeCaseDiagSub,
155 }
156
157 pub enum NonSnakeCaseDiagSub {
158     Label { span: Span },
159     Help,
160     RenameOrConvertSuggestion { span: Span, suggestion: Ident },
161     ConvertSuggestion { span: Span, suggestion: String },
162     SuggestionAndNote { span: Span },
163 }
164
165 impl AddToDiagnostic for NonSnakeCaseDiagSub {
166     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
167     where
168         F: Fn(
169             &mut rustc_errors::Diagnostic,
170             rustc_errors::SubdiagnosticMessage,
171         ) -> rustc_errors::SubdiagnosticMessage,
172     {
173         match self {
174             NonSnakeCaseDiagSub::Label { span } => {
175                 diag.span_label(span, fluent::label);
176             }
177             NonSnakeCaseDiagSub::Help => {
178                 diag.help(fluent::help);
179             }
180             NonSnakeCaseDiagSub::ConvertSuggestion { span, suggestion } => {
181                 diag.span_suggestion(
182                     span,
183                     fluent::convert_suggestion,
184                     suggestion,
185                     Applicability::MaybeIncorrect,
186                 );
187             }
188             NonSnakeCaseDiagSub::RenameOrConvertSuggestion { span, suggestion } => {
189                 diag.span_suggestion(
190                     span,
191                     fluent::rename_or_convert_suggestion,
192                     suggestion,
193                     Applicability::MaybeIncorrect,
194                 );
195             }
196             NonSnakeCaseDiagSub::SuggestionAndNote { span } => {
197                 diag.note(fluent::cannot_convert_note);
198                 diag.span_suggestion(
199                     span,
200                     fluent::rename_suggestion,
201                     "",
202                     Applicability::MaybeIncorrect,
203                 );
204             }
205         };
206     }
207 }
208
209 #[derive(LintDiagnostic)]
210 #[diag(lint_non_upper_case_global)]
211 pub struct NonUpperCaseGlobal<'a> {
212     pub sort: &'a str,
213     pub name: &'a str,
214     #[subdiagnostic]
215     pub sub: NonUpperCaseGlobalSub,
216 }
217
218 #[derive(Subdiagnostic)]
219 pub enum NonUpperCaseGlobalSub {
220     #[label(label)]
221     Label {
222         #[primary_span]
223         span: Span,
224     },
225     #[suggestion(suggestion, code = "{replace}", applicability = "maybe-incorrect")]
226     Suggestion {
227         #[primary_span]
228         span: Span,
229         replace: String,
230     },
231 }
232
233 #[derive(LintDiagnostic)]
234 #[diag(lint_noop_method_call)]
235 #[note]
236 pub struct NoopMethodCallDiag<'a> {
237     pub method: Symbol,
238     pub receiver_ty: Ty<'a>,
239     #[label]
240     pub label: Span,
241 }
242
243 #[derive(LintDiagnostic)]
244 #[diag(lint_pass_by_value)]
245 pub struct PassByValueDiag {
246     pub ty: String,
247     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
248     pub suggestion: Span,
249 }
250
251 #[derive(LintDiagnostic)]
252 #[diag(lint_redundant_semicolons)]
253 pub struct RedundantSemicolonsDiag {
254     pub multiple: bool,
255     #[suggestion(code = "", applicability = "maybe-incorrect")]
256     pub suggestion: Span,
257 }
258
259 pub struct DropTraitConstraintsDiag<'a> {
260     pub predicate: Predicate<'a>,
261     pub tcx: TyCtxt<'a>,
262     pub def_id: DefId,
263 }
264
265 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropTraitConstraintsDiag<'a> {
266     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
267         let mut diag = diag.build(fluent::lint_drop_trait_constraints);
268         diag.set_arg("predicate", self.predicate);
269         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
270         diag.emit();
271     }
272 }
273
274 pub struct DropGlue<'a> {
275     pub tcx: TyCtxt<'a>,
276     pub def_id: DefId,
277 }
278
279 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropGlue<'a> {
280     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
281         let mut diag = diag.build(fluent::lint_drop_glue);
282         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
283         diag.emit();
284     }
285 }
286
287 #[derive(LintDiagnostic)]
288 #[diag(lint_range_endpoint_out_of_range)]
289 pub struct RangeEndpointOutOfRange<'a> {
290     pub ty: &'a str,
291     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
292     pub suggestion: Span,
293     pub start: String,
294     pub literal: u128,
295     pub suffix: &'a str,
296 }
297
298 #[derive(LintDiagnostic)]
299 #[diag(lint_overflowing_bin_hex)]
300 pub struct OverflowingBinHex<'a> {
301     pub ty: &'a str,
302     pub lit: String,
303     pub dec: u128,
304     pub actually: String,
305     #[subdiagnostic]
306     pub sign: OverflowingBinHexSign,
307     #[subdiagnostic]
308     pub sub: Option<OverflowingBinHexSub<'a>>,
309 }
310
311 pub enum OverflowingBinHexSign {
312     Positive,
313     Negative,
314 }
315
316 impl AddToDiagnostic for OverflowingBinHexSign {
317     fn add_to_diagnostic_with<F>(self, diag: &mut rustc_errors::Diagnostic, _: F)
318     where
319         F: Fn(
320             &mut rustc_errors::Diagnostic,
321             rustc_errors::SubdiagnosticMessage,
322         ) -> rustc_errors::SubdiagnosticMessage,
323     {
324         match self {
325             OverflowingBinHexSign::Positive => {
326                 diag.note(fluent::positive_note);
327             }
328             OverflowingBinHexSign::Negative => {
329                 diag.note(fluent::negative_note);
330                 diag.note(fluent::negative_becomes_note);
331             }
332         }
333     }
334 }
335
336 #[derive(Subdiagnostic)]
337 pub enum OverflowingBinHexSub<'a> {
338     #[suggestion(
339         suggestion,
340         code = "{sans_suffix}{suggestion_ty}",
341         applicability = "machine-applicable"
342     )]
343     Suggestion {
344         #[primary_span]
345         span: Span,
346         suggestion_ty: &'a str,
347         sans_suffix: &'a str,
348     },
349     #[help(help)]
350     Help { suggestion_ty: &'a str },
351 }
352
353 pub struct OverflowingInt<'a> {
354     pub ty: &'a str,
355     pub lit: String,
356     pub min: i128,
357     pub max: u128,
358     pub suggestion_ty: Option<&'a str>,
359 }
360
361 // FIXME: refactor with `Option<&'a str>` in macro
362 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> {
363     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
364         let mut diag = diag.build(fluent::lint_overflowing_int);
365         diag.set_arg("ty", self.ty);
366         diag.set_arg("lit", self.lit);
367         diag.set_arg("min", self.min);
368         diag.set_arg("max", self.max);
369         diag.note(fluent::note);
370         if let Some(suggestion_ty) = self.suggestion_ty {
371             diag.set_arg("suggestion_ty", suggestion_ty);
372             diag.help(fluent::help);
373         }
374         diag.emit();
375     }
376 }
377
378 #[derive(LintDiagnostic)]
379 #[diag(lint_only_cast_u8_to_char)]
380 pub struct OnlyCastu8ToChar {
381     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
382     pub span: Span,
383     pub literal: u128,
384 }
385
386 #[derive(LintDiagnostic)]
387 #[diag(lint_overflowing_uint)]
388 #[note]
389 pub struct OverflowingUInt<'a> {
390     pub ty: &'a str,
391     pub lit: String,
392     pub min: u128,
393     pub max: u128,
394 }
395
396 #[derive(LintDiagnostic)]
397 #[diag(lint_overflowing_literal)]
398 #[note]
399 pub struct OverflowingLiteral<'a> {
400     pub ty: &'a str,
401     pub lit: String,
402 }
403
404 #[derive(LintDiagnostic)]
405 #[diag(lint_unused_comparisons)]
406 pub struct UnusedComparisons;
407
408 #[derive(LintDiagnostic)]
409 #[diag(lint_variant_size_differences)]
410 pub struct VariantSizeDifferencesDiag {
411     pub largest: u64,
412 }
413
414 #[derive(LintDiagnostic)]
415 #[diag(lint_atomic_ordering_load)]
416 #[help]
417 pub struct AtomicOrderingLoad;
418
419 #[derive(LintDiagnostic)]
420 #[diag(lint_atomic_ordering_store)]
421 #[help]
422 pub struct AtomicOrderingStore;
423
424 #[derive(LintDiagnostic)]
425 #[diag(lint_atomic_ordering_fence)]
426 #[help]
427 pub struct AtomicOrderingFence;
428
429 #[derive(LintDiagnostic)]
430 #[diag(lint_atomic_ordering_invalid)]
431 #[help]
432 pub struct InvalidAtomicOrderingDiag {
433     pub method: Symbol,
434     #[label]
435     pub fail_order_arg_span: Span,
436 }
437
438 #[derive(LintDiagnostic)]
439 #[diag(lint_unused_op)]
440 pub struct UnusedOp<'a> {
441     pub op: &'a str,
442     #[label]
443     pub label: Span,
444     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
445     pub suggestion: Span,
446 }
447
448 #[derive(LintDiagnostic)]
449 #[diag(lint_unused_result)]
450 pub struct UnusedResult<'a> {
451     pub ty: Ty<'a>,
452 }
453
454 // FIXME(davidtwco): this isn't properly translatable becauses of the
455 // pre/post strings
456 #[derive(LintDiagnostic)]
457 #[diag(lint_unused_closure)]
458 #[note]
459 pub struct UnusedClosure<'a> {
460     pub count: usize,
461     pub pre: &'a str,
462     pub post: &'a str,
463 }
464
465 // FIXME(davidtwco): this isn't properly translatable becauses of the
466 // pre/post strings
467 #[derive(LintDiagnostic)]
468 #[diag(lint_unused_generator)]
469 #[note]
470 pub struct UnusedGenerator<'a> {
471     pub count: usize,
472     pub pre: &'a str,
473     pub post: &'a str,
474 }
475
476 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
477 // strings
478 pub struct UnusedDef<'a, 'b> {
479     pub pre: &'a str,
480     pub post: &'a str,
481     pub cx: &'a LateContext<'b>,
482     pub def_id: DefId,
483     pub note: Option<Symbol>,
484 }
485
486 // FIXME: refactor with `Option<String>` in macro
487 impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> {
488     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
489         let mut diag = diag.build(fluent::lint_unused_def);
490         diag.set_arg("pre", self.pre);
491         diag.set_arg("post", self.post);
492         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
493         // check for #[must_use = "..."]
494         if let Some(note) = self.note {
495             diag.note(note.as_str());
496         }
497         diag.emit();
498     }
499 }
500
501 #[derive(LintDiagnostic)]
502 #[diag(lint_path_statement_drop)]
503 pub struct PathStatementDrop {
504     #[subdiagnostic]
505     pub sub: PathStatementDropSub,
506 }
507
508 #[derive(Subdiagnostic)]
509 pub enum PathStatementDropSub {
510     #[suggestion(suggestion, code = "drop({snippet});", applicability = "machine-applicable")]
511     Suggestion {
512         #[primary_span]
513         span: Span,
514         snippet: String,
515     },
516     #[help(help)]
517     Help {
518         #[primary_span]
519         span: Span,
520     },
521 }
522
523 #[derive(LintDiagnostic)]
524 #[diag(lint_path_statement_no_effect)]
525 pub struct PathStatementNoEffect;
526
527 #[derive(LintDiagnostic)]
528 #[diag(lint_unused_delim)]
529 pub struct UnusedDelim<'a> {
530     pub delim: &'static str,
531     pub item: &'a str,
532     #[subdiagnostic]
533     pub suggestion: Option<UnusedDelimSuggestion>,
534 }
535
536 #[derive(Subdiagnostic)]
537 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
538 pub struct UnusedDelimSuggestion {
539     #[suggestion_part(code = "{start_replace}")]
540     pub start_span: Span,
541     pub start_replace: &'static str,
542     #[suggestion_part(code = "{end_replace}")]
543     pub end_span: Span,
544     pub end_replace: &'static str,
545 }
546
547 #[derive(LintDiagnostic)]
548 #[diag(lint_unused_import_braces)]
549 pub struct UnusedImportBracesDiag {
550     pub node: Symbol,
551 }
552
553 #[derive(LintDiagnostic)]
554 #[diag(lint_unused_allocation)]
555 pub struct UnusedAllocationDiag;
556
557 #[derive(LintDiagnostic)]
558 #[diag(lint_unused_allocation_mut)]
559 pub struct UnusedAllocationMutDiag;