1use crate::front::wgsl::parse::lexer::Token;
2use crate::front::wgsl::Scalar;
3use crate::proc::{Alignment, ConstantEvaluatorError, ResolveError};
4use crate::{SourceLocation, Span};
5use codespan_reporting::diagnostic::{Diagnostic, Label};
6use codespan_reporting::files::SimpleFile;
7use codespan_reporting::term;
8use std::borrow::Cow;
9use std::ops::Range;
10use termcolor::{ColorChoice, NoColor, StandardStream};
11use thiserror::Error;
12
13#[derive(Clone, Debug)]
14pub struct ParseError {
15 message: String,
16 labels: Vec<(Span, Cow<'static, str>)>,
17 notes: Vec<String>,
18}
19
20impl ParseError {
21 pub fn labels(&self) -> impl ExactSizeIterator<Item = (Span, &str)> + '_ {
22 self.labels
23 .iter()
24 .map(|&(span, ref msg)| (span, msg.as_ref()))
25 }
26
27 pub fn message(&self) -> &str {
28 &self.message
29 }
30
31 fn diagnostic(&self) -> Diagnostic<()> {
32 let diagnostic = Diagnostic::error()
33 .with_message(self.message.to_string())
34 .with_labels(
35 self.labels
36 .iter()
37 .filter_map(|label| label.0.to_range().map(|range| (label, range)))
38 .map(|(label, range)| {
39 Label::primary((), range).with_message(label.1.to_string())
40 })
41 .collect(),
42 )
43 .with_notes(
44 self.notes
45 .iter()
46 .map(|note| format!("note: {note}"))
47 .collect(),
48 );
49 diagnostic
50 }
51
52 pub fn emit_to_stderr(&self, source: &str) {
54 self.emit_to_stderr_with_path(source, "wgsl")
55 }
56
57 pub fn emit_to_stderr_with_path<P>(&self, source: &str, path: P)
59 where
60 P: AsRef<std::path::Path>,
61 {
62 let path = path.as_ref().display().to_string();
63 let files = SimpleFile::new(path, source);
64 let config = codespan_reporting::term::Config::default();
65 let writer = StandardStream::stderr(ColorChoice::Auto);
66 term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
67 .expect("cannot write error");
68 }
69
70 pub fn emit_to_string(&self, source: &str) -> String {
72 self.emit_to_string_with_path(source, "wgsl")
73 }
74
75 pub fn emit_to_string_with_path<P>(&self, source: &str, path: P) -> String
77 where
78 P: AsRef<std::path::Path>,
79 {
80 let path = path.as_ref().display().to_string();
81 let files = SimpleFile::new(path, source);
82 let config = codespan_reporting::term::Config::default();
83 let mut writer = NoColor::new(Vec::new());
84 term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
85 String::from_utf8(writer.into_inner()).unwrap()
86 }
87
88 pub fn location(&self, source: &str) -> Option<SourceLocation> {
90 self.labels.first().map(|label| label.0.location(source))
91 }
92}
93
94impl std::fmt::Display for ParseError {
95 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
96 write!(f, "{}", self.message)
97 }
98}
99
100impl std::error::Error for ParseError {
101 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
102 None
103 }
104}
105
106#[derive(Copy, Clone, Debug, PartialEq)]
107pub enum ExpectedToken<'a> {
108 Token(Token<'a>),
109 Identifier,
110 PrimaryExpression,
112 Assignment,
114 SwitchItem,
116 WorkgroupSizeSeparator,
118 GlobalItem,
120 Type,
122 Variable,
124 Function,
126}
127
128#[derive(Clone, Copy, Debug, Error, PartialEq)]
129pub enum NumberError {
130 #[error("invalid numeric literal format")]
131 Invalid,
132 #[error("numeric literal not representable by target type")]
133 NotRepresentable,
134 #[error("unimplemented f16 type")]
135 UnimplementedF16,
136}
137
138#[derive(Copy, Clone, Debug, PartialEq)]
139pub enum InvalidAssignmentType {
140 Other,
141 Swizzle,
142 ImmutableBinding(Span),
143}
144
145#[derive(Clone, Debug)]
146pub enum Error<'a> {
147 Unexpected(Span, ExpectedToken<'a>),
148 UnexpectedComponents(Span),
149 UnexpectedOperationInConstContext(Span),
150 BadNumber(Span, NumberError),
151 BadMatrixScalarKind(Span, Scalar),
152 BadAccessor(Span),
153 BadTexture(Span),
154 BadTypeCast {
155 span: Span,
156 from_type: String,
157 to_type: String,
158 },
159 BadTextureSampleType {
160 span: Span,
161 scalar: Scalar,
162 },
163 BadIncrDecrReferenceType(Span),
164 InvalidResolve(ResolveError),
165 InvalidForInitializer(Span),
166 InvalidBreakIf(Span),
168 InvalidGatherComponent(Span),
169 InvalidConstructorComponentType(Span, i32),
170 InvalidIdentifierUnderscore(Span),
171 ReservedIdentifierPrefix(Span),
172 UnknownAddressSpace(Span),
173 RepeatedAttribute(Span),
174 UnknownAttribute(Span),
175 UnknownBuiltin(Span),
176 UnknownAccess(Span),
177 UnknownIdent(Span, &'a str),
178 UnknownScalarType(Span),
179 UnknownType(Span),
180 UnknownStorageFormat(Span),
181 UnknownConservativeDepth(Span),
182 SizeAttributeTooLow(Span, u32),
183 AlignAttributeTooLow(Span, Alignment),
184 NonPowerOfTwoAlignAttribute(Span),
185 InconsistentBinding(Span),
186 TypeNotConstructible(Span),
187 TypeNotInferable(Span),
188 InitializationTypeMismatch {
189 name: Span,
190 expected: String,
191 got: String,
192 },
193 DeclMissingTypeAndInit(Span),
194 MissingAttribute(&'static str, Span),
195 InvalidAtomicPointer(Span),
196 InvalidAtomicOperandType(Span),
197 InvalidRayQueryPointer(Span),
198 Pointer(&'static str, Span),
199 NotPointer(Span),
200 NotReference(&'static str, Span),
201 InvalidAssignment {
202 span: Span,
203 ty: InvalidAssignmentType,
204 },
205 ReservedKeyword(Span),
206 Redefinition {
208 previous: Span,
210
211 current: Span,
213 },
214 RecursiveDeclaration {
216 ident: Span,
218
219 usage: Span,
221 },
222 CyclicDeclaration {
225 ident: Span,
227
228 path: Vec<(Span, Span)>,
235 },
236 InvalidSwitchValue {
237 uint: bool,
238 span: Span,
239 },
240 CalledEntryPoint(Span),
241 WrongArgumentCount {
242 span: Span,
243 expected: Range<u32>,
244 found: u32,
245 },
246 FunctionReturnsVoid(Span),
247 InvalidWorkGroupUniformLoad(Span),
248 Internal(&'static str),
249 ExpectedConstExprConcreteIntegerScalar(Span),
250 ExpectedNonNegative(Span),
251 ExpectedPositiveArrayLength(Span),
252 MissingWorkgroupSize(Span),
253 ConstantEvaluatorError(ConstantEvaluatorError, Span),
254 AutoConversion {
255 dest_span: Span,
256 dest_type: String,
257 source_span: Span,
258 source_type: String,
259 },
260 AutoConversionLeafScalar {
261 dest_span: Span,
262 dest_scalar: String,
263 source_span: Span,
264 source_type: String,
265 },
266 ConcretizationFailed {
267 expr_span: Span,
268 expr_type: String,
269 scalar: String,
270 inner: ConstantEvaluatorError,
271 },
272 ExceededLimitForNestedBraces {
273 span: Span,
274 limit: u8,
275 },
276 PipelineConstantIDValue(Span),
277}
278
279impl<'a> Error<'a> {
280 pub(crate) fn as_parse_error(&self, source: &'a str) -> ParseError {
281 match *self {
282 Error::Unexpected(unexpected_span, expected) => {
283 let expected_str = match expected {
284 ExpectedToken::Token(token) => {
285 match token {
286 Token::Separator(c) => format!("'{c}'"),
287 Token::Paren(c) => format!("'{c}'"),
288 Token::Attribute => "@".to_string(),
289 Token::Number(_) => "number".to_string(),
290 Token::Word(s) => s.to_string(),
291 Token::Operation(c) => format!("operation ('{c}')"),
292 Token::LogicalOperation(c) => format!("logical operation ('{c}')"),
293 Token::ShiftOperation(c) => format!("bitshift ('{c}{c}')"),
294 Token::AssignmentOperation(c) if c=='<' || c=='>' => format!("bitshift ('{c}{c}=')"),
295 Token::AssignmentOperation(c) => format!("operation ('{c}=')"),
296 Token::IncrementOperation => "increment operation".to_string(),
297 Token::DecrementOperation => "decrement operation".to_string(),
298 Token::Arrow => "->".to_string(),
299 Token::Unknown(c) => format!("unknown ('{c}')"),
300 Token::Trivia => "trivia".to_string(),
301 Token::End => "end".to_string(),
302 }
303 }
304 ExpectedToken::Identifier => "identifier".to_string(),
305 ExpectedToken::PrimaryExpression => "expression".to_string(),
306 ExpectedToken::Assignment => "assignment or increment/decrement".to_string(),
307 ExpectedToken::SwitchItem => "switch item ('case' or 'default') or a closing curly bracket to signify the end of the switch statement ('}')".to_string(),
308 ExpectedToken::WorkgroupSizeSeparator => "workgroup size separator (',') or a closing parenthesis".to_string(),
309 ExpectedToken::GlobalItem => "global item ('struct', 'const', 'var', 'alias', ';', 'fn') or the end of the file".to_string(),
310 ExpectedToken::Type => "type".to_string(),
311 ExpectedToken::Variable => "variable access".to_string(),
312 ExpectedToken::Function => "function name".to_string(),
313 };
314 ParseError {
315 message: format!(
316 "expected {}, found '{}'",
317 expected_str, &source[unexpected_span],
318 ),
319 labels: vec![(unexpected_span, format!("expected {expected_str}").into())],
320 notes: vec![],
321 }
322 }
323 Error::UnexpectedComponents(bad_span) => ParseError {
324 message: "unexpected components".to_string(),
325 labels: vec![(bad_span, "unexpected components".into())],
326 notes: vec![],
327 },
328 Error::UnexpectedOperationInConstContext(span) => ParseError {
329 message: "this operation is not supported in a const context".to_string(),
330 labels: vec![(span, "operation not supported here".into())],
331 notes: vec![],
332 },
333 Error::BadNumber(bad_span, ref err) => ParseError {
334 message: format!("{}: `{}`", err, &source[bad_span],),
335 labels: vec![(bad_span, err.to_string().into())],
336 notes: vec![],
337 },
338 Error::BadMatrixScalarKind(span, scalar) => ParseError {
339 message: format!(
340 "matrix scalar type must be floating-point, but found `{}`",
341 scalar.to_wgsl()
342 ),
343 labels: vec![(span, "must be floating-point (e.g. `f32`)".into())],
344 notes: vec![],
345 },
346 Error::BadAccessor(accessor_span) => ParseError {
347 message: format!("invalid field accessor `{}`", &source[accessor_span],),
348 labels: vec![(accessor_span, "invalid accessor".into())],
349 notes: vec![],
350 },
351 Error::UnknownIdent(ident_span, ident) => ParseError {
352 message: format!("no definition in scope for identifier: '{ident}'"),
353 labels: vec![(ident_span, "unknown identifier".into())],
354 notes: vec![],
355 },
356 Error::UnknownScalarType(bad_span) => ParseError {
357 message: format!("unknown scalar type: '{}'", &source[bad_span]),
358 labels: vec![(bad_span, "unknown scalar type".into())],
359 notes: vec!["Valid scalar types are f32, f64, i32, u32, bool".into()],
360 },
361 Error::BadTextureSampleType { span, scalar } => ParseError {
362 message: format!(
363 "texture sample type must be one of f32, i32 or u32, but found {}",
364 scalar.to_wgsl()
365 ),
366 labels: vec![(span, "must be one of f32, i32 or u32".into())],
367 notes: vec![],
368 },
369 Error::BadIncrDecrReferenceType(span) => ParseError {
370 message:
371 "increment/decrement operation requires reference type to be one of i32 or u32"
372 .to_string(),
373 labels: vec![(span, "must be a reference type of i32 or u32".into())],
374 notes: vec![],
375 },
376 Error::BadTexture(bad_span) => ParseError {
377 message: format!(
378 "expected an image, but found '{}' which is not an image",
379 &source[bad_span]
380 ),
381 labels: vec![(bad_span, "not an image".into())],
382 notes: vec![],
383 },
384 Error::BadTypeCast {
385 span,
386 ref from_type,
387 ref to_type,
388 } => {
389 let msg = format!("cannot cast a {from_type} to a {to_type}");
390 ParseError {
391 message: msg.clone(),
392 labels: vec![(span, msg.into())],
393 notes: vec![],
394 }
395 }
396 Error::InvalidResolve(ref resolve_error) => ParseError {
397 message: resolve_error.to_string(),
398 labels: vec![],
399 notes: vec![],
400 },
401 Error::InvalidForInitializer(bad_span) => ParseError {
402 message: format!(
403 "for(;;) initializer is not an assignment or a function call: '{}'",
404 &source[bad_span]
405 ),
406 labels: vec![(bad_span, "not an assignment or function call".into())],
407 notes: vec![],
408 },
409 Error::InvalidBreakIf(bad_span) => ParseError {
410 message: "A break if is only allowed in a continuing block".to_string(),
411 labels: vec![(bad_span, "not in a continuing block".into())],
412 notes: vec![],
413 },
414 Error::InvalidGatherComponent(bad_span) => ParseError {
415 message: format!(
416 "textureGather component '{}' doesn't exist, must be 0, 1, 2, or 3",
417 &source[bad_span]
418 ),
419 labels: vec![(bad_span, "invalid component".into())],
420 notes: vec![],
421 },
422 Error::InvalidConstructorComponentType(bad_span, component) => ParseError {
423 message: format!("invalid type for constructor component at index [{component}]"),
424 labels: vec![(bad_span, "invalid component type".into())],
425 notes: vec![],
426 },
427 Error::InvalidIdentifierUnderscore(bad_span) => ParseError {
428 message: "Identifier can't be '_'".to_string(),
429 labels: vec![(bad_span, "invalid identifier".into())],
430 notes: vec![
431 "Use phony assignment instead ('_ =' notice the absence of 'let' or 'var')"
432 .to_string(),
433 ],
434 },
435 Error::ReservedIdentifierPrefix(bad_span) => ParseError {
436 message: format!(
437 "Identifier starts with a reserved prefix: '{}'",
438 &source[bad_span]
439 ),
440 labels: vec![(bad_span, "invalid identifier".into())],
441 notes: vec![],
442 },
443 Error::UnknownAddressSpace(bad_span) => ParseError {
444 message: format!("unknown address space: '{}'", &source[bad_span]),
445 labels: vec![(bad_span, "unknown address space".into())],
446 notes: vec![],
447 },
448 Error::RepeatedAttribute(bad_span) => ParseError {
449 message: format!("repeated attribute: '{}'", &source[bad_span]),
450 labels: vec![(bad_span, "repeated attribute".into())],
451 notes: vec![],
452 },
453 Error::UnknownAttribute(bad_span) => ParseError {
454 message: format!("unknown attribute: '{}'", &source[bad_span]),
455 labels: vec![(bad_span, "unknown attribute".into())],
456 notes: vec![],
457 },
458 Error::UnknownBuiltin(bad_span) => ParseError {
459 message: format!("unknown builtin: '{}'", &source[bad_span]),
460 labels: vec![(bad_span, "unknown builtin".into())],
461 notes: vec![],
462 },
463 Error::UnknownAccess(bad_span) => ParseError {
464 message: format!("unknown access: '{}'", &source[bad_span]),
465 labels: vec![(bad_span, "unknown access".into())],
466 notes: vec![],
467 },
468 Error::UnknownStorageFormat(bad_span) => ParseError {
469 message: format!("unknown storage format: '{}'", &source[bad_span]),
470 labels: vec![(bad_span, "unknown storage format".into())],
471 notes: vec![],
472 },
473 Error::UnknownConservativeDepth(bad_span) => ParseError {
474 message: format!("unknown conservative depth: '{}'", &source[bad_span]),
475 labels: vec![(bad_span, "unknown conservative depth".into())],
476 notes: vec![],
477 },
478 Error::UnknownType(bad_span) => ParseError {
479 message: format!("unknown type: '{}'", &source[bad_span]),
480 labels: vec![(bad_span, "unknown type".into())],
481 notes: vec![],
482 },
483 Error::SizeAttributeTooLow(bad_span, min_size) => ParseError {
484 message: format!("struct member size must be at least {min_size}"),
485 labels: vec![(bad_span, format!("must be at least {min_size}").into())],
486 notes: vec![],
487 },
488 Error::AlignAttributeTooLow(bad_span, min_align) => ParseError {
489 message: format!("struct member alignment must be at least {min_align}"),
490 labels: vec![(bad_span, format!("must be at least {min_align}").into())],
491 notes: vec![],
492 },
493 Error::NonPowerOfTwoAlignAttribute(bad_span) => ParseError {
494 message: "struct member alignment must be a power of 2".to_string(),
495 labels: vec![(bad_span, "must be a power of 2".into())],
496 notes: vec![],
497 },
498 Error::InconsistentBinding(span) => ParseError {
499 message: "input/output binding is not consistent".to_string(),
500 labels: vec![(span, "input/output binding is not consistent".into())],
501 notes: vec![],
502 },
503 Error::TypeNotConstructible(span) => ParseError {
504 message: format!("type `{}` is not constructible", &source[span]),
505 labels: vec![(span, "type is not constructible".into())],
506 notes: vec![],
507 },
508 Error::TypeNotInferable(span) => ParseError {
509 message: "type can't be inferred".to_string(),
510 labels: vec![(span, "type can't be inferred".into())],
511 notes: vec![],
512 },
513 Error::InitializationTypeMismatch { name, ref expected, ref got } => {
514 ParseError {
515 message: format!(
516 "the type of `{}` is expected to be `{}`, but got `{}`",
517 &source[name], expected, got,
518 ),
519 labels: vec![(
520 name,
521 format!("definition of `{}`", &source[name]).into(),
522 )],
523 notes: vec![],
524 }
525 }
526 Error::DeclMissingTypeAndInit(name_span) => ParseError {
527 message: format!("declaration of `{}` needs a type specifier or initializer", &source[name_span]),
528 labels: vec![(
529 name_span,
530 "needs a type specifier or initializer".into(),
531 )],
532 notes: vec![],
533 },
534 Error::MissingAttribute(name, name_span) => ParseError {
535 message: format!(
536 "variable `{}` needs a '{}' attribute",
537 &source[name_span], name
538 ),
539 labels: vec![(
540 name_span,
541 format!("definition of `{}`", &source[name_span]).into(),
542 )],
543 notes: vec![],
544 },
545 Error::InvalidAtomicPointer(span) => ParseError {
546 message: "atomic operation is done on a pointer to a non-atomic".to_string(),
547 labels: vec![(span, "atomic pointer is invalid".into())],
548 notes: vec![],
549 },
550 Error::InvalidAtomicOperandType(span) => ParseError {
551 message: "atomic operand type is inconsistent with the operation".to_string(),
552 labels: vec![(span, "atomic operand type is invalid".into())],
553 notes: vec![],
554 },
555 Error::InvalidRayQueryPointer(span) => ParseError {
556 message: "ray query operation is done on a pointer to a non-ray-query".to_string(),
557 labels: vec![(span, "ray query pointer is invalid".into())],
558 notes: vec![],
559 },
560 Error::NotPointer(span) => ParseError {
561 message: "the operand of the `*` operator must be a pointer".to_string(),
562 labels: vec![(span, "expression is not a pointer".into())],
563 notes: vec![],
564 },
565 Error::NotReference(what, span) => ParseError {
566 message: format!("{what} must be a reference"),
567 labels: vec![(span, "expression is not a reference".into())],
568 notes: vec![],
569 },
570 Error::InvalidAssignment { span, ty } => {
571 let (extra_label, notes) = match ty {
572 InvalidAssignmentType::Swizzle => (
573 None,
574 vec![
575 "WGSL does not support assignments to swizzles".into(),
576 "consider assigning each component individually".into(),
577 ],
578 ),
579 InvalidAssignmentType::ImmutableBinding(binding_span) => (
580 Some((binding_span, "this is an immutable binding".into())),
581 vec![format!(
582 "consider declaring '{}' with `var` instead of `let`",
583 &source[binding_span]
584 )],
585 ),
586 InvalidAssignmentType::Other => (None, vec![]),
587 };
588
589 ParseError {
590 message: "invalid left-hand side of assignment".into(),
591 labels: std::iter::once((span, "cannot assign to this expression".into()))
592 .chain(extra_label)
593 .collect(),
594 notes,
595 }
596 }
597 Error::Pointer(what, span) => ParseError {
598 message: format!("{what} must not be a pointer"),
599 labels: vec![(span, "expression is a pointer".into())],
600 notes: vec![],
601 },
602 Error::ReservedKeyword(name_span) => ParseError {
603 message: format!("name `{}` is a reserved keyword", &source[name_span]),
604 labels: vec![(
605 name_span,
606 format!("definition of `{}`", &source[name_span]).into(),
607 )],
608 notes: vec![],
609 },
610 Error::Redefinition { previous, current } => ParseError {
611 message: format!("redefinition of `{}`", &source[current]),
612 labels: vec![
613 (
614 current,
615 format!("redefinition of `{}`", &source[current]).into(),
616 ),
617 (
618 previous,
619 format!("previous definition of `{}`", &source[previous]).into(),
620 ),
621 ],
622 notes: vec![],
623 },
624 Error::RecursiveDeclaration { ident, usage } => ParseError {
625 message: format!("declaration of `{}` is recursive", &source[ident]),
626 labels: vec![(ident, "".into()), (usage, "uses itself here".into())],
627 notes: vec![],
628 },
629 Error::CyclicDeclaration { ident, ref path } => ParseError {
630 message: format!("declaration of `{}` is cyclic", &source[ident]),
631 labels: path
632 .iter()
633 .enumerate()
634 .flat_map(|(i, &(ident, usage))| {
635 [
636 (ident, "".into()),
637 (
638 usage,
639 if i == path.len() - 1 {
640 "ending the cycle".into()
641 } else {
642 format!("uses `{}`", &source[ident]).into()
643 },
644 ),
645 ]
646 })
647 .collect(),
648 notes: vec![],
649 },
650 Error::InvalidSwitchValue { uint, span } => ParseError {
651 message: "invalid switch value".to_string(),
652 labels: vec![(
653 span,
654 if uint {
655 "expected unsigned integer"
656 } else {
657 "expected signed integer"
658 }
659 .into(),
660 )],
661 notes: vec![if uint {
662 format!("suffix the integer with a `u`: '{}u'", &source[span])
663 } else {
664 let span = span.to_range().unwrap();
665 format!(
666 "remove the `u` suffix: '{}'",
667 &source[span.start..span.end - 1]
668 )
669 }],
670 },
671 Error::CalledEntryPoint(span) => ParseError {
672 message: "entry point cannot be called".to_string(),
673 labels: vec![(span, "entry point cannot be called".into())],
674 notes: vec![],
675 },
676 Error::WrongArgumentCount {
677 span,
678 ref expected,
679 found,
680 } => ParseError {
681 message: format!(
682 "wrong number of arguments: expected {}, found {}",
683 if expected.len() < 2 {
684 format!("{}", expected.start)
685 } else {
686 format!("{}..{}", expected.start, expected.end)
687 },
688 found
689 ),
690 labels: vec![(span, "wrong number of arguments".into())],
691 notes: vec![],
692 },
693 Error::FunctionReturnsVoid(span) => ParseError {
694 message: "function does not return any value".to_string(),
695 labels: vec![(span, "".into())],
696 notes: vec![
697 "perhaps you meant to call the function in a separate statement?".into(),
698 ],
699 },
700 Error::InvalidWorkGroupUniformLoad(span) => ParseError {
701 message: "incorrect type passed to workgroupUniformLoad".into(),
702 labels: vec![(span, "".into())],
703 notes: vec!["passed type must be a workgroup pointer".into()],
704 },
705 Error::Internal(message) => ParseError {
706 message: "internal WGSL front end error".to_string(),
707 labels: vec![],
708 notes: vec![message.into()],
709 },
710 Error::ExpectedConstExprConcreteIntegerScalar(span) => ParseError {
711 message: "must be a const-expression that resolves to a concrete integer scalar (u32 or i32)".to_string(),
712 labels: vec![(span, "must resolve to u32 or i32".into())],
713 notes: vec![],
714 },
715 Error::ExpectedNonNegative(span) => ParseError {
716 message: "must be non-negative (>= 0)".to_string(),
717 labels: vec![(span, "must be non-negative".into())],
718 notes: vec![],
719 },
720 Error::ExpectedPositiveArrayLength(span) => ParseError {
721 message: "array element count must be positive (> 0)".to_string(),
722 labels: vec![(span, "must be positive".into())],
723 notes: vec![],
724 },
725 Error::ConstantEvaluatorError(ref e, span) => ParseError {
726 message: e.to_string(),
727 labels: vec![(span, "see msg".into())],
728 notes: vec![],
729 },
730 Error::MissingWorkgroupSize(span) => ParseError {
731 message: "workgroup size is missing on compute shader entry point".to_string(),
732 labels: vec![(
733 span,
734 "must be paired with a @workgroup_size attribute".into(),
735 )],
736 notes: vec![],
737 },
738 Error::AutoConversion { dest_span, ref dest_type, source_span, ref source_type } => ParseError {
739 message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"),
740 labels: vec![
741 (
742 dest_span,
743 format!("a value of type {dest_type} is required here").into(),
744 ),
745 (
746 source_span,
747 format!("this expression has type {source_type}").into(),
748 )
749 ],
750 notes: vec![],
751 },
752 Error::AutoConversionLeafScalar { dest_span, ref dest_scalar, source_span, ref source_type } => ParseError {
753 message: format!("automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"),
754 labels: vec![
755 (
756 dest_span,
757 format!("a value with elements of type {dest_scalar} is required here").into(),
758 ),
759 (
760 source_span,
761 format!("this expression has type {source_type}").into(),
762 )
763 ],
764 notes: vec![],
765 },
766 Error::ConcretizationFailed { expr_span, ref expr_type, ref scalar, ref inner } => ParseError {
767 message: format!("failed to convert expression to a concrete type: {}", inner),
768 labels: vec![
769 (
770 expr_span,
771 format!("this expression has type {}", expr_type).into(),
772 )
773 ],
774 notes: vec![
775 format!("the expression should have been converted to have {} scalar type", scalar),
776 ]
777 },
778 Error::ExceededLimitForNestedBraces { span, limit } => ParseError {
779 message: "brace nesting limit reached".into(),
780 labels: vec![(span, "limit reached at this brace".into())],
781 notes: vec![
782 format!("nesting limit is currently set to {limit}"),
783 ],
784 },
785 Error::PipelineConstantIDValue(span) => ParseError {
786 message: "pipeline constant ID must be between 0 and 65535 inclusive".to_string(),
787 labels: vec![(
788 span,
789 "must be between 0 and 65535 inclusive".into(),
790 )],
791 notes: vec![],
792 },
793 }
794 }
795}