naga/front/wgsl/
error.rs

1//! Formatting WGSL front end error messages.
2
3use crate::common::wgsl::TryToWgsl;
4use crate::diagnostic_filter::ConflictingDiagnosticRuleError;
5use crate::error::replace_control_chars;
6use crate::proc::{Alignment, ConstantEvaluatorError, ResolveError};
7use crate::{Scalar, SourceLocation, Span};
8
9use super::parse::directive::enable_extension::{EnableExtension, UnimplementedEnableExtension};
10use super::parse::directive::language_extension::{
11    LanguageExtension, UnimplementedLanguageExtension,
12};
13use super::parse::lexer::Token;
14
15use codespan_reporting::diagnostic::{Diagnostic, Label};
16use codespan_reporting::files::SimpleFile;
17use codespan_reporting::term;
18use thiserror::Error;
19
20use alloc::{
21    borrow::Cow,
22    boxed::Box,
23    format,
24    string::{String, ToString},
25    vec,
26    vec::Vec,
27};
28use core::ops::Range;
29
30#[derive(Clone, Debug)]
31pub struct ParseError {
32    message: String,
33    // The first span should be the primary span, and the other ones should be complementary.
34    labels: Vec<(Span, Cow<'static, str>)>,
35    notes: Vec<String>,
36}
37
38impl ParseError {
39    pub fn labels(&self) -> impl ExactSizeIterator<Item = (Span, &str)> + '_ {
40        self.labels
41            .iter()
42            .map(|&(span, ref msg)| (span, msg.as_ref()))
43    }
44
45    pub fn message(&self) -> &str {
46        &self.message
47    }
48
49    fn diagnostic(&self) -> Diagnostic<()> {
50        let diagnostic = Diagnostic::error()
51            .with_message(self.message.to_string())
52            .with_labels(
53                self.labels
54                    .iter()
55                    .filter_map(|label| label.0.to_range().map(|range| (label, range)))
56                    .map(|(label, range)| {
57                        Label::primary((), range).with_message(label.1.to_string())
58                    })
59                    .collect(),
60            )
61            .with_notes(
62                self.notes
63                    .iter()
64                    .map(|note| format!("note: {note}"))
65                    .collect(),
66            );
67        diagnostic
68    }
69
70    /// Emits a summary of the error to standard error stream.
71    #[cfg(feature = "stderr")]
72    pub fn emit_to_stderr(&self, source: &str) {
73        self.emit_to_stderr_with_path(source, "wgsl")
74    }
75
76    /// Emits a summary of the error to standard error stream.
77    #[cfg(feature = "stderr")]
78    pub fn emit_to_stderr_with_path<P>(&self, source: &str, path: P)
79    where
80        P: AsRef<std::path::Path>,
81    {
82        let path = path.as_ref().display().to_string();
83        let files = SimpleFile::new(path, replace_control_chars(source));
84        let config = term::Config::default();
85
86        cfg_if::cfg_if! {
87            if #[cfg(feature = "termcolor")] {
88                let writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Auto);
89            } else {
90                let writer = std::io::stderr();
91            }
92        }
93
94        term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
95            .expect("cannot write error");
96    }
97
98    /// Emits a summary of the error to a string.
99    pub fn emit_to_string(&self, source: &str) -> String {
100        self.emit_to_string_with_path(source, "wgsl")
101    }
102
103    /// Emits a summary of the error to a string.
104    pub fn emit_to_string_with_path<P>(&self, source: &str, path: P) -> String
105    where
106        P: AsRef<std::path::Path>,
107    {
108        let path = path.as_ref().display().to_string();
109        let files = SimpleFile::new(path, replace_control_chars(source));
110        let config = term::Config::default();
111
112        let mut writer = crate::error::DiagnosticBuffer::new();
113        term::emit(writer.inner_mut(), &config, &files, &self.diagnostic())
114            .expect("cannot write error");
115        writer.into_string()
116    }
117
118    /// Returns a [`SourceLocation`] for the first label in the error message.
119    pub fn location(&self, source: &str) -> Option<SourceLocation> {
120        self.labels.first().map(|label| label.0.location(source))
121    }
122}
123
124impl core::fmt::Display for ParseError {
125    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
126        write!(f, "{}", self.message)
127    }
128}
129
130impl core::error::Error for ParseError {}
131
132#[derive(Copy, Clone, Debug, PartialEq)]
133pub enum ExpectedToken<'a> {
134    Token(Token<'a>),
135    Identifier,
136    AfterIdentListComma,
137    AfterIdentListArg,
138    /// Expected: constant, parenthesized expression, identifier
139    PrimaryExpression,
140    /// Expected: assignment, increment/decrement expression
141    Assignment,
142    /// Expected: 'case', 'default', '}'
143    SwitchItem,
144    /// Expected: ',', ')'
145    WorkgroupSizeSeparator,
146    /// Expected: 'struct', 'let', 'var', 'type', ';', 'fn', eof
147    GlobalItem,
148    /// Expected a type.
149    Type,
150    /// Access of `var`, `let`, `const`.
151    Variable,
152    /// Access of a function
153    Function,
154    /// The `diagnostic` identifier of the `@diagnostic(…)` attribute.
155    DiagnosticAttribute,
156}
157
158#[derive(Clone, Copy, Debug, Error, PartialEq)]
159pub enum NumberError {
160    #[error("invalid numeric literal format")]
161    Invalid,
162    #[error("numeric literal not representable by target type")]
163    NotRepresentable,
164}
165
166#[derive(Copy, Clone, Debug, PartialEq)]
167pub enum InvalidAssignmentType {
168    Other,
169    Swizzle,
170    ImmutableBinding(Span),
171}
172
173#[derive(Clone, Debug)]
174pub(crate) enum Error<'a> {
175    Unexpected(Span, ExpectedToken<'a>),
176    UnexpectedComponents(Span),
177    UnexpectedOperationInConstContext(Span),
178    BadNumber(Span, NumberError),
179    BadMatrixScalarKind(Span, Scalar),
180    BadAccessor(Span),
181    BadTexture(Span),
182    BadTypeCast {
183        span: Span,
184        from_type: String,
185        to_type: String,
186    },
187    NotStorageTexture(Span),
188    BadTextureSampleType {
189        span: Span,
190        scalar: Scalar,
191    },
192    BadIncrDecrReferenceType(Span),
193    InvalidResolve(ResolveError),
194    InvalidForInitializer(Span),
195    /// A break if appeared outside of a continuing block
196    InvalidBreakIf(Span),
197    InvalidGatherComponent(Span),
198    InvalidConstructorComponentType(Span, i32),
199    InvalidIdentifierUnderscore(Span),
200    ReservedIdentifierPrefix(Span),
201    UnknownAddressSpace(Span),
202    RepeatedAttribute(Span),
203    UnknownAttribute(Span),
204    UnknownBuiltin(Span),
205    UnknownAccess(Span),
206    UnknownIdent(Span, &'a str),
207    UnknownScalarType(Span),
208    UnknownType(Span),
209    UnknownStorageFormat(Span),
210    UnknownConservativeDepth(Span),
211    UnknownEnableExtension(Span, &'a str),
212    UnknownLanguageExtension(Span, &'a str),
213    UnknownDiagnosticRuleName(Span),
214    SizeAttributeTooLow(Span, u32),
215    AlignAttributeTooLow(Span, Alignment),
216    NonPowerOfTwoAlignAttribute(Span),
217    InconsistentBinding(Span),
218    TypeNotConstructible(Span),
219    TypeNotInferable(Span),
220    InitializationTypeMismatch {
221        name: Span,
222        expected: String,
223        got: String,
224    },
225    DeclMissingTypeAndInit(Span),
226    MissingAttribute(&'static str, Span),
227    InvalidAddrOfOperand(Span),
228    InvalidAtomicPointer(Span),
229    InvalidAtomicOperandType(Span),
230    InvalidRayQueryPointer(Span),
231    NotPointer(Span),
232    NotReference(&'static str, Span),
233    InvalidAssignment {
234        span: Span,
235        ty: InvalidAssignmentType,
236    },
237    ReservedKeyword(Span),
238    /// Redefinition of an identifier (used for both module-scope and local redefinitions).
239    Redefinition {
240        /// Span of the identifier in the previous definition.
241        previous: Span,
242
243        /// Span of the identifier in the new definition.
244        current: Span,
245    },
246    /// A declaration refers to itself directly.
247    RecursiveDeclaration {
248        /// The location of the name of the declaration.
249        ident: Span,
250
251        /// The point at which it is used.
252        usage: Span,
253    },
254    /// A declaration refers to itself indirectly, through one or more other
255    /// definitions.
256    CyclicDeclaration {
257        /// The location of the name of some declaration in the cycle.
258        ident: Span,
259
260        /// The edges of the cycle of references.
261        ///
262        /// Each `(decl, reference)` pair indicates that the declaration whose
263        /// name is `decl` has an identifier at `reference` whose definition is
264        /// the next declaration in the cycle. The last pair's `reference` is
265        /// the same identifier as `ident`, above.
266        path: Box<[(Span, Span)]>,
267    },
268    InvalidSwitchSelector {
269        span: Span,
270    },
271    InvalidSwitchCase {
272        span: Span,
273    },
274    SwitchCaseTypeMismatch {
275        span: Span,
276    },
277    CalledEntryPoint(Span),
278    WrongArgumentCount {
279        span: Span,
280        expected: Range<u32>,
281        found: u32,
282    },
283    /// No overload of this function accepts this many arguments.
284    TooManyArguments {
285        /// The name of the function being called.
286        function: String,
287
288        /// The function name in the call expression.
289        call_span: Span,
290
291        /// The first argument that is unacceptable.
292        arg_span: Span,
293
294        /// Maximum number of arguments accepted by any overload of
295        /// this function.
296        max_arguments: u32,
297    },
298    /// A value passed to a builtin function has a type that is not
299    /// accepted by any overload of the function.
300    WrongArgumentType {
301        /// The name of the function being called.
302        function: String,
303
304        /// The function name in the call expression.
305        call_span: Span,
306
307        /// The first argument whose type is unacceptable.
308        arg_span: Span,
309
310        /// The index of the first argument whose type is unacceptable.
311        arg_index: u32,
312
313        /// That argument's actual type.
314        arg_ty: String,
315
316        /// The set of argument types that would have been accepted for
317        /// this argument, given the prior arguments.
318        allowed: Vec<String>,
319    },
320    /// A value passed to a builtin function has a type that is not
321    /// accepted, given the earlier arguments' types.
322    InconsistentArgumentType {
323        /// The name of the function being called.
324        function: String,
325
326        /// The function name in the call expression.
327        call_span: Span,
328
329        /// The first unacceptable argument.
330        arg_span: Span,
331
332        /// The index of the first unacceptable argument.
333        arg_index: u32,
334
335        /// The actual type of the first unacceptable argument.
336        arg_ty: String,
337
338        /// The prior argument whose type made the `arg_span` argument
339        /// unacceptable.
340        inconsistent_span: Span,
341
342        /// The index of the `inconsistent_span` argument.
343        inconsistent_index: u32,
344
345        /// The type of the `inconsistent_span` argument.
346        inconsistent_ty: String,
347
348        /// The types that would have been accepted instead of the
349        /// first unacceptable argument.
350        allowed: Vec<String>,
351    },
352    FunctionReturnsVoid(Span),
353    FunctionMustUseUnused(Span),
354    FunctionMustUseReturnsVoid(Span, Span),
355    InvalidWorkGroupUniformLoad(Span),
356    Internal(&'static str),
357    ExpectedConstExprConcreteIntegerScalar(Span),
358    ExpectedNonNegative(Span),
359    ExpectedPositiveArrayLength(Span),
360    MissingWorkgroupSize(Span),
361    ConstantEvaluatorError(Box<ConstantEvaluatorError>, Span),
362    AutoConversion(Box<AutoConversionError>),
363    AutoConversionLeafScalar(Box<AutoConversionLeafScalarError>),
364    ConcretizationFailed(Box<ConcretizationFailedError>),
365    ExceededLimitForNestedBraces {
366        span: Span,
367        limit: u8,
368    },
369    PipelineConstantIDValue(Span),
370    NotBool(Span),
371    ConstAssertFailed(Span),
372    DirectiveAfterFirstGlobalDecl {
373        directive_span: Span,
374    },
375    EnableExtensionNotYetImplemented {
376        kind: UnimplementedEnableExtension,
377        span: Span,
378    },
379    EnableExtensionNotEnabled {
380        kind: EnableExtension,
381        span: Span,
382    },
383    LanguageExtensionNotYetImplemented {
384        kind: UnimplementedLanguageExtension,
385        span: Span,
386    },
387    DiagnosticInvalidSeverity {
388        severity_control_name_span: Span,
389    },
390    DiagnosticDuplicateTriggeringRule(ConflictingDiagnosticRuleError),
391    DiagnosticAttributeNotYetImplementedAtParseSite {
392        site_name_plural: &'static str,
393        spans: Vec<Span>,
394    },
395    DiagnosticAttributeNotSupported {
396        on_what: DiagnosticAttributeNotSupportedPosition,
397        spans: Vec<Span>,
398    },
399    SelectUnexpectedArgumentType {
400        arg_span: Span,
401        arg_type: String,
402    },
403    SelectRejectAndAcceptHaveNoCommonType {
404        reject_span: Span,
405        reject_type: String,
406        accept_span: Span,
407        accept_type: String,
408    },
409    StructMemberTooLarge {
410        member_name_span: Span,
411    },
412    TypeTooLarge {
413        span: Span,
414    },
415}
416
417impl From<ConflictingDiagnosticRuleError> for Error<'_> {
418    fn from(value: ConflictingDiagnosticRuleError) -> Self {
419        Self::DiagnosticDuplicateTriggeringRule(value)
420    }
421}
422
423/// Used for diagnostic refinement in [`Error::DiagnosticAttributeNotSupported`].
424#[derive(Clone, Copy, Debug)]
425pub(crate) enum DiagnosticAttributeNotSupportedPosition {
426    SemicolonInModulePosition,
427    Other { display_plural: &'static str },
428}
429
430impl From<&'static str> for DiagnosticAttributeNotSupportedPosition {
431    fn from(display_plural: &'static str) -> Self {
432        Self::Other { display_plural }
433    }
434}
435
436#[derive(Clone, Debug)]
437pub(crate) struct AutoConversionError {
438    pub dest_span: Span,
439    pub dest_type: String,
440    pub source_span: Span,
441    pub source_type: String,
442}
443
444#[derive(Clone, Debug)]
445pub(crate) struct AutoConversionLeafScalarError {
446    pub dest_span: Span,
447    pub dest_scalar: String,
448    pub source_span: Span,
449    pub source_type: String,
450}
451
452#[derive(Clone, Debug)]
453pub(crate) struct ConcretizationFailedError {
454    pub expr_span: Span,
455    pub expr_type: String,
456    pub scalar: String,
457    pub inner: ConstantEvaluatorError,
458}
459
460impl<'a> Error<'a> {
461    #[cold]
462    #[inline(never)]
463    pub(crate) fn as_parse_error(&self, source: &'a str) -> ParseError {
464        match *self {
465            Error::Unexpected(unexpected_span, expected) => {
466                let expected_str = match expected {
467                    ExpectedToken::Token(token) => match token {
468                        Token::Separator(c) => format!("`{c}`"),
469                        Token::Paren(c) => format!("`{c}`"),
470                        Token::Attribute => "@".to_string(),
471                        Token::Number(_) => "number".to_string(),
472                        Token::Word(s) => s.to_string(),
473                        Token::Operation(c) => format!("operation (`{c}`)"),
474                        Token::LogicalOperation(c) => format!("logical operation (`{c}`)"),
475                        Token::ShiftOperation(c) => format!("bitshift (`{c}{c}`)"),
476                        Token::AssignmentOperation(c) if c == '<' || c == '>' => {
477                            format!("bitshift (`{c}{c}=`)")
478                        }
479                        Token::AssignmentOperation(c) => format!("operation (`{c}=`)"),
480                        Token::IncrementOperation => "increment operation".to_string(),
481                        Token::DecrementOperation => "decrement operation".to_string(),
482                        Token::Arrow => "->".to_string(),
483                        Token::Unknown(c) => format!("unknown (`{c}`)"),
484                        Token::Trivia => "trivia".to_string(),
485                        Token::DocComment(s) => format!("doc comment ('{s}')"),
486                        Token::ModuleDocComment(s) => format!("module doc comment ('{s}')"),
487                        Token::End => "end".to_string(),
488                    },
489                    ExpectedToken::Identifier => "identifier".to_string(),
490                    ExpectedToken::PrimaryExpression => "expression".to_string(),
491                    ExpectedToken::Assignment => "assignment or increment/decrement".to_string(),
492                    ExpectedToken::SwitchItem => concat!(
493                        "switch item (`case` or `default`) or a closing curly bracket ",
494                        "to signify the end of the switch statement (`}`)"
495                    )
496                    .to_string(),
497                    ExpectedToken::WorkgroupSizeSeparator => {
498                        "workgroup size separator (`,`) or a closing parenthesis".to_string()
499                    }
500                    ExpectedToken::GlobalItem => concat!(
501                        "global item (`struct`, `const`, `var`, `alias`, ",
502                        "`fn`, `diagnostic`, `enable`, `requires`, `;`) ",
503                        "or the end of the file"
504                    )
505                    .to_string(),
506                    ExpectedToken::Type => "type".to_string(),
507                    ExpectedToken::Variable => "variable access".to_string(),
508                    ExpectedToken::Function => "function name".to_string(),
509                    ExpectedToken::AfterIdentListArg => {
510                        "next argument, trailing comma, or end of list (`,` or `;`)".to_string()
511                    }
512                    ExpectedToken::AfterIdentListComma => {
513                        "next argument or end of list (`;`)".to_string()
514                    }
515                    ExpectedToken::DiagnosticAttribute => {
516                        "the `diagnostic` attribute identifier".to_string()
517                    }
518                };
519                ParseError {
520                    message: format!(
521                        "expected {}, found {:?}",
522                        expected_str, &source[unexpected_span],
523                    ),
524                    labels: vec![(unexpected_span, format!("expected {expected_str}").into())],
525                    notes: vec![],
526                }
527            }
528            Error::UnexpectedComponents(bad_span) => ParseError {
529                message: "unexpected components".to_string(),
530                labels: vec![(bad_span, "unexpected components".into())],
531                notes: vec![],
532            },
533            Error::UnexpectedOperationInConstContext(span) => ParseError {
534                message: "this operation is not supported in a const context".to_string(),
535                labels: vec![(span, "operation not supported here".into())],
536                notes: vec![],
537            },
538            Error::BadNumber(bad_span, ref err) => ParseError {
539                message: format!("{}: `{}`", err, &source[bad_span],),
540                labels: vec![(bad_span, err.to_string().into())],
541                notes: vec![],
542            },
543            Error::BadMatrixScalarKind(span, scalar) => ParseError {
544                message: format!(
545                    "matrix scalar type must be floating-point, but found `{}`",
546                    scalar.to_wgsl_for_diagnostics()
547                ),
548                labels: vec![(span, "must be floating-point (e.g. `f32`)".into())],
549                notes: vec![],
550            },
551            Error::BadAccessor(accessor_span) => ParseError {
552                message: format!("invalid field accessor `{}`", &source[accessor_span],),
553                labels: vec![(accessor_span, "invalid accessor".into())],
554                notes: vec![],
555            },
556            Error::UnknownIdent(ident_span, ident) => ParseError {
557                message: format!("no definition in scope for identifier: `{ident}`"),
558                labels: vec![(ident_span, "unknown identifier".into())],
559                notes: vec![],
560            },
561            Error::UnknownScalarType(bad_span) => ParseError {
562                message: format!("unknown scalar type: `{}`", &source[bad_span]),
563                labels: vec![(bad_span, "unknown scalar type".into())],
564                notes: vec!["Valid scalar types are f32, f64, i32, u32, bool".into()],
565            },
566            Error::NotStorageTexture(bad_span) => ParseError {
567                message: "textureStore can only be applied to storage textures".to_string(),
568                labels: vec![(bad_span, "not a storage texture".into())],
569                notes: vec![],
570            },
571            Error::BadTextureSampleType { span, scalar } => ParseError {
572                message: format!(
573                    "texture sample type must be one of f32, i32 or u32, but found {}",
574                    scalar.to_wgsl_for_diagnostics()
575                ),
576                labels: vec![(span, "must be one of f32, i32 or u32".into())],
577                notes: vec![],
578            },
579            Error::BadIncrDecrReferenceType(span) => ParseError {
580                message: concat!(
581                    "increment/decrement operation requires ",
582                    "reference type to be one of i32 or u32"
583                )
584                .to_string(),
585                labels: vec![(span, "must be a reference type of i32 or u32".into())],
586                notes: vec![],
587            },
588            Error::BadTexture(bad_span) => ParseError {
589                message: format!(
590                    "expected an image, but found `{}` which is not an image",
591                    &source[bad_span]
592                ),
593                labels: vec![(bad_span, "not an image".into())],
594                notes: vec![],
595            },
596            Error::BadTypeCast {
597                span,
598                ref from_type,
599                ref to_type,
600            } => {
601                let msg = format!("cannot cast a {from_type} to a {to_type}");
602                ParseError {
603                    message: msg.clone(),
604                    labels: vec![(span, msg.into())],
605                    notes: vec![],
606                }
607            }
608            Error::InvalidResolve(ref resolve_error) => ParseError {
609                message: resolve_error.to_string(),
610                labels: vec![],
611                notes: vec![],
612            },
613            Error::InvalidForInitializer(bad_span) => ParseError {
614                message: format!(
615                    "for(;;) initializer is not an assignment or a function call: `{}`",
616                    &source[bad_span]
617                ),
618                labels: vec![(bad_span, "not an assignment or function call".into())],
619                notes: vec![],
620            },
621            Error::InvalidBreakIf(bad_span) => ParseError {
622                message: "A break if is only allowed in a continuing block".to_string(),
623                labels: vec![(bad_span, "not in a continuing block".into())],
624                notes: vec![],
625            },
626            Error::InvalidGatherComponent(bad_span) => ParseError {
627                message: format!(
628                    "textureGather component `{}` doesn't exist, must be 0, 1, 2, or 3",
629                    &source[bad_span]
630                ),
631                labels: vec![(bad_span, "invalid component".into())],
632                notes: vec![],
633            },
634            Error::InvalidConstructorComponentType(bad_span, component) => ParseError {
635                message: format!("invalid type for constructor component at index [{component}]"),
636                labels: vec![(bad_span, "invalid component type".into())],
637                notes: vec![],
638            },
639            Error::InvalidIdentifierUnderscore(bad_span) => ParseError {
640                message: "Identifier can't be `_`".to_string(),
641                labels: vec![(bad_span, "invalid identifier".into())],
642                notes: vec![
643                    "Use phony assignment instead (`_ =` notice the absence of `let` or `var`)"
644                        .to_string(),
645                ],
646            },
647            Error::ReservedIdentifierPrefix(bad_span) => ParseError {
648                message: format!(
649                    "Identifier starts with a reserved prefix: `{}`",
650                    &source[bad_span]
651                ),
652                labels: vec![(bad_span, "invalid identifier".into())],
653                notes: vec![],
654            },
655            Error::UnknownAddressSpace(bad_span) => ParseError {
656                message: format!("unknown address space: `{}`", &source[bad_span]),
657                labels: vec![(bad_span, "unknown address space".into())],
658                notes: vec![],
659            },
660            Error::RepeatedAttribute(bad_span) => ParseError {
661                message: format!("repeated attribute: `{}`", &source[bad_span]),
662                labels: vec![(bad_span, "repeated attribute".into())],
663                notes: vec![],
664            },
665            Error::UnknownAttribute(bad_span) => ParseError {
666                message: format!("unknown attribute: `{}`", &source[bad_span]),
667                labels: vec![(bad_span, "unknown attribute".into())],
668                notes: vec![],
669            },
670            Error::UnknownBuiltin(bad_span) => ParseError {
671                message: format!("unknown builtin: `{}`", &source[bad_span]),
672                labels: vec![(bad_span, "unknown builtin".into())],
673                notes: vec![],
674            },
675            Error::UnknownAccess(bad_span) => ParseError {
676                message: format!("unknown access: `{}`", &source[bad_span]),
677                labels: vec![(bad_span, "unknown access".into())],
678                notes: vec![],
679            },
680            Error::UnknownStorageFormat(bad_span) => ParseError {
681                message: format!("unknown storage format: `{}`", &source[bad_span]),
682                labels: vec![(bad_span, "unknown storage format".into())],
683                notes: vec![],
684            },
685            Error::UnknownConservativeDepth(bad_span) => ParseError {
686                message: format!("unknown conservative depth: `{}`", &source[bad_span]),
687                labels: vec![(bad_span, "unknown conservative depth".into())],
688                notes: vec![],
689            },
690            Error::UnknownType(bad_span) => ParseError {
691                message: format!("unknown type: `{}`", &source[bad_span]),
692                labels: vec![(bad_span, "unknown type".into())],
693                notes: vec![],
694            },
695            Error::UnknownEnableExtension(span, word) => ParseError {
696                message: format!("unknown enable-extension `{word}`"),
697                labels: vec![(span, "".into())],
698                notes: vec![
699                    "See available extensions at <https://www.w3.org/TR/WGSL/#enable-extension>."
700                        .into(),
701                ],
702            },
703            Error::UnknownLanguageExtension(span, name) => ParseError {
704                message: format!("unknown language extension `{name}`"),
705                labels: vec![(span, "".into())],
706                notes: vec![concat!(
707                    "See available extensions at ",
708                    "<https://www.w3.org/TR/WGSL/#language-extensions-sec>."
709                )
710                .into()],
711            },
712            Error::UnknownDiagnosticRuleName(span) => ParseError {
713                message: format!("unknown `diagnostic(…)` rule name `{}`", &source[span]),
714                labels: vec![(span, "not a valid diagnostic rule name".into())],
715                notes: vec![concat!(
716                    "See available trigger rules at ",
717                    "<https://www.w3.org/TR/WGSL/#filterable-triggering-rules>."
718                )
719                .into()],
720            },
721            Error::SizeAttributeTooLow(bad_span, min_size) => ParseError {
722                message: format!("struct member size must be at least {min_size}"),
723                labels: vec![(bad_span, format!("must be at least {min_size}").into())],
724                notes: vec![],
725            },
726            Error::AlignAttributeTooLow(bad_span, min_align) => ParseError {
727                message: format!("struct member alignment must be at least {min_align}"),
728                labels: vec![(bad_span, format!("must be at least {min_align}").into())],
729                notes: vec![],
730            },
731            Error::NonPowerOfTwoAlignAttribute(bad_span) => ParseError {
732                message: "struct member alignment must be a power of 2".to_string(),
733                labels: vec![(bad_span, "must be a power of 2".into())],
734                notes: vec![],
735            },
736            Error::InconsistentBinding(span) => ParseError {
737                message: "input/output binding is not consistent".to_string(),
738                labels: vec![(span, "input/output binding is not consistent".into())],
739                notes: vec![],
740            },
741            Error::TypeNotConstructible(span) => ParseError {
742                message: format!("type `{}` is not constructible", &source[span]),
743                labels: vec![(span, "type is not constructible".into())],
744                notes: vec![],
745            },
746            Error::TypeNotInferable(span) => ParseError {
747                message: "type can't be inferred".to_string(),
748                labels: vec![(span, "type can't be inferred".into())],
749                notes: vec![],
750            },
751            Error::InitializationTypeMismatch {
752                name,
753                ref expected,
754                ref got,
755            } => ParseError {
756                message: format!(
757                    "the type of `{}` is expected to be `{}`, but got `{}`",
758                    &source[name], expected, got,
759                ),
760                labels: vec![(name, format!("definition of `{}`", &source[name]).into())],
761                notes: vec![],
762            },
763            Error::DeclMissingTypeAndInit(name_span) => ParseError {
764                message: format!(
765                    "declaration of `{}` needs a type specifier or initializer",
766                    &source[name_span]
767                ),
768                labels: vec![(name_span, "needs a type specifier or initializer".into())],
769                notes: vec![],
770            },
771            Error::MissingAttribute(name, name_span) => ParseError {
772                message: format!(
773                    "variable `{}` needs a '{}' attribute",
774                    &source[name_span], name
775                ),
776                labels: vec![(
777                    name_span,
778                    format!("definition of `{}`", &source[name_span]).into(),
779                )],
780                notes: vec![],
781            },
782            Error::InvalidAddrOfOperand(span) => ParseError {
783                message: "cannot take the address of a vector component".to_string(),
784                labels: vec![(span, "invalid operand for address-of".into())],
785                notes: vec![],
786            },
787            Error::InvalidAtomicPointer(span) => ParseError {
788                message: "atomic operation is done on a pointer to a non-atomic".to_string(),
789                labels: vec![(span, "atomic pointer is invalid".into())],
790                notes: vec![],
791            },
792            Error::InvalidAtomicOperandType(span) => ParseError {
793                message: "atomic operand type is inconsistent with the operation".to_string(),
794                labels: vec![(span, "atomic operand type is invalid".into())],
795                notes: vec![],
796            },
797            Error::InvalidRayQueryPointer(span) => ParseError {
798                message: "ray query operation is done on a pointer to a non-ray-query".to_string(),
799                labels: vec![(span, "ray query pointer is invalid".into())],
800                notes: vec![],
801            },
802            Error::NotPointer(span) => ParseError {
803                message: "the operand of the `*` operator must be a pointer".to_string(),
804                labels: vec![(span, "expression is not a pointer".into())],
805                notes: vec![],
806            },
807            Error::NotReference(what, span) => ParseError {
808                message: format!("{what} must be a reference"),
809                labels: vec![(span, "expression is not a reference".into())],
810                notes: vec![],
811            },
812            Error::InvalidAssignment { span, ty } => {
813                let (extra_label, notes) = match ty {
814                    InvalidAssignmentType::Swizzle => (
815                        None,
816                        vec![
817                            "WGSL does not support assignments to swizzles".into(),
818                            "consider assigning each component individually".into(),
819                        ],
820                    ),
821                    InvalidAssignmentType::ImmutableBinding(binding_span) => (
822                        Some((binding_span, "this is an immutable binding".into())),
823                        vec![format!(
824                            "consider declaring `{}` with `var` instead of `let`",
825                            &source[binding_span]
826                        )],
827                    ),
828                    InvalidAssignmentType::Other => (None, vec![]),
829                };
830
831                ParseError {
832                    message: "invalid left-hand side of assignment".into(),
833                    labels: core::iter::once((span, "cannot assign to this expression".into()))
834                        .chain(extra_label)
835                        .collect(),
836                    notes,
837                }
838            }
839            Error::ReservedKeyword(name_span) => ParseError {
840                message: format!("name `{}` is a reserved keyword", &source[name_span]),
841                labels: vec![(
842                    name_span,
843                    format!("definition of `{}`", &source[name_span]).into(),
844                )],
845                notes: vec![],
846            },
847            Error::Redefinition { previous, current } => ParseError {
848                message: format!("redefinition of `{}`", &source[current]),
849                labels: vec![
850                    (
851                        current,
852                        format!("redefinition of `{}`", &source[current]).into(),
853                    ),
854                    (
855                        previous,
856                        format!("previous definition of `{}`", &source[previous]).into(),
857                    ),
858                ],
859                notes: vec![],
860            },
861            Error::RecursiveDeclaration { ident, usage } => ParseError {
862                message: format!("declaration of `{}` is recursive", &source[ident]),
863                labels: vec![(ident, "".into()), (usage, "uses itself here".into())],
864                notes: vec![],
865            },
866            Error::CyclicDeclaration { ident, ref path } => ParseError {
867                message: format!("declaration of `{}` is cyclic", &source[ident]),
868                labels: path
869                    .iter()
870                    .enumerate()
871                    .flat_map(|(i, &(ident, usage))| {
872                        [
873                            (ident, "".into()),
874                            (
875                                usage,
876                                if i == path.len() - 1 {
877                                    "ending the cycle".into()
878                                } else {
879                                    format!("uses `{}`", &source[ident]).into()
880                                },
881                            ),
882                        ]
883                    })
884                    .collect(),
885                notes: vec![],
886            },
887            Error::InvalidSwitchSelector { span } => ParseError {
888                message: "invalid `switch` selector".to_string(),
889                labels: vec![(
890                    span,
891                    "`switch` selector must be a scalar integer"
892                    .into(),
893                )],
894                notes: vec![],
895            },
896            Error::InvalidSwitchCase { span } => ParseError {
897                message: "invalid `switch` case selector value".to_string(),
898                labels: vec![(
899                    span,
900                    "`switch` case selector must be a scalar integer const expression"
901                    .into(),
902                )],
903                notes: vec![],
904            },
905            Error::SwitchCaseTypeMismatch { span } => ParseError {
906                message: "invalid `switch` case selector value".to_string(),
907                labels: vec![(
908                    span,
909                    "`switch` case selector must have the same type as the `switch` selector expression"
910                    .into(),
911                )],
912                notes: vec![],
913            },
914            Error::CalledEntryPoint(span) => ParseError {
915                message: "entry point cannot be called".to_string(),
916                labels: vec![(span, "entry point cannot be called".into())],
917                notes: vec![],
918            },
919            Error::WrongArgumentCount {
920                span,
921                ref expected,
922                found,
923            } => ParseError {
924                message: format!(
925                    "wrong number of arguments: expected {}, found {}",
926                    if expected.len() < 2 {
927                        format!("{}", expected.start)
928                    } else {
929                        format!("{}..{}", expected.start, expected.end)
930                    },
931                    found
932                ),
933                labels: vec![(span, "wrong number of arguments".into())],
934                notes: vec![],
935            },
936            Error::TooManyArguments {
937                ref function,
938                call_span,
939                arg_span,
940                max_arguments,
941            } => ParseError {
942                message: format!("too many arguments passed to `{function}`"),
943                labels: vec![
944                    (call_span, "".into()),
945                    (arg_span, format!("unexpected argument #{}", max_arguments + 1).into())
946                ],
947                notes: vec![
948                    format!("The `{function}` function accepts at most {max_arguments} argument(s)")
949                ],
950            },
951            Error::WrongArgumentType {
952                ref function,
953                call_span,
954                arg_span,
955                arg_index,
956                ref arg_ty,
957                ref allowed,
958            } => {
959                let message = format!(
960                    "wrong type passed as argument #{} to `{function}`",
961                    arg_index + 1,
962                );
963                let labels = vec![
964                    (call_span, "".into()),
965                    (arg_span, format!("argument #{} has type `{arg_ty}`", arg_index + 1).into())
966                ];
967
968                let mut notes = vec![];
969                notes.push(format!("`{function}` accepts the following types for argument #{}:", arg_index + 1));
970                notes.extend(allowed.iter().map(|ty| format!("allowed type: {ty}")));
971
972                ParseError { message, labels, notes }
973            },
974            Error::InconsistentArgumentType {
975                ref function,
976                call_span,
977                arg_span,
978                arg_index,
979                ref arg_ty,
980                inconsistent_span,
981                inconsistent_index,
982                ref inconsistent_ty,
983                ref allowed
984            } => {
985                let message = format!(
986                    "inconsistent type passed as argument #{} to `{function}`",
987                    arg_index + 1,
988                );
989                let labels = vec![
990                    (call_span, "".into()),
991                    (arg_span, format!("argument #{} has type {arg_ty}", arg_index + 1).into()),
992                    (inconsistent_span, format!(
993                        "this argument has type {inconsistent_ty}, which constrains subsequent arguments"
994                    ).into()),
995                ];
996                let mut notes = vec![
997                    format!("Because argument #{} has type {inconsistent_ty}, only the following types", inconsistent_index + 1),
998                    format!("(or types that automatically convert to them) are accepted for argument #{}:", arg_index + 1),
999                ];
1000                notes.extend(allowed.iter().map(|ty| format!("allowed type: {ty}")));
1001
1002                ParseError { message, labels, notes }
1003            }
1004            Error::FunctionReturnsVoid(span) => ParseError {
1005                message: "function does not return any value".to_string(),
1006                labels: vec![(span, "".into())],
1007                notes: vec![
1008                    "perhaps you meant to call the function in a separate statement?".into(),
1009                ],
1010            },
1011            Error::FunctionMustUseUnused(call) => ParseError {
1012                message: "unused return value from function annotated with @must_use".into(),
1013                labels: vec![(call, "".into())],
1014                notes: vec![
1015                    format!(
1016                        "function '{}' is declared with `@must_use` attribute",
1017                        &source[call],
1018                    ),
1019                    "use a phony assignment or declare a value using the function call as the initializer".into(),
1020                ],
1021            },
1022            Error::FunctionMustUseReturnsVoid(attr, signature) => ParseError {
1023                message: "function annotated with @must_use but does not return any value".into(),
1024                labels: vec![
1025                    (attr, "".into()),
1026                    (signature, "".into()),
1027                ],
1028                notes: vec![
1029                    "declare a return type or remove the attribute".into(),
1030                ],
1031            },
1032            Error::InvalidWorkGroupUniformLoad(span) => ParseError {
1033                message: "incorrect type passed to workgroupUniformLoad".into(),
1034                labels: vec![(span, "".into())],
1035                notes: vec!["passed type must be a workgroup pointer".into()],
1036            },
1037            Error::Internal(message) => ParseError {
1038                message: "internal WGSL front end error".to_string(),
1039                labels: vec![],
1040                notes: vec![message.into()],
1041            },
1042            Error::ExpectedConstExprConcreteIntegerScalar(span) => ParseError {
1043                message: concat!(
1044                    "must be a const-expression that ",
1045                    "resolves to a concrete integer scalar (`u32` or `i32`)"
1046                )
1047                .to_string(),
1048                labels: vec![(span, "must resolve to `u32` or `i32`".into())],
1049                notes: vec![],
1050            },
1051            Error::ExpectedNonNegative(span) => ParseError {
1052                message: "must be non-negative (>= 0)".to_string(),
1053                labels: vec![(span, "must be non-negative".into())],
1054                notes: vec![],
1055            },
1056            Error::ExpectedPositiveArrayLength(span) => ParseError {
1057                message: "array element count must be positive (> 0)".to_string(),
1058                labels: vec![(span, "must be positive".into())],
1059                notes: vec![],
1060            },
1061            Error::ConstantEvaluatorError(ref e, span) => ParseError {
1062                message: e.to_string(),
1063                labels: vec![(span, "see msg".into())],
1064                notes: vec![],
1065            },
1066            Error::MissingWorkgroupSize(span) => ParseError {
1067                message: "workgroup size is missing on compute shader entry point".to_string(),
1068                labels: vec![(
1069                    span,
1070                    "must be paired with a `@workgroup_size` attribute".into(),
1071                )],
1072                notes: vec![],
1073            },
1074            Error::AutoConversion(ref error) => {
1075                // destructuring ensures all fields are handled
1076                let AutoConversionError {
1077                    dest_span,
1078                    ref dest_type,
1079                    source_span,
1080                    ref source_type,
1081                } = **error;
1082                ParseError {
1083                    message: format!(
1084                        "automatic conversions cannot convert `{source_type}` to `{dest_type}`"
1085                    ),
1086                    labels: vec![
1087                        (
1088                            dest_span,
1089                            format!("a value of type {dest_type} is required here").into(),
1090                        ),
1091                        (
1092                            source_span,
1093                            format!("this expression has type {source_type}").into(),
1094                        ),
1095                    ],
1096                    notes: vec![],
1097                }
1098            }
1099            Error::AutoConversionLeafScalar(ref error) => {
1100                let AutoConversionLeafScalarError {
1101                    dest_span,
1102                    ref dest_scalar,
1103                    source_span,
1104                    ref source_type,
1105                } = **error;
1106                ParseError {
1107                    message: format!(
1108                        "automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"
1109                    ),
1110                    labels: vec![
1111                        (
1112                            dest_span,
1113                            format!(
1114                                "a value with elements of type {dest_scalar} is required here"
1115                            )
1116                            .into(),
1117                        ),
1118                        (
1119                            source_span,
1120                            format!("this expression has type {source_type}").into(),
1121                        ),
1122                    ],
1123                    notes: vec![],
1124                }
1125            }
1126            Error::ConcretizationFailed(ref error) => {
1127                let ConcretizationFailedError {
1128                    expr_span,
1129                    ref expr_type,
1130                    ref scalar,
1131                    ref inner,
1132                } = **error;
1133                ParseError {
1134                    message: format!("failed to convert expression to a concrete type: {inner}"),
1135                    labels: vec![(
1136                        expr_span,
1137                        format!("this expression has type {expr_type}").into(),
1138                    )],
1139                    notes: vec![format!(
1140                        "the expression should have been converted to have {} scalar type",
1141                        scalar
1142                    )],
1143                }
1144            }
1145            Error::ExceededLimitForNestedBraces { span, limit } => ParseError {
1146                message: "brace nesting limit reached".into(),
1147                labels: vec![(span, "limit reached at this brace".into())],
1148                notes: vec![format!("nesting limit is currently set to {limit}")],
1149            },
1150            Error::PipelineConstantIDValue(span) => ParseError {
1151                message: "pipeline constant ID must be between 0 and 65535 inclusive".to_string(),
1152                labels: vec![(span, "must be between 0 and 65535 inclusive".into())],
1153                notes: vec![],
1154            },
1155            Error::NotBool(span) => ParseError {
1156                message: "must be a const-expression that resolves to a `bool`".to_string(),
1157                labels: vec![(span, "must resolve to `bool`".into())],
1158                notes: vec![],
1159            },
1160            Error::ConstAssertFailed(span) => ParseError {
1161                message: "`const_assert` failure".to_string(),
1162                labels: vec![(span, "evaluates to `false`".into())],
1163                notes: vec![],
1164            },
1165            Error::DirectiveAfterFirstGlobalDecl { directive_span } => ParseError {
1166                message: "expected global declaration, but found a global directive".into(),
1167                labels: vec![(
1168                    directive_span,
1169                    "written after first global declaration".into(),
1170                )],
1171                notes: vec![concat!(
1172                    "global directives are only allowed before global declarations; ",
1173                    "maybe hoist this closer to the top of the shader module?"
1174                )
1175                .into()],
1176            },
1177            Error::EnableExtensionNotYetImplemented { kind, span } => ParseError {
1178                message: format!(
1179                    "the `{}` enable-extension is not yet supported",
1180                    EnableExtension::Unimplemented(kind).to_ident()
1181                ),
1182                labels: vec![(
1183                    span,
1184                    concat!(
1185                        "this enable-extension specifies standard functionality ",
1186                        "which is not yet implemented in Naga"
1187                    )
1188                    .into(),
1189                )],
1190                notes: vec![format!(
1191                    concat!(
1192                        "Let Naga maintainers know that you ran into this at ",
1193                        "<https://github.com/gfx-rs/wgpu/issues/{}>, ",
1194                        "so they can prioritize it!"
1195                    ),
1196                    kind.tracking_issue_num()
1197                )],
1198            },
1199            Error::EnableExtensionNotEnabled { kind, span } => ParseError {
1200                message: format!("the `{}` enable extension is not enabled", kind.to_ident()),
1201                labels: vec![(
1202                    span,
1203                    format!(
1204                        concat!(
1205                            "the `{}` \"Enable Extension\" is needed for this functionality, ",
1206                            "but it is not currently enabled."
1207                        ),
1208                        kind.to_ident()
1209                    )
1210                    .into(),
1211                )],
1212                notes: if let EnableExtension::Unimplemented(kind) = kind {
1213                    vec![format!(
1214                        concat!(
1215                            "This \"Enable Extension\" is not yet implemented. ",
1216                            "Let Naga maintainers know that you ran into this at ",
1217                            "<https://github.com/gfx-rs/wgpu/issues/{}>, ",
1218                            "so they can prioritize it!"
1219                        ),
1220                        kind.tracking_issue_num()
1221                    )]
1222                } else {
1223                    vec![
1224                        format!(
1225                            "You can enable this extension by adding `enable {};` at the top of the shader, before any other items.",
1226                            kind.to_ident()
1227                        ),
1228                    ]
1229                },
1230            },
1231            Error::LanguageExtensionNotYetImplemented { kind, span } => ParseError {
1232                message: format!(
1233                    "the `{}` language extension is not yet supported",
1234                    LanguageExtension::Unimplemented(kind).to_ident()
1235                ),
1236                labels: vec![(span, "".into())],
1237                notes: vec![format!(
1238                    concat!(
1239                        "Let Naga maintainers know that you ran into this at ",
1240                        "<https://github.com/gfx-rs/wgpu/issues/{}>, ",
1241                        "so they can prioritize it!"
1242                    ),
1243                    kind.tracking_issue_num()
1244                )],
1245            },
1246            Error::DiagnosticInvalidSeverity {
1247                severity_control_name_span,
1248            } => ParseError {
1249                message: "invalid `diagnostic(…)` severity".into(),
1250                labels: vec![(
1251                    severity_control_name_span,
1252                    "not a valid severity level".into(),
1253                )],
1254                notes: vec![concat!(
1255                    "See available severities at ",
1256                    "<https://www.w3.org/TR/WGSL/#diagnostic-severity>."
1257                )
1258                .into()],
1259            },
1260            Error::DiagnosticDuplicateTriggeringRule(ConflictingDiagnosticRuleError {
1261                triggering_rule_spans,
1262            }) => {
1263                let [first_span, second_span] = triggering_rule_spans;
1264                ParseError {
1265                    message: "found conflicting `diagnostic(…)` rule(s)".into(),
1266                    labels: vec![
1267                        (first_span, "first rule".into()),
1268                        (second_span, "second rule".into()),
1269                    ],
1270                    notes: vec![
1271                        concat!(
1272                            "Multiple `diagnostic(…)` rules with the same rule name ",
1273                            "conflict unless they are directives and the severity is the same.",
1274                        )
1275                        .into(),
1276                        "You should delete the rule you don't want.".into(),
1277                    ],
1278                }
1279            }
1280            Error::DiagnosticAttributeNotYetImplementedAtParseSite {
1281                site_name_plural,
1282                ref spans,
1283            } => ParseError {
1284                message: "`@diagnostic(…)` attribute(s) not yet implemented".into(),
1285                labels: {
1286                    let mut spans = spans.iter().cloned();
1287                    let first = spans
1288                        .next()
1289                        .map(|span| {
1290                            (
1291                                span,
1292                                format!("can't use this on {site_name_plural} (yet)").into(),
1293                            )
1294                        })
1295                        .expect("internal error: diag. attr. rejection on empty map");
1296                    core::iter::once(first)
1297                        .chain(spans.map(|span| (span, "".into())))
1298                        .collect()
1299                },
1300                notes: vec![format!(concat!(
1301                    "Let Naga maintainers know that you ran into this at ",
1302                    "<https://github.com/gfx-rs/wgpu/issues/5320>, ",
1303                    "so they can prioritize it!"
1304                ))],
1305            },
1306            Error::DiagnosticAttributeNotSupported { on_what, ref spans } => {
1307                // In this case the user may have intended to create a global diagnostic filter directive,
1308                // so display a note to them suggesting the correct syntax.
1309                let intended_diagnostic_directive = match on_what {
1310                    DiagnosticAttributeNotSupportedPosition::SemicolonInModulePosition => true,
1311                    DiagnosticAttributeNotSupportedPosition::Other { .. } => false,
1312                };
1313                let on_what_plural = match on_what {
1314                    DiagnosticAttributeNotSupportedPosition::SemicolonInModulePosition => {
1315                        "semicolons"
1316                    }
1317                    DiagnosticAttributeNotSupportedPosition::Other { display_plural } => {
1318                        display_plural
1319                    }
1320                };
1321                ParseError {
1322                    message: format!(
1323                        "`@diagnostic(…)` attribute(s) on {on_what_plural} are not supported",
1324                    ),
1325                    labels: spans
1326                        .iter()
1327                        .cloned()
1328                        .map(|span| (span, "".into()))
1329                        .collect(),
1330                    notes: vec![
1331                        concat!(
1332                            "`@diagnostic(…)` attributes are only permitted on `fn`s, ",
1333                            "some statements, and `switch`/`loop` bodies."
1334                        )
1335                        .into(),
1336                        {
1337                            if intended_diagnostic_directive {
1338                                concat!(
1339                                    "If you meant to declare a diagnostic filter that ",
1340                                    "applies to the entire module, move this line to ",
1341                                    "the top of the file and remove the `@` symbol."
1342                                )
1343                                .into()
1344                            } else {
1345                                concat!(
1346                                    "These attributes are well-formed, ",
1347                                    "you likely just need to move them."
1348                                )
1349                                .into()
1350                            }
1351                        },
1352                    ],
1353                }
1354            }
1355            Error::SelectUnexpectedArgumentType { arg_span, ref arg_type } => ParseError {
1356                message: "unexpected argument type for `select` call".into(),
1357                labels: vec![(arg_span, format!("this value of type {arg_type}").into())],
1358                notes: vec!["expected a scalar or a `vecN` of scalars".into()],
1359            },
1360            Error::SelectRejectAndAcceptHaveNoCommonType {
1361                reject_span,
1362                ref reject_type,
1363                accept_span,
1364                ref accept_type,
1365            } => ParseError {
1366                message: "type mismatch for reject and accept values in `select` call".into(),
1367                labels: vec![
1368                    (reject_span, format!("reject value of type {reject_type}").into()),
1369                    (accept_span, format!("accept value of type {accept_type}").into()),
1370                ],
1371                notes: vec![],
1372            },
1373            Error::StructMemberTooLarge { member_name_span } => ParseError {
1374                message: "struct member is too large".into(),
1375                labels: vec![(member_name_span, "this member exceeds the maximum size".into())],
1376                notes: vec![format!(
1377                    "the maximum size is {} bytes",
1378                    crate::valid::MAX_TYPE_SIZE
1379                )],
1380            },
1381            Error::TypeTooLarge { span } => ParseError {
1382                message: "type is too large".into(),
1383                labels: vec![(span, "this type exceeds the maximum size".into())],
1384                notes: vec![format!(
1385                    "the maximum size is {} bytes",
1386                    crate::valid::MAX_TYPE_SIZE
1387                )],
1388            },
1389        }
1390    }
1391}