rustc_attr_parsing/
session_diagnostics.rs

1use std::num::IntErrorKind;
2
3use rustc_ast as ast;
4use rustc_errors::codes::*;
5use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level};
6use rustc_macros::{Diagnostic, Subdiagnostic};
7use rustc_span::{Span, Symbol};
8
9use crate::fluent_generated as fluent;
10
11pub(crate) enum UnsupportedLiteralReason {
12    Generic,
13    CfgString,
14    CfgBoolean,
15    DeprecatedString,
16    DeprecatedKvPair,
17}
18
19#[derive(Diagnostic)]
20#[diag(attr_parsing_expected_one_cfg_pattern, code = E0536)]
21pub(crate) struct ExpectedOneCfgPattern {
22    #[primary_span]
23    pub span: Span,
24}
25
26#[derive(Diagnostic)]
27#[diag(attr_parsing_invalid_predicate, code = E0537)]
28pub(crate) struct InvalidPredicate {
29    #[primary_span]
30    pub span: Span,
31
32    pub predicate: String,
33}
34
35#[derive(Diagnostic)]
36#[diag(attr_parsing_multiple_item, code = E0538)]
37pub(crate) struct MultipleItem {
38    #[primary_span]
39    pub span: Span,
40
41    pub item: String,
42}
43
44#[derive(Diagnostic)]
45#[diag(attr_parsing_incorrect_meta_item, code = E0539)]
46pub(crate) struct IncorrectMetaItem {
47    #[primary_span]
48    pub span: Span,
49
50    #[subdiagnostic]
51    pub suggestion: Option<IncorrectMetaItemSuggestion>,
52}
53
54#[derive(Subdiagnostic)]
55#[multipart_suggestion(
56    attr_parsing_incorrect_meta_item_suggestion,
57    applicability = "maybe-incorrect"
58)]
59pub(crate) struct IncorrectMetaItemSuggestion {
60    #[suggestion_part(code = "\"")]
61    pub lo: Span,
62    #[suggestion_part(code = "\"")]
63    pub hi: Span,
64}
65
66/// Error code: E0541
67pub(crate) struct UnknownMetaItem<'a> {
68    pub span: Span,
69    pub item: String,
70    pub expected: &'a [&'a str],
71}
72
73// Manual implementation to be able to format `expected` items correctly.
74impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnknownMetaItem<'_> {
75    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
76        let expected = self.expected.iter().map(|name| format!("`{name}`")).collect::<Vec<_>>();
77        Diag::new(dcx, level, fluent::attr_parsing_unknown_meta_item)
78            .with_span(self.span)
79            .with_code(E0541)
80            .with_arg("item", self.item)
81            .with_arg("expected", expected.join(", "))
82            .with_span_label(self.span, fluent::attr_parsing_label)
83    }
84}
85
86#[derive(Diagnostic)]
87#[diag(attr_parsing_missing_since, code = E0542)]
88pub(crate) struct MissingSince {
89    #[primary_span]
90    pub span: Span,
91}
92
93#[derive(Diagnostic)]
94#[diag(attr_parsing_missing_note, code = E0543)]
95pub(crate) struct MissingNote {
96    #[primary_span]
97    pub span: Span,
98}
99
100#[derive(Diagnostic)]
101#[diag(attr_parsing_multiple_stability_levels, code = E0544)]
102pub(crate) struct MultipleStabilityLevels {
103    #[primary_span]
104    pub span: Span,
105}
106
107#[derive(Diagnostic)]
108#[diag(attr_parsing_invalid_issue_string, code = E0545)]
109pub(crate) struct InvalidIssueString {
110    #[primary_span]
111    pub span: Span,
112
113    #[subdiagnostic]
114    pub cause: Option<InvalidIssueStringCause>,
115}
116
117// The error kinds of `IntErrorKind` are duplicated here in order to allow the messages to be
118// translatable.
119#[derive(Subdiagnostic)]
120pub(crate) enum InvalidIssueStringCause {
121    #[label(attr_parsing_must_not_be_zero)]
122    MustNotBeZero {
123        #[primary_span]
124        span: Span,
125    },
126
127    #[label(attr_parsing_empty)]
128    Empty {
129        #[primary_span]
130        span: Span,
131    },
132
133    #[label(attr_parsing_invalid_digit)]
134    InvalidDigit {
135        #[primary_span]
136        span: Span,
137    },
138
139    #[label(attr_parsing_pos_overflow)]
140    PosOverflow {
141        #[primary_span]
142        span: Span,
143    },
144
145    #[label(attr_parsing_neg_overflow)]
146    NegOverflow {
147        #[primary_span]
148        span: Span,
149    },
150}
151
152impl InvalidIssueStringCause {
153    pub(crate) fn from_int_error_kind(span: Span, kind: &IntErrorKind) -> Option<Self> {
154        match kind {
155            IntErrorKind::Empty => Some(Self::Empty { span }),
156            IntErrorKind::InvalidDigit => Some(Self::InvalidDigit { span }),
157            IntErrorKind::PosOverflow => Some(Self::PosOverflow { span }),
158            IntErrorKind::NegOverflow => Some(Self::NegOverflow { span }),
159            IntErrorKind::Zero => Some(Self::MustNotBeZero { span }),
160            _ => None,
161        }
162    }
163}
164
165#[derive(Diagnostic)]
166#[diag(attr_parsing_missing_feature, code = E0546)]
167pub(crate) struct MissingFeature {
168    #[primary_span]
169    pub span: Span,
170}
171
172#[derive(Diagnostic)]
173#[diag(attr_parsing_non_ident_feature, code = E0546)]
174pub(crate) struct NonIdentFeature {
175    #[primary_span]
176    pub span: Span,
177}
178
179#[derive(Diagnostic)]
180#[diag(attr_parsing_missing_issue, code = E0547)]
181pub(crate) struct MissingIssue {
182    #[primary_span]
183    pub span: Span,
184}
185
186// FIXME: Why is this the same error code as `InvalidReprHintNoParen` and `InvalidReprHintNoValue`?
187// It is more similar to `IncorrectReprFormatGeneric`.
188#[derive(Diagnostic)]
189#[diag(attr_parsing_incorrect_repr_format_packed_one_or_zero_arg, code = E0552)]
190pub(crate) struct IncorrectReprFormatPackedOneOrZeroArg {
191    #[primary_span]
192    pub span: Span,
193}
194#[derive(Diagnostic)]
195#[diag(attr_parsing_incorrect_repr_format_packed_expect_integer, code = E0552)]
196pub(crate) struct IncorrectReprFormatPackedExpectInteger {
197    #[primary_span]
198    pub span: Span,
199}
200
201#[derive(Diagnostic)]
202#[diag(attr_parsing_invalid_repr_hint_no_paren, code = E0552)]
203pub(crate) struct InvalidReprHintNoParen {
204    #[primary_span]
205    pub span: Span,
206
207    pub name: String,
208}
209
210#[derive(Diagnostic)]
211#[diag(attr_parsing_invalid_repr_hint_no_value, code = E0552)]
212pub(crate) struct InvalidReprHintNoValue {
213    #[primary_span]
214    pub span: Span,
215
216    pub name: String,
217}
218
219/// Error code: E0565
220pub(crate) struct UnsupportedLiteral {
221    pub span: Span,
222    pub reason: UnsupportedLiteralReason,
223    pub is_bytestr: bool,
224    pub start_point_span: Span,
225}
226
227impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for UnsupportedLiteral {
228    fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
229        let mut diag = Diag::new(
230            dcx,
231            level,
232            match self.reason {
233                UnsupportedLiteralReason::Generic => {
234                    fluent::attr_parsing_unsupported_literal_generic
235                }
236                UnsupportedLiteralReason::CfgString => {
237                    fluent::attr_parsing_unsupported_literal_cfg_string
238                }
239                UnsupportedLiteralReason::CfgBoolean => {
240                    fluent::attr_parsing_unsupported_literal_cfg_boolean
241                }
242                UnsupportedLiteralReason::DeprecatedString => {
243                    fluent::attr_parsing_unsupported_literal_deprecated_string
244                }
245                UnsupportedLiteralReason::DeprecatedKvPair => {
246                    fluent::attr_parsing_unsupported_literal_deprecated_kv_pair
247                }
248            },
249        );
250        diag.span(self.span);
251        diag.code(E0565);
252        if self.is_bytestr {
253            diag.span_suggestion(
254                self.start_point_span,
255                fluent::attr_parsing_unsupported_literal_suggestion,
256                "",
257                Applicability::MaybeIncorrect,
258            );
259        }
260        diag
261    }
262}
263
264#[derive(Diagnostic)]
265#[diag(attr_parsing_invalid_repr_align_need_arg, code = E0589)]
266pub(crate) struct InvalidReprAlignNeedArg {
267    #[primary_span]
268    #[suggestion(code = "align(...)", applicability = "has-placeholders")]
269    pub span: Span,
270}
271
272#[derive(Diagnostic)]
273#[diag(attr_parsing_invalid_repr_generic, code = E0589)]
274pub(crate) struct InvalidReprGeneric<'a> {
275    #[primary_span]
276    pub span: Span,
277
278    pub repr_arg: String,
279    pub error_part: &'a str,
280}
281
282#[derive(Diagnostic)]
283#[diag(attr_parsing_incorrect_repr_format_align_one_arg, code = E0693)]
284pub(crate) struct IncorrectReprFormatAlignOneArg {
285    #[primary_span]
286    pub span: Span,
287}
288
289#[derive(Diagnostic)]
290#[diag(attr_parsing_incorrect_repr_format_expect_literal_integer, code = E0693)]
291pub(crate) struct IncorrectReprFormatExpectInteger {
292    #[primary_span]
293    pub span: Span,
294}
295
296#[derive(Diagnostic)]
297#[diag(attr_parsing_incorrect_repr_format_generic, code = E0693)]
298pub(crate) struct IncorrectReprFormatGeneric<'a> {
299    #[primary_span]
300    pub span: Span,
301
302    pub repr_arg: &'a str,
303
304    #[subdiagnostic]
305    pub cause: Option<IncorrectReprFormatGenericCause<'a>>,
306}
307
308#[derive(Subdiagnostic)]
309pub(crate) enum IncorrectReprFormatGenericCause<'a> {
310    #[suggestion(
311        attr_parsing_suggestion,
312        code = "{name}({int})",
313        applicability = "machine-applicable"
314    )]
315    Int {
316        #[primary_span]
317        span: Span,
318
319        #[skip_arg]
320        name: &'a str,
321
322        #[skip_arg]
323        int: u128,
324    },
325
326    #[suggestion(
327        attr_parsing_suggestion,
328        code = "{name}({symbol})",
329        applicability = "machine-applicable"
330    )]
331    Symbol {
332        #[primary_span]
333        span: Span,
334
335        #[skip_arg]
336        name: &'a str,
337
338        #[skip_arg]
339        symbol: Symbol,
340    },
341}
342
343impl<'a> IncorrectReprFormatGenericCause<'a> {
344    pub(crate) fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option<Self> {
345        match kind {
346            ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
347                Some(Self::Int { span, name, int: int.get() })
348            }
349            ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
350            _ => None,
351        }
352    }
353}
354
355#[derive(Diagnostic)]
356#[diag(attr_parsing_rustc_promotable_pairing, code = E0717)]
357pub(crate) struct RustcPromotablePairing {
358    #[primary_span]
359    pub span: Span,
360}
361
362#[derive(Diagnostic)]
363#[diag(attr_parsing_rustc_allowed_unstable_pairing, code = E0789)]
364pub(crate) struct RustcAllowedUnstablePairing {
365    #[primary_span]
366    pub span: Span,
367}
368
369#[derive(Diagnostic)]
370#[diag(attr_parsing_cfg_predicate_identifier)]
371pub(crate) struct CfgPredicateIdentifier {
372    #[primary_span]
373    pub span: Span,
374}
375
376#[derive(Diagnostic)]
377#[diag(attr_parsing_deprecated_item_suggestion)]
378pub(crate) struct DeprecatedItemSuggestion {
379    #[primary_span]
380    pub span: Span,
381
382    #[help]
383    pub is_nightly: bool,
384
385    #[note]
386    pub details: (),
387}
388
389#[derive(Diagnostic)]
390#[diag(attr_parsing_expected_single_version_literal)]
391pub(crate) struct ExpectedSingleVersionLiteral {
392    #[primary_span]
393    pub span: Span,
394}
395
396#[derive(Diagnostic)]
397#[diag(attr_parsing_expected_version_literal)]
398pub(crate) struct ExpectedVersionLiteral {
399    #[primary_span]
400    pub span: Span,
401}
402
403#[derive(Diagnostic)]
404#[diag(attr_parsing_expects_feature_list)]
405pub(crate) struct ExpectsFeatureList {
406    #[primary_span]
407    pub span: Span,
408
409    pub name: String,
410}
411
412#[derive(Diagnostic)]
413#[diag(attr_parsing_expects_features)]
414pub(crate) struct ExpectsFeatures {
415    #[primary_span]
416    pub span: Span,
417
418    pub name: String,
419}
420
421#[derive(Diagnostic)]
422#[diag(attr_parsing_invalid_since)]
423pub(crate) struct InvalidSince {
424    #[primary_span]
425    pub span: Span,
426}
427
428#[derive(Diagnostic)]
429#[diag(attr_parsing_soft_no_args)]
430pub(crate) struct SoftNoArgs {
431    #[primary_span]
432    pub span: Span,
433}
434
435#[derive(Diagnostic)]
436#[diag(attr_parsing_unknown_version_literal)]
437pub(crate) struct UnknownVersionLiteral {
438    #[primary_span]
439    pub span: Span,
440}
441
442// FIXME(jdonszelmann) duplicated from `rustc_passes`, remove once `check_attr` is integrated.
443#[derive(Diagnostic)]
444#[diag(attr_parsing_unused_multiple)]
445pub(crate) struct UnusedMultiple {
446    #[primary_span]
447    #[suggestion(code = "", applicability = "machine-applicable")]
448    pub this: Span,
449    #[note]
450    pub other: Span,
451    pub name: Symbol,
452}
453
454#[derive(Diagnostic)]
455#[diag(attr_parsing_stability_outside_std, code = E0734)]
456pub(crate) struct StabilityOutsideStd {
457    #[primary_span]
458    pub span: Span,
459}
460
461#[derive(Diagnostic)]
462#[diag(attr_parsing_empty_confusables)]
463pub(crate) struct EmptyConfusables {
464    #[primary_span]
465    pub span: Span,
466}
467
468#[derive(Diagnostic)]
469#[diag(attr_parsing_repr_ident, code = E0565)]
470pub(crate) struct ReprIdent {
471    #[primary_span]
472    pub span: Span,
473}
474
475#[derive(Diagnostic)]
476#[diag(attr_parsing_unrecognized_repr_hint, code = E0552)]
477#[help]
478pub(crate) struct UnrecognizedReprHint {
479    #[primary_span]
480    pub span: Span,
481}