1use crate::arena::{Arena, Handle, UniqueArena};
2
3use thiserror::Error;
4
5#[derive(Debug, PartialEq)]
85#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
86#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
87pub enum TypeResolution {
88 Handle(Handle<crate::Type>),
90
91 Value(crate::TypeInner),
97}
98
99impl TypeResolution {
100 pub const fn handle(&self) -> Option<Handle<crate::Type>> {
101 match *self {
102 Self::Handle(handle) => Some(handle),
103 Self::Value(_) => None,
104 }
105 }
106
107 pub fn inner_with<'a>(&'a self, arena: &'a UniqueArena<crate::Type>) -> &'a crate::TypeInner {
108 match *self {
109 Self::Handle(handle) => &arena[handle].inner,
110 Self::Value(ref inner) => inner,
111 }
112 }
113}
114
115impl Clone for TypeResolution {
117 fn clone(&self) -> Self {
118 use crate::TypeInner as Ti;
119 match *self {
120 Self::Handle(handle) => Self::Handle(handle),
121 Self::Value(ref v) => Self::Value(match *v {
122 Ti::Scalar { kind, width } => Ti::Scalar { kind, width },
123 Ti::Vector { size, kind, width } => Ti::Vector { size, kind, width },
124 Ti::Matrix {
125 rows,
126 columns,
127 width,
128 } => Ti::Matrix {
129 rows,
130 columns,
131 width,
132 },
133 Ti::Pointer { base, space } => Ti::Pointer { base, space },
134 Ti::ValuePointer {
135 size,
136 kind,
137 width,
138 space,
139 } => Ti::ValuePointer {
140 size,
141 kind,
142 width,
143 space,
144 },
145 _ => unreachable!("Unexpected clone type: {:?}", v),
146 }),
147 }
148 }
149}
150
151#[derive(Clone, Debug, Error, PartialEq)]
152pub enum ResolveError {
153 #[error("Index {index} is out of bounds for expression {expr:?}")]
154 OutOfBoundsIndex {
155 expr: Handle<crate::Expression>,
156 index: u32,
157 },
158 #[error("Invalid access into expression {expr:?}, indexed: {indexed}")]
159 InvalidAccess {
160 expr: Handle<crate::Expression>,
161 indexed: bool,
162 },
163 #[error("Invalid sub-access into type {ty:?}, indexed: {indexed}")]
164 InvalidSubAccess {
165 ty: Handle<crate::Type>,
166 indexed: bool,
167 },
168 #[error("Invalid scalar {0:?}")]
169 InvalidScalar(Handle<crate::Expression>),
170 #[error("Invalid vector {0:?}")]
171 InvalidVector(Handle<crate::Expression>),
172 #[error("Invalid pointer {0:?}")]
173 InvalidPointer(Handle<crate::Expression>),
174 #[error("Invalid image {0:?}")]
175 InvalidImage(Handle<crate::Expression>),
176 #[error("Function {name} not defined")]
177 FunctionNotDefined { name: String },
178 #[error("Function without return type")]
179 FunctionReturnsVoid,
180 #[error("Incompatible operands: {0}")]
181 IncompatibleOperands(String),
182 #[error("Function argument {0} doesn't exist")]
183 FunctionArgumentNotFound(u32),
184 #[error("Special type is not registered within the module")]
185 MissingSpecialType,
186}
187
188pub struct ResolveContext<'a> {
189 pub constants: &'a Arena<crate::Constant>,
190 pub types: &'a UniqueArena<crate::Type>,
191 pub special_types: &'a crate::SpecialTypes,
192 pub global_vars: &'a Arena<crate::GlobalVariable>,
193 pub local_vars: &'a Arena<crate::LocalVariable>,
194 pub functions: &'a Arena<crate::Function>,
195 pub arguments: &'a [crate::FunctionArgument],
196}
197
198impl<'a> ResolveContext<'a> {
199 pub const fn with_locals(
201 module: &'a crate::Module,
202 local_vars: &'a Arena<crate::LocalVariable>,
203 arguments: &'a [crate::FunctionArgument],
204 ) -> Self {
205 Self {
206 constants: &module.constants,
207 types: &module.types,
208 special_types: &module.special_types,
209 global_vars: &module.global_variables,
210 local_vars,
211 functions: &module.functions,
212 arguments,
213 }
214 }
215
216 pub fn resolve(
232 &self,
233 expr: &crate::Expression,
234 past: impl Fn(Handle<crate::Expression>) -> Result<&'a TypeResolution, ResolveError>,
235 ) -> Result<TypeResolution, ResolveError> {
236 use crate::TypeInner as Ti;
237 let types = self.types;
238 Ok(match *expr {
239 crate::Expression::Access { base, .. } => match *past(base)?.inner_with(types) {
240 Ti::Array { base, .. } => TypeResolution::Handle(base),
244 Ti::Matrix { rows, width, .. } => TypeResolution::Value(Ti::Vector {
245 size: rows,
246 kind: crate::ScalarKind::Float,
247 width,
248 }),
249 Ti::Vector {
250 size: _,
251 kind,
252 width,
253 } => TypeResolution::Value(Ti::Scalar { kind, width }),
254 Ti::ValuePointer {
255 size: Some(_),
256 kind,
257 width,
258 space,
259 } => TypeResolution::Value(Ti::ValuePointer {
260 size: None,
261 kind,
262 width,
263 space,
264 }),
265 Ti::Pointer { base, space } => {
266 TypeResolution::Value(match types[base].inner {
267 Ti::Array { base, .. } => Ti::Pointer { base, space },
268 Ti::Vector {
269 size: _,
270 kind,
271 width,
272 } => Ti::ValuePointer {
273 size: None,
274 kind,
275 width,
276 space,
277 },
278 Ti::Matrix {
280 columns: _,
281 rows,
282 width,
283 } => Ti::ValuePointer {
284 kind: crate::ScalarKind::Float,
285 size: Some(rows),
286 width,
287 space,
288 },
289 Ti::BindingArray { base, .. } => Ti::Pointer { base, space },
290 ref other => {
291 log::error!("Access sub-type {:?}", other);
292 return Err(ResolveError::InvalidSubAccess {
293 ty: base,
294 indexed: false,
295 });
296 }
297 })
298 }
299 Ti::BindingArray { base, .. } => TypeResolution::Handle(base),
300 ref other => {
301 log::error!("Access type {:?}", other);
302 return Err(ResolveError::InvalidAccess {
303 expr: base,
304 indexed: false,
305 });
306 }
307 },
308 crate::Expression::AccessIndex { base, index } => {
309 match *past(base)?.inner_with(types) {
310 Ti::Vector { size, kind, width } => {
311 if index >= size as u32 {
312 return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
313 }
314 TypeResolution::Value(Ti::Scalar { kind, width })
315 }
316 Ti::Matrix {
317 columns,
318 rows,
319 width,
320 } => {
321 if index >= columns as u32 {
322 return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
323 }
324 TypeResolution::Value(crate::TypeInner::Vector {
325 size: rows,
326 kind: crate::ScalarKind::Float,
327 width,
328 })
329 }
330 Ti::Array { base, .. } => TypeResolution::Handle(base),
331 Ti::Struct { ref members, .. } => {
332 let member = members
333 .get(index as usize)
334 .ok_or(ResolveError::OutOfBoundsIndex { expr: base, index })?;
335 TypeResolution::Handle(member.ty)
336 }
337 Ti::ValuePointer {
338 size: Some(size),
339 kind,
340 width,
341 space,
342 } => {
343 if index >= size as u32 {
344 return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
345 }
346 TypeResolution::Value(Ti::ValuePointer {
347 size: None,
348 kind,
349 width,
350 space,
351 })
352 }
353 Ti::Pointer {
354 base: ty_base,
355 space,
356 } => TypeResolution::Value(match types[ty_base].inner {
357 Ti::Array { base, .. } => Ti::Pointer { base, space },
358 Ti::Vector { size, kind, width } => {
359 if index >= size as u32 {
360 return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
361 }
362 Ti::ValuePointer {
363 size: None,
364 kind,
365 width,
366 space,
367 }
368 }
369 Ti::Matrix {
370 rows,
371 columns,
372 width,
373 } => {
374 if index >= columns as u32 {
375 return Err(ResolveError::OutOfBoundsIndex { expr: base, index });
376 }
377 Ti::ValuePointer {
378 size: Some(rows),
379 kind: crate::ScalarKind::Float,
380 width,
381 space,
382 }
383 }
384 Ti::Struct { ref members, .. } => {
385 let member = members
386 .get(index as usize)
387 .ok_or(ResolveError::OutOfBoundsIndex { expr: base, index })?;
388 Ti::Pointer {
389 base: member.ty,
390 space,
391 }
392 }
393 Ti::BindingArray { base, .. } => Ti::Pointer { base, space },
394 ref other => {
395 log::error!("Access index sub-type {:?}", other);
396 return Err(ResolveError::InvalidSubAccess {
397 ty: ty_base,
398 indexed: true,
399 });
400 }
401 }),
402 Ti::BindingArray { base, .. } => TypeResolution::Handle(base),
403 ref other => {
404 log::error!("Access index type {:?}", other);
405 return Err(ResolveError::InvalidAccess {
406 expr: base,
407 indexed: true,
408 });
409 }
410 }
411 }
412 crate::Expression::Splat { size, value } => match *past(value)?.inner_with(types) {
413 Ti::Scalar { kind, width } => {
414 TypeResolution::Value(Ti::Vector { size, kind, width })
415 }
416 ref other => {
417 log::error!("Scalar type {:?}", other);
418 return Err(ResolveError::InvalidScalar(value));
419 }
420 },
421 crate::Expression::Swizzle {
422 size,
423 vector,
424 pattern: _,
425 } => match *past(vector)?.inner_with(types) {
426 Ti::Vector {
427 size: _,
428 kind,
429 width,
430 } => TypeResolution::Value(Ti::Vector { size, kind, width }),
431 ref other => {
432 log::error!("Vector type {:?}", other);
433 return Err(ResolveError::InvalidVector(vector));
434 }
435 },
436 crate::Expression::Literal(lit) => TypeResolution::Value(lit.ty_inner()),
437 crate::Expression::Constant(h) => TypeResolution::Handle(self.constants[h].ty),
438 crate::Expression::ZeroValue(ty) => TypeResolution::Handle(ty),
439 crate::Expression::Compose { ty, .. } => TypeResolution::Handle(ty),
440 crate::Expression::FunctionArgument(index) => {
441 let arg = self
442 .arguments
443 .get(index as usize)
444 .ok_or(ResolveError::FunctionArgumentNotFound(index))?;
445 TypeResolution::Handle(arg.ty)
446 }
447 crate::Expression::GlobalVariable(h) => {
448 let var = &self.global_vars[h];
449 if var.space == crate::AddressSpace::Handle {
450 TypeResolution::Handle(var.ty)
451 } else {
452 TypeResolution::Value(Ti::Pointer {
453 base: var.ty,
454 space: var.space,
455 })
456 }
457 }
458 crate::Expression::LocalVariable(h) => {
459 let var = &self.local_vars[h];
460 TypeResolution::Value(Ti::Pointer {
461 base: var.ty,
462 space: crate::AddressSpace::Function,
463 })
464 }
465 crate::Expression::Load { pointer } => match *past(pointer)?.inner_with(types) {
466 Ti::Pointer { base, space: _ } => {
467 if let Ti::Atomic { kind, width } = types[base].inner {
468 TypeResolution::Value(Ti::Scalar { kind, width })
469 } else {
470 TypeResolution::Handle(base)
471 }
472 }
473 Ti::ValuePointer {
474 size,
475 kind,
476 width,
477 space: _,
478 } => TypeResolution::Value(match size {
479 Some(size) => Ti::Vector { size, kind, width },
480 None => Ti::Scalar { kind, width },
481 }),
482 ref other => {
483 log::error!("Pointer type {:?}", other);
484 return Err(ResolveError::InvalidPointer(pointer));
485 }
486 },
487 crate::Expression::ImageSample {
488 image,
489 gather: Some(_),
490 ..
491 } => match *past(image)?.inner_with(types) {
492 Ti::Image { class, .. } => TypeResolution::Value(Ti::Vector {
493 kind: match class {
494 crate::ImageClass::Sampled { kind, multi: _ } => kind,
495 _ => crate::ScalarKind::Float,
496 },
497 width: 4,
498 size: crate::VectorSize::Quad,
499 }),
500 ref other => {
501 log::error!("Image type {:?}", other);
502 return Err(ResolveError::InvalidImage(image));
503 }
504 },
505 crate::Expression::ImageSample { image, .. }
506 | crate::Expression::ImageLoad { image, .. } => match *past(image)?.inner_with(types) {
507 Ti::Image { class, .. } => TypeResolution::Value(match class {
508 crate::ImageClass::Depth { multi: _ } => Ti::Scalar {
509 kind: crate::ScalarKind::Float,
510 width: 4,
511 },
512 crate::ImageClass::Sampled { kind, multi: _ } => Ti::Vector {
513 kind,
514 width: 4,
515 size: crate::VectorSize::Quad,
516 },
517 crate::ImageClass::Storage { format, .. } => Ti::Vector {
518 kind: format.into(),
519 width: 4,
520 size: crate::VectorSize::Quad,
521 },
522 }),
523 ref other => {
524 log::error!("Image type {:?}", other);
525 return Err(ResolveError::InvalidImage(image));
526 }
527 },
528 crate::Expression::ImageQuery { image, query } => TypeResolution::Value(match query {
529 crate::ImageQuery::Size { level: _ } => match *past(image)?.inner_with(types) {
530 Ti::Image { dim, .. } => match dim {
531 crate::ImageDimension::D1 => Ti::Scalar {
532 kind: crate::ScalarKind::Uint,
533 width: 4,
534 },
535 crate::ImageDimension::D2 | crate::ImageDimension::Cube => Ti::Vector {
536 size: crate::VectorSize::Bi,
537 kind: crate::ScalarKind::Uint,
538 width: 4,
539 },
540 crate::ImageDimension::D3 => Ti::Vector {
541 size: crate::VectorSize::Tri,
542 kind: crate::ScalarKind::Uint,
543 width: 4,
544 },
545 },
546 ref other => {
547 log::error!("Image type {:?}", other);
548 return Err(ResolveError::InvalidImage(image));
549 }
550 },
551 crate::ImageQuery::NumLevels
552 | crate::ImageQuery::NumLayers
553 | crate::ImageQuery::NumSamples => Ti::Scalar {
554 kind: crate::ScalarKind::Uint,
555 width: 4,
556 },
557 }),
558 crate::Expression::Unary { expr, .. } => past(expr)?.clone(),
559 crate::Expression::Binary { op, left, right } => match op {
560 crate::BinaryOperator::Add
561 | crate::BinaryOperator::Subtract
562 | crate::BinaryOperator::Divide
563 | crate::BinaryOperator::Modulo => past(left)?.clone(),
564 crate::BinaryOperator::Multiply => {
565 let (res_left, res_right) = (past(left)?, past(right)?);
566 match (res_left.inner_with(types), res_right.inner_with(types)) {
567 (
568 &Ti::Matrix {
569 columns: _,
570 rows,
571 width,
572 },
573 &Ti::Matrix { columns, .. },
574 ) => TypeResolution::Value(Ti::Matrix {
575 columns,
576 rows,
577 width,
578 }),
579 (
580 &Ti::Matrix {
581 columns: _,
582 rows,
583 width,
584 },
585 &Ti::Vector { .. },
586 ) => TypeResolution::Value(Ti::Vector {
587 size: rows,
588 kind: crate::ScalarKind::Float,
589 width,
590 }),
591 (
592 &Ti::Vector { .. },
593 &Ti::Matrix {
594 columns,
595 rows: _,
596 width,
597 },
598 ) => TypeResolution::Value(Ti::Vector {
599 size: columns,
600 kind: crate::ScalarKind::Float,
601 width,
602 }),
603 (&Ti::Scalar { .. }, _) => res_right.clone(),
604 (_, &Ti::Scalar { .. }) => res_left.clone(),
605 (&Ti::Vector { .. }, &Ti::Vector { .. }) => res_left.clone(),
606 (tl, tr) => {
607 return Err(ResolveError::IncompatibleOperands(format!(
608 "{tl:?} * {tr:?}"
609 )))
610 }
611 }
612 }
613 crate::BinaryOperator::Equal
614 | crate::BinaryOperator::NotEqual
615 | crate::BinaryOperator::Less
616 | crate::BinaryOperator::LessEqual
617 | crate::BinaryOperator::Greater
618 | crate::BinaryOperator::GreaterEqual
619 | crate::BinaryOperator::LogicalAnd
620 | crate::BinaryOperator::LogicalOr => {
621 let kind = crate::ScalarKind::Bool;
622 let width = crate::BOOL_WIDTH;
623 let inner = match *past(left)?.inner_with(types) {
624 Ti::Scalar { .. } => Ti::Scalar { kind, width },
625 Ti::Vector { size, .. } => Ti::Vector { size, kind, width },
626 ref other => {
627 return Err(ResolveError::IncompatibleOperands(format!(
628 "{op:?}({other:?}, _)"
629 )))
630 }
631 };
632 TypeResolution::Value(inner)
633 }
634 crate::BinaryOperator::And
635 | crate::BinaryOperator::ExclusiveOr
636 | crate::BinaryOperator::InclusiveOr
637 | crate::BinaryOperator::ShiftLeft
638 | crate::BinaryOperator::ShiftRight => past(left)?.clone(),
639 },
640 crate::Expression::AtomicResult { ty, .. } => TypeResolution::Handle(ty),
641 crate::Expression::WorkGroupUniformLoadResult { ty } => TypeResolution::Handle(ty),
642 crate::Expression::Select { accept, .. } => past(accept)?.clone(),
643 crate::Expression::Derivative { expr, .. } => past(expr)?.clone(),
644 crate::Expression::Relational { fun, argument } => match fun {
645 crate::RelationalFunction::All | crate::RelationalFunction::Any => {
646 TypeResolution::Value(Ti::Scalar {
647 kind: crate::ScalarKind::Bool,
648 width: crate::BOOL_WIDTH,
649 })
650 }
651 crate::RelationalFunction::IsNan
652 | crate::RelationalFunction::IsInf
653 | crate::RelationalFunction::IsFinite
654 | crate::RelationalFunction::IsNormal => match *past(argument)?.inner_with(types) {
655 Ti::Scalar { .. } => TypeResolution::Value(Ti::Scalar {
656 kind: crate::ScalarKind::Bool,
657 width: crate::BOOL_WIDTH,
658 }),
659 Ti::Vector { size, .. } => TypeResolution::Value(Ti::Vector {
660 kind: crate::ScalarKind::Bool,
661 width: crate::BOOL_WIDTH,
662 size,
663 }),
664 ref other => {
665 return Err(ResolveError::IncompatibleOperands(format!(
666 "{fun:?}({other:?})"
667 )))
668 }
669 },
670 },
671 crate::Expression::Math {
672 fun,
673 arg,
674 arg1,
675 arg2: _,
676 arg3: _,
677 } => {
678 use crate::MathFunction as Mf;
679 let res_arg = past(arg)?;
680 match fun {
681 Mf::Abs |
683 Mf::Min |
684 Mf::Max |
685 Mf::Clamp |
686 Mf::Saturate |
687 Mf::Cos |
689 Mf::Cosh |
690 Mf::Sin |
691 Mf::Sinh |
692 Mf::Tan |
693 Mf::Tanh |
694 Mf::Acos |
695 Mf::Asin |
696 Mf::Atan |
697 Mf::Atan2 |
698 Mf::Asinh |
699 Mf::Acosh |
700 Mf::Atanh |
701 Mf::Radians |
702 Mf::Degrees |
703 Mf::Ceil |
705 Mf::Floor |
706 Mf::Round |
707 Mf::Fract |
708 Mf::Trunc |
709 Mf::Modf |
710 Mf::Frexp |
711 Mf::Ldexp |
712 Mf::Exp |
714 Mf::Exp2 |
715 Mf::Log |
716 Mf::Log2 |
717 Mf::Pow => res_arg.clone(),
718 Mf::Dot => match *res_arg.inner_with(types) {
720 Ti::Vector {
721 kind,
722 size: _,
723 width,
724 } => TypeResolution::Value(Ti::Scalar { kind, width }),
725 ref other =>
726 return Err(ResolveError::IncompatibleOperands(
727 format!("{fun:?}({other:?}, _)")
728 )),
729 },
730 Mf::Outer => {
731 let arg1 = arg1.ok_or_else(|| ResolveError::IncompatibleOperands(
732 format!("{fun:?}(_, None)")
733 ))?;
734 match (res_arg.inner_with(types), past(arg1)?.inner_with(types)) {
735 (&Ti::Vector {kind: _, size: columns,width}, &Ti::Vector{ size: rows, .. }) => TypeResolution::Value(Ti::Matrix { columns, rows, width }),
736 (left, right) =>
737 return Err(ResolveError::IncompatibleOperands(
738 format!("{fun:?}({left:?}, {right:?})")
739 )),
740 }
741 },
742 Mf::Cross => res_arg.clone(),
743 Mf::Distance |
744 Mf::Length => match *res_arg.inner_with(types) {
745 Ti::Scalar {width,kind} |
746 Ti::Vector {width,kind,size:_} => TypeResolution::Value(Ti::Scalar { kind, width }),
747 ref other => return Err(ResolveError::IncompatibleOperands(
748 format!("{fun:?}({other:?})")
749 )),
750 },
751 Mf::Normalize |
752 Mf::FaceForward |
753 Mf::Reflect |
754 Mf::Refract => res_arg.clone(),
755 Mf::Sign |
757 Mf::Fma |
758 Mf::Mix |
759 Mf::Step |
760 Mf::SmoothStep |
761 Mf::Sqrt |
762 Mf::InverseSqrt => res_arg.clone(),
763 Mf::Transpose => match *res_arg.inner_with(types) {
764 Ti::Matrix {
765 columns,
766 rows,
767 width,
768 } => TypeResolution::Value(Ti::Matrix {
769 columns: rows,
770 rows: columns,
771 width,
772 }),
773 ref other => return Err(ResolveError::IncompatibleOperands(
774 format!("{fun:?}({other:?})")
775 )),
776 },
777 Mf::Inverse => match *res_arg.inner_with(types) {
778 Ti::Matrix {
779 columns,
780 rows,
781 width,
782 } if columns == rows => TypeResolution::Value(Ti::Matrix {
783 columns,
784 rows,
785 width,
786 }),
787 ref other => return Err(ResolveError::IncompatibleOperands(
788 format!("{fun:?}({other:?})")
789 )),
790 },
791 Mf::Determinant => match *res_arg.inner_with(types) {
792 Ti::Matrix {
793 width,
794 ..
795 } => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Float, width }),
796 ref other => return Err(ResolveError::IncompatibleOperands(
797 format!("{fun:?}({other:?})")
798 )),
799 },
800 Mf::CountTrailingZeros |
802 Mf::CountLeadingZeros |
803 Mf::CountOneBits |
804 Mf::ReverseBits |
805 Mf::ExtractBits |
806 Mf::InsertBits |
807 Mf::FindLsb |
808 Mf::FindMsb => match *res_arg.inner_with(types) {
809 Ti::Scalar { kind: kind @ (crate::ScalarKind::Sint | crate::ScalarKind::Uint), width } =>
810 TypeResolution::Value(Ti::Scalar { kind, width }),
811 Ti::Vector { size, kind: kind @ (crate::ScalarKind::Sint | crate::ScalarKind::Uint), width } =>
812 TypeResolution::Value(Ti::Vector { size, kind, width }),
813 ref other => return Err(ResolveError::IncompatibleOperands(
814 format!("{fun:?}({other:?})")
815 )),
816 },
817 Mf::Pack4x8snorm |
819 Mf::Pack4x8unorm |
820 Mf::Pack2x16snorm |
821 Mf::Pack2x16unorm |
822 Mf::Pack2x16float => TypeResolution::Value(Ti::Scalar { kind: crate::ScalarKind::Uint, width: 4 }),
823 Mf::Unpack4x8snorm |
825 Mf::Unpack4x8unorm => TypeResolution::Value(Ti::Vector { size: crate::VectorSize::Quad, kind: crate::ScalarKind::Float, width: 4 }),
826 Mf::Unpack2x16snorm |
827 Mf::Unpack2x16unorm |
828 Mf::Unpack2x16float => TypeResolution::Value(Ti::Vector { size: crate::VectorSize::Bi, kind: crate::ScalarKind::Float, width: 4 }),
829 }
830 }
831 crate::Expression::As {
832 expr,
833 kind,
834 convert,
835 } => match *past(expr)?.inner_with(types) {
836 Ti::Scalar { kind: _, width } => TypeResolution::Value(Ti::Scalar {
837 kind,
838 width: convert.unwrap_or(width),
839 }),
840 Ti::Vector {
841 kind: _,
842 size,
843 width,
844 } => TypeResolution::Value(Ti::Vector {
845 kind,
846 size,
847 width: convert.unwrap_or(width),
848 }),
849 Ti::Matrix {
850 columns,
851 rows,
852 width,
853 } => TypeResolution::Value(Ti::Matrix {
854 columns,
855 rows,
856 width: convert.unwrap_or(width),
857 }),
858 ref other => {
859 return Err(ResolveError::IncompatibleOperands(format!(
860 "{other:?} as {kind:?}"
861 )))
862 }
863 },
864 crate::Expression::CallResult(function) => {
865 let result = self.functions[function]
866 .result
867 .as_ref()
868 .ok_or(ResolveError::FunctionReturnsVoid)?;
869 TypeResolution::Handle(result.ty)
870 }
871 crate::Expression::ArrayLength(_) => TypeResolution::Value(Ti::Scalar {
872 kind: crate::ScalarKind::Uint,
873 width: 4,
874 }),
875 crate::Expression::RayQueryProceedResult => TypeResolution::Value(Ti::Scalar {
876 kind: crate::ScalarKind::Bool,
877 width: crate::BOOL_WIDTH,
878 }),
879 crate::Expression::RayQueryGetIntersection { .. } => {
880 let result = self
881 .special_types
882 .ray_intersection
883 .ok_or(ResolveError::MissingSpecialType)?;
884 TypeResolution::Handle(result)
885 }
886 })
887 }
888}
889
890#[test]
891fn test_error_size() {
892 use std::mem::size_of;
893 assert_eq!(size_of::<ResolveError>(), 32);
894}