]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_lint/src/lints.rs
83d8dce154082d87593b4e1233df46a03985f0ee
[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::{Span, Symbol};
6
7 use crate::LateContext;
8
9 #[derive(LintDiagnostic)]
10 #[diag(lint_noop_method_call)]
11 #[note]
12 pub struct NoopMethodCallDiag<'a> {
13     pub method: Symbol,
14     pub receiver_ty: Ty<'a>,
15     #[label]
16     pub label: Span,
17 }
18
19 #[derive(LintDiagnostic)]
20 #[diag(lint_pass_by_value)]
21 pub struct PassByValueDiag {
22     pub ty: String,
23     #[suggestion(code = "{ty}", applicability = "maybe-incorrect")]
24     pub suggestion: Span,
25 }
26
27 #[derive(LintDiagnostic)]
28 #[diag(lint_redundant_semicolons)]
29 pub struct RedundantSemicolonsDiag {
30     pub multiple: bool,
31     #[suggestion(code = "", applicability = "maybe-incorrect")]
32     pub suggestion: Span,
33 }
34
35 pub struct DropTraitConstraintsDiag<'a> {
36     pub predicate: Predicate<'a>,
37     pub tcx: TyCtxt<'a>,
38     pub def_id: DefId,
39 }
40
41 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropTraitConstraintsDiag<'a> {
42     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
43         let mut diag = diag.build(fluent::lint_drop_trait_constraints);
44         diag.set_arg("predicate", self.predicate);
45         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
46         diag.emit();
47     }
48 }
49
50 pub struct DropGlue<'a> {
51     pub tcx: TyCtxt<'a>,
52     pub def_id: DefId,
53 }
54
55 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for DropGlue<'a> {
56     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
57         let mut diag = diag.build(fluent::lint_drop_glue);
58         diag.set_arg("needs_drop", self.tcx.def_path_str(self.def_id));
59         diag.emit();
60     }
61 }
62
63 #[derive(LintDiagnostic)]
64 #[diag(lint_range_endpoint_out_of_range)]
65 pub struct RangeEndpointOutOfRange<'a> {
66     pub ty: &'a str,
67     #[suggestion(code = "{start}..={literal}{suffix}", applicability = "machine-applicable")]
68     pub suggestion: Span,
69     pub start: String,
70     pub literal: u128,
71     pub suffix: &'a str,
72 }
73
74 #[derive(LintDiagnostic)]
75 #[diag(lint_overflowing_bin_hex)]
76 pub struct OverflowingBinHex<'a> {
77     pub ty: &'a str,
78     pub lit: String,
79     pub dec: u128,
80     pub actually: String,
81     #[subdiagnostic]
82     pub sign: OverflowingBinHexSign,
83     #[subdiagnostic]
84     pub sub: Option<OverflowingBinHexSub<'a>>,
85 }
86
87 pub enum OverflowingBinHexSign {
88     Positive,
89     Negative,
90 }
91
92 impl AddSubdiagnostic for OverflowingBinHexSign {
93     fn add_to_diagnostic(self, diag: &mut rustc_errors::Diagnostic) {
94         match self {
95             OverflowingBinHexSign::Positive => {
96                 diag.note(fluent::positive_note);
97             }
98             OverflowingBinHexSign::Negative => {
99                 diag.note(fluent::negative_note);
100                 diag.note(fluent::negative_becomes_note);
101             }
102         }
103     }
104 }
105
106 #[derive(SessionSubdiagnostic)]
107 pub enum OverflowingBinHexSub<'a> {
108     #[suggestion(
109         suggestion,
110         code = "{sans_suffix}{suggestion_ty}",
111         applicability = "machine-applicable"
112     )]
113     Suggestion {
114         #[primary_span]
115         span: Span,
116         suggestion_ty: &'a str,
117         sans_suffix: &'a str,
118     },
119     #[help(help)]
120     Help { suggestion_ty: &'a str },
121 }
122
123 pub struct OverflowingInt<'a> {
124     pub ty: &'a str,
125     pub lit: String,
126     pub min: i128,
127     pub max: u128,
128     pub suggestion_ty: Option<&'a str>,
129 }
130
131 // FIXME: refactor with `Option<&'a str>` in macro
132 impl<'a, G: EmissionGuarantee> DecorateLint<'_, G> for OverflowingInt<'a> {
133     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
134         let mut diag = diag.build(fluent::lint_overflowing_int);
135         diag.set_arg("ty", self.ty);
136         diag.set_arg("lit", self.lit);
137         diag.set_arg("min", self.min);
138         diag.set_arg("max", self.max);
139         diag.note(fluent::note);
140         if let Some(suggestion_ty) = self.suggestion_ty {
141             diag.set_arg("suggestion_ty", suggestion_ty);
142             diag.help(fluent::help);
143         }
144         diag.emit();
145     }
146 }
147
148 #[derive(LintDiagnostic)]
149 #[diag(lint_only_cast_u8_to_char)]
150 pub struct OnlyCastu8ToChar {
151     #[suggestion(code = "'\\u{{{literal:X}}}'", applicability = "machine-applicable")]
152     pub span: Span,
153     pub literal: u128,
154 }
155
156 #[derive(LintDiagnostic)]
157 #[diag(lint_overflowing_uint)]
158 #[note]
159 pub struct OverflowingUInt<'a> {
160     pub ty: &'a str,
161     pub lit: String,
162     pub min: u128,
163     pub max: u128,
164 }
165
166 #[derive(LintDiagnostic)]
167 #[diag(lint_overflowing_literal)]
168 #[note]
169 pub struct OverflowingLiteral<'a> {
170     pub ty: &'a str,
171     pub lit: String,
172 }
173
174 #[derive(LintDiagnostic)]
175 #[diag(lint_unused_comparisons)]
176 pub struct UnusedComparisons;
177
178 #[derive(LintDiagnostic)]
179 #[diag(lint_variant_size_differences)]
180 pub struct VariantSizeDifferencesDiag {
181     pub largest: u64,
182 }
183
184 #[derive(LintDiagnostic)]
185 #[diag(lint_atomic_ordering_load)]
186 #[help]
187 pub struct AtomicOrderingLoad;
188
189 #[derive(LintDiagnostic)]
190 #[diag(lint_atomic_ordering_store)]
191 #[help]
192 pub struct AtomicOrderingStore;
193
194 #[derive(LintDiagnostic)]
195 #[diag(lint_atomic_ordering_fence)]
196 #[help]
197 pub struct AtomicOrderingFence;
198
199 #[derive(LintDiagnostic)]
200 #[diag(lint_atomic_ordering_invalid)]
201 #[help]
202 pub struct InvalidAtomicOrderingDiag {
203     pub method: Symbol,
204     #[label]
205     pub fail_order_arg_span: Span,
206 }
207
208 #[derive(LintDiagnostic)]
209 #[diag(lint_unused_op)]
210 pub struct UnusedOp<'a> {
211     pub op: &'a str,
212     #[label]
213     pub label: Span,
214     #[suggestion(style = "verbose", code = "let _ = ", applicability = "machine-applicable")]
215     pub suggestion: Span,
216 }
217
218 #[derive(LintDiagnostic)]
219 #[diag(lint_unused_result)]
220 pub struct UnusedResult<'a> {
221     pub ty: Ty<'a>,
222 }
223
224 // FIXME(davidtwco): this isn't properly translatable becauses of the
225 // pre/post strings
226 #[derive(LintDiagnostic)]
227 #[diag(lint_unused_closure)]
228 #[note]
229 pub struct UnusedClosure<'a> {
230     pub count: usize,
231     pub pre: &'a str,
232     pub post: &'a str,
233 }
234
235 // FIXME(davidtwco): this isn't properly translatable becauses of the
236 // pre/post strings
237 #[derive(LintDiagnostic)]
238 #[diag(lint_unused_generator)]
239 #[note]
240 pub struct UnusedGenerator<'a> {
241     pub count: usize,
242     pub pre: &'a str,
243     pub post: &'a str,
244 }
245
246 // FIXME(davidtwco): this isn't properly translatable becauses of the pre/post
247 // strings
248 pub struct UnusedDef<'a, 'b> {
249     pub pre: &'a str,
250     pub post: &'a str,
251     pub cx: &'a LateContext<'b>,
252     pub def_id: DefId,
253     pub note: Option<Symbol>,
254 }
255
256 // FIXME: refactor with `Option<String>` in macro
257 impl<'a, 'b, G: EmissionGuarantee> DecorateLint<'_, G> for UnusedDef<'a, 'b> {
258     fn decorate_lint(self, diag: rustc_errors::LintDiagnosticBuilder<'_, G>) {
259         let mut diag = diag.build(fluent::lint_unused_def);
260         diag.set_arg("pre", self.pre);
261         diag.set_arg("post", self.post);
262         diag.set_arg("def", self.cx.tcx.def_path_str(self.def_id));
263         // check for #[must_use = "..."]
264         if let Some(note) = self.note {
265             diag.note(note.as_str());
266         }
267         diag.emit();
268     }
269 }
270
271 #[derive(LintDiagnostic)]
272 #[diag(lint_path_statement_drop)]
273 pub struct PathStatementDrop {
274     #[subdiagnostic]
275     pub sub: PathStatementDropSub,
276 }
277
278 #[derive(SessionSubdiagnostic)]
279 pub enum PathStatementDropSub {
280     #[suggestion(
281         suggestion,
282         code = "drop({snippet});",
283         applicability = "machine-applicable"
284     )]
285     Suggestion {
286         #[primary_span]
287         span: Span,
288         snippet: String,
289     },
290     #[help(help)]
291     Help {
292         #[primary_span]
293         span: Span,
294     },
295 }
296
297 #[derive(LintDiagnostic)]
298 #[diag(lint_path_statement_no_effect)]
299 pub struct PathStatementNoEffect;
300
301 #[derive(LintDiagnostic)]
302 #[diag(lint_unused_delim)]
303 pub struct UnusedDelim<'a> {
304     pub delim: &'static str,
305     pub item: &'a str,
306     #[subdiagnostic]
307     pub suggestion: Option<UnusedDelimSuggestion>,
308 }
309
310 #[derive(Subdiagnostic)]
311 #[multipart_suggestion(suggestion, applicability = "machine-applicable")]
312 pub struct UnusedDelimSuggestion {
313     #[suggestion_part(code = "{start_replace}")]
314     pub start_span: Span,
315     pub start_replace: &'static str,
316     #[suggestion_part(code = "{end_replace}")]
317     pub end_span: Span,
318     pub end_replace: &'static str,
319 }
320
321 #[derive(LintDiagnostic)]
322 #[diag(lint_unused_import_braces)]
323 pub struct UnusedImportBracesDiag {
324     pub node: Symbol,
325 }
326
327 #[derive(LintDiagnostic)]
328 #[diag(lint_unused_allocation)]
329 pub struct UnusedAllocationDiag;
330
331 #[derive(LintDiagnostic)]
332 #[diag(lint_unused_allocation_mut)]
333 pub struct UnusedAllocationMutDiag;