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