1 #[cfg(feature = "validate")]
2 use super::{compose::validate_compose, FunctionInfo, ShaderStages, TypeFlags};
3 #[cfg(feature = "validate")]
4 use crate::arena::UniqueArena;
5 
6 use crate::{
7     arena::Handle,
8     proc::{ProcError, ResolveError},
9 };
10 
11 #[derive(Clone, Debug, thiserror::Error)]
12 #[cfg_attr(test, derive(PartialEq))]
13 pub enum ExpressionError {
14     #[error("Doesn't exist")]
15     DoesntExist,
16     #[error("Used by a statement before it was introduced into the scope by any of the dominating blocks")]
17     NotInScope,
18     #[error("Depends on {0:?}, which has not been processed yet")]
19     ForwardDependency(Handle<crate::Expression>),
20     #[error("Base type {0:?} is not compatible with this expression")]
21     InvalidBaseType(Handle<crate::Expression>),
22     #[error("Accessing with index {0:?} can't be done")]
23     InvalidIndexType(Handle<crate::Expression>),
24     #[error("Accessing index {1:?} is out of {0:?} bounds")]
25     IndexOutOfBounds(Handle<crate::Expression>, crate::ScalarValue),
26     #[error("The expression {0:?} may only be indexed by a constant")]
27     IndexMustBeConstant(Handle<crate::Expression>),
28     #[error("Function argument {0:?} doesn't exist")]
29     FunctionArgumentDoesntExist(u32),
30     #[error("Constant {0:?} doesn't exist")]
31     ConstantDoesntExist(Handle<crate::Constant>),
32     #[error("Global variable {0:?} doesn't exist")]
33     GlobalVarDoesntExist(Handle<crate::GlobalVariable>),
34     #[error("Local variable {0:?} doesn't exist")]
35     LocalVarDoesntExist(Handle<crate::LocalVariable>),
36     #[error("Loading of {0:?} can't be done")]
37     InvalidPointerType(Handle<crate::Expression>),
38     #[error("Array length of {0:?} can't be done")]
39     InvalidArrayType(Handle<crate::Expression>),
40     #[error("Splatting {0:?} can't be done")]
41     InvalidSplatType(Handle<crate::Expression>),
42     #[error("Swizzling {0:?} can't be done")]
43     InvalidVectorType(Handle<crate::Expression>),
44     #[error("Swizzle component {0:?} is outside of vector size {1:?}")]
45     InvalidSwizzleComponent(crate::SwizzleComponent, crate::VectorSize),
46     #[error(transparent)]
47     Compose(#[from] super::ComposeError),
48     #[error(transparent)]
49     Proc(#[from] ProcError),
50     #[error("Operation {0:?} can't work with {1:?}")]
51     InvalidUnaryOperandType(crate::UnaryOperator, Handle<crate::Expression>),
52     #[error("Operation {0:?} can't work with {1:?} and {2:?}")]
53     InvalidBinaryOperandTypes(
54         crate::BinaryOperator,
55         Handle<crate::Expression>,
56         Handle<crate::Expression>,
57     ),
58     #[error("Selecting is not possible")]
59     InvalidSelectTypes,
60     #[error("Relational argument {0:?} is not a boolean vector")]
61     InvalidBooleanVector(Handle<crate::Expression>),
62     #[error("Relational argument {0:?} is not a float")]
63     InvalidFloatArgument(Handle<crate::Expression>),
64     #[error("Type resolution failed")]
65     Type(#[from] ResolveError),
66     #[error("Not a global variable")]
67     ExpectedGlobalVariable,
68     #[error("Not a global variable or a function argument")]
69     ExpectedGlobalOrArgument,
70     #[error("Calling an undeclared function {0:?}")]
71     CallToUndeclaredFunction(Handle<crate::Function>),
72     #[error("Needs to be an image instead of {0:?}")]
73     ExpectedImageType(Handle<crate::Type>),
74     #[error("Needs to be an image instead of {0:?}")]
75     ExpectedSamplerType(Handle<crate::Type>),
76     #[error("Unable to operate on image class {0:?}")]
77     InvalidImageClass(crate::ImageClass),
78     #[error("Derivatives can only be taken from scalar and vector floats")]
79     InvalidDerivative,
80     #[error("Image array index parameter is misplaced")]
81     InvalidImageArrayIndex,
82     #[error("Image other index parameter is misplaced")]
83     InvalidImageOtherIndex,
84     #[error("Image array index type of {0:?} is not an integer scalar")]
85     InvalidImageArrayIndexType(Handle<crate::Expression>),
86     #[error("Image other index type of {0:?} is not an integer scalar")]
87     InvalidImageOtherIndexType(Handle<crate::Expression>),
88     #[error("Image coordinate type of {1:?} does not match dimension {0:?}")]
89     InvalidImageCoordinateType(crate::ImageDimension, Handle<crate::Expression>),
90     #[error("Comparison sampling mismatch: image has class {image:?}, but the sampler is comparison={sampler}, and the reference was provided={has_ref}")]
91     ComparisonSamplingMismatch {
92         image: crate::ImageClass,
93         sampler: bool,
94         has_ref: bool,
95     },
96     #[error("Sample offset constant {1:?} doesn't match the image dimension {0:?}")]
97     InvalidSampleOffset(crate::ImageDimension, Handle<crate::Constant>),
98     #[error("Depth reference {0:?} is not a scalar float")]
99     InvalidDepthReference(Handle<crate::Expression>),
100     #[error("Depth sample level can only be Auto or Zero")]
101     InvalidDepthSampleLevel,
102     #[error("Gather level can only be Zero")]
103     InvalidGatherLevel,
104     #[error("Gather component {0:?} doesn't exist in the image")]
105     InvalidGatherComponent(crate::SwizzleComponent),
106     #[error("Gather can't be done for image dimension {0:?}")]
107     InvalidGatherDimension(crate::ImageDimension),
108     #[error("Sample level (exact) type {0:?} is not a scalar float")]
109     InvalidSampleLevelExactType(Handle<crate::Expression>),
110     #[error("Sample level (bias) type {0:?} is not a scalar float")]
111     InvalidSampleLevelBiasType(Handle<crate::Expression>),
112     #[error("Sample level (gradient) of {1:?} doesn't match the image dimension {0:?}")]
113     InvalidSampleLevelGradientType(crate::ImageDimension, Handle<crate::Expression>),
114     #[error("Unable to cast")]
115     InvalidCastArgument,
116     #[error("Invalid argument count for {0:?}")]
117     WrongArgumentCount(crate::MathFunction),
118     #[error("Argument [{1}] to {0:?} as expression {2:?} has an invalid type.")]
119     InvalidArgumentType(crate::MathFunction, u32, Handle<crate::Expression>),
120     #[error("Atomic result type can't be {0:?} of {1} bytes")]
121     InvalidAtomicResultType(crate::ScalarKind, crate::Bytes),
122 }
123 
124 #[cfg(feature = "validate")]
125 struct ExpressionTypeResolver<'a> {
126     root: Handle<crate::Expression>,
127     types: &'a UniqueArena<crate::Type>,
128     info: &'a FunctionInfo,
129 }
130 
131 #[cfg(feature = "validate")]
132 impl<'a> ExpressionTypeResolver<'a> {
resolve( &self, handle: Handle<crate::Expression>, ) -> Result<&'a crate::TypeInner, ExpressionError>133     fn resolve(
134         &self,
135         handle: Handle<crate::Expression>,
136     ) -> Result<&'a crate::TypeInner, ExpressionError> {
137         if handle < self.root {
138             Ok(self.info[handle].ty.inner_with(self.types))
139         } else {
140             Err(ExpressionError::ForwardDependency(handle))
141         }
142     }
143 }
144 
145 #[cfg(feature = "validate")]
146 impl super::Validator {
validate_expression( &self, root: Handle<crate::Expression>, expression: &crate::Expression, function: &crate::Function, module: &crate::Module, info: &FunctionInfo, other_infos: &[FunctionInfo], ) -> Result<ShaderStages, ExpressionError>147     pub(super) fn validate_expression(
148         &self,
149         root: Handle<crate::Expression>,
150         expression: &crate::Expression,
151         function: &crate::Function,
152         module: &crate::Module,
153         info: &FunctionInfo,
154         other_infos: &[FunctionInfo],
155     ) -> Result<ShaderStages, ExpressionError> {
156         use crate::{Expression as E, ScalarKind as Sk, TypeInner as Ti};
157 
158         let resolver = ExpressionTypeResolver {
159             root,
160             types: &module.types,
161             info,
162         };
163 
164         let stages = match *expression {
165             E::Access { base, index } => {
166                 let base_type = resolver.resolve(base)?;
167                 // See the documentation for `Expression::Access`.
168                 let dynamic_indexing_restricted = match *base_type {
169                     Ti::Vector { .. } => false,
170                     Ti::Matrix { .. } | Ti::Array { .. } => true,
171                     Ti::Pointer { .. } | Ti::ValuePointer { size: Some(_), .. } => false,
172                     ref other => {
173                         log::error!("Indexing of {:?}", other);
174                         return Err(ExpressionError::InvalidBaseType(base));
175                     }
176                 };
177                 match *resolver.resolve(index)? {
178                     //TODO: only allow one of these
179                     Ti::Scalar {
180                         kind: Sk::Sint,
181                         width: _,
182                     }
183                     | Ti::Scalar {
184                         kind: Sk::Uint,
185                         width: _,
186                     } => {}
187                     ref other => {
188                         log::error!("Indexing by {:?}", other);
189                         return Err(ExpressionError::InvalidIndexType(index));
190                     }
191                 }
192                 if dynamic_indexing_restricted
193                     && function.expressions[index].is_dynamic_index(module)
194                 {
195                     return Err(ExpressionError::IndexMustBeConstant(base));
196                 }
197 
198                 // If we know both the length and the index, we can do the
199                 // bounds check now.
200                 if let crate::proc::IndexableLength::Known(known_length) =
201                     base_type.indexable_length(module)?
202                 {
203                     if let E::Constant(k) = function.expressions[index] {
204                         if let crate::Constant {
205                             // We must treat specializable constants as unknown.
206                             specialization: None,
207                             // Non-scalar indices should have been caught above.
208                             inner: crate::ConstantInner::Scalar { value, .. },
209                             ..
210                         } = module.constants[k]
211                         {
212                             match value {
213                                 crate::ScalarValue::Uint(u) if u >= known_length as u64 => {
214                                     return Err(ExpressionError::IndexOutOfBounds(base, value));
215                                 }
216                                 crate::ScalarValue::Sint(s)
217                                     if s < 0 || s >= known_length as i64 =>
218                                 {
219                                     return Err(ExpressionError::IndexOutOfBounds(base, value));
220                                 }
221                                 _ => (),
222                             }
223                         }
224                     }
225                 }
226 
227                 ShaderStages::all()
228             }
229             E::AccessIndex { base, index } => {
230                 fn resolve_index_limit(
231                     module: &crate::Module,
232                     top: Handle<crate::Expression>,
233                     ty: &crate::TypeInner,
234                     top_level: bool,
235                 ) -> Result<u32, ExpressionError> {
236                     let limit = match *ty {
237                         Ti::Vector { size, .. }
238                         | Ti::ValuePointer {
239                             size: Some(size), ..
240                         } => size as u32,
241                         Ti::Matrix { columns, .. } => columns as u32,
242                         Ti::Array {
243                             size: crate::ArraySize::Constant(handle),
244                             ..
245                         } => module.constants[handle].to_array_length().unwrap(),
246                         Ti::Array { .. } => !0, // can't statically know, but need run-time checks
247                         Ti::Pointer { base, .. } if top_level => {
248                             resolve_index_limit(module, top, &module.types[base].inner, false)?
249                         }
250                         Ti::Struct { ref members, .. } => members.len() as u32,
251                         ref other => {
252                             log::error!("Indexing of {:?}", other);
253                             return Err(ExpressionError::InvalidBaseType(top));
254                         }
255                     };
256                     Ok(limit)
257                 }
258 
259                 let limit = resolve_index_limit(module, base, resolver.resolve(base)?, true)?;
260                 if index >= limit {
261                     return Err(ExpressionError::IndexOutOfBounds(
262                         base,
263                         crate::ScalarValue::Uint(limit as _),
264                     ));
265                 }
266                 ShaderStages::all()
267             }
268             E::Constant(handle) => {
269                 let _ = module
270                     .constants
271                     .try_get(handle)
272                     .ok_or(ExpressionError::ConstantDoesntExist(handle))?;
273                 ShaderStages::all()
274             }
275             E::Splat { size: _, value } => match *resolver.resolve(value)? {
276                 Ti::Scalar { .. } => ShaderStages::all(),
277                 ref other => {
278                     log::error!("Splat scalar type {:?}", other);
279                     return Err(ExpressionError::InvalidSplatType(value));
280                 }
281             },
282             E::Swizzle {
283                 size,
284                 vector,
285                 pattern,
286             } => {
287                 let vec_size = match *resolver.resolve(vector)? {
288                     Ti::Vector { size: vec_size, .. } => vec_size,
289                     ref other => {
290                         log::error!("Swizzle vector type {:?}", other);
291                         return Err(ExpressionError::InvalidVectorType(vector));
292                     }
293                 };
294                 for &sc in pattern[..size as usize].iter() {
295                     if sc as u8 >= vec_size as u8 {
296                         return Err(ExpressionError::InvalidSwizzleComponent(sc, vec_size));
297                     }
298                 }
299                 ShaderStages::all()
300             }
301             E::Compose { ref components, ty } => {
302                 for &handle in components {
303                     if handle >= root {
304                         return Err(ExpressionError::ForwardDependency(handle));
305                     }
306                 }
307                 validate_compose(
308                     ty,
309                     &module.constants,
310                     &module.types,
311                     components.iter().map(|&handle| info[handle].ty.clone()),
312                 )?;
313                 ShaderStages::all()
314             }
315             E::FunctionArgument(index) => {
316                 if index >= function.arguments.len() as u32 {
317                     return Err(ExpressionError::FunctionArgumentDoesntExist(index));
318                 }
319                 ShaderStages::all()
320             }
321             E::GlobalVariable(handle) => {
322                 let _ = module
323                     .global_variables
324                     .try_get(handle)
325                     .ok_or(ExpressionError::GlobalVarDoesntExist(handle))?;
326                 ShaderStages::all()
327             }
328             E::LocalVariable(handle) => {
329                 let _ = function
330                     .local_variables
331                     .try_get(handle)
332                     .ok_or(ExpressionError::LocalVarDoesntExist(handle))?;
333                 ShaderStages::all()
334             }
335             E::Load { pointer } => {
336                 match *resolver.resolve(pointer)? {
337                     Ti::Pointer { base, .. }
338                         if self.types[base.index()]
339                             .flags
340                             .contains(TypeFlags::SIZED | TypeFlags::DATA) => {}
341                     Ti::ValuePointer { .. } => {}
342                     ref other => {
343                         log::error!("Loading {:?}", other);
344                         return Err(ExpressionError::InvalidPointerType(pointer));
345                     }
346                 }
347                 ShaderStages::all()
348             }
349             E::ImageSample {
350                 image,
351                 sampler,
352                 gather,
353                 coordinate,
354                 array_index,
355                 offset,
356                 level,
357                 depth_ref,
358             } => {
359                 // check the validity of expressions
360                 let image_ty = match function.expressions[image] {
361                     crate::Expression::GlobalVariable(var_handle) => {
362                         module.global_variables[var_handle].ty
363                     }
364                     crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
365                     _ => return Err(ExpressionError::ExpectedGlobalVariable),
366                 };
367                 let sampler_ty = match function.expressions[sampler] {
368                     crate::Expression::GlobalVariable(var_handle) => {
369                         module.global_variables[var_handle].ty
370                     }
371                     crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
372                     _ => return Err(ExpressionError::ExpectedGlobalVariable),
373                 };
374                 let comparison = match module.types[sampler_ty].inner {
375                     Ti::Sampler { comparison } => comparison,
376                     _ => return Err(ExpressionError::ExpectedSamplerType(sampler_ty)),
377                 };
378 
379                 let (class, dim) = match module.types[image_ty].inner {
380                     Ti::Image {
381                         class,
382                         arrayed,
383                         dim,
384                     } => {
385                         // check the array property
386                         if arrayed != array_index.is_some() {
387                             return Err(ExpressionError::InvalidImageArrayIndex);
388                         }
389                         if let Some(expr) = array_index {
390                             match *resolver.resolve(expr)? {
391                                 Ti::Scalar {
392                                     kind: Sk::Sint,
393                                     width: _,
394                                 } => {}
395                                 _ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
396                             }
397                         }
398                         (class, dim)
399                     }
400                     _ => return Err(ExpressionError::ExpectedImageType(image_ty)),
401                 };
402 
403                 // check sampling and comparison properties
404                 let image_depth = match class {
405                     crate::ImageClass::Sampled {
406                         kind: crate::ScalarKind::Float,
407                         multi: false,
408                     } => false,
409                     crate::ImageClass::Depth { multi: false } => true,
410                     _ => return Err(ExpressionError::InvalidImageClass(class)),
411                 };
412                 if comparison != depth_ref.is_some() || (comparison && !image_depth) {
413                     return Err(ExpressionError::ComparisonSamplingMismatch {
414                         image: class,
415                         sampler: comparison,
416                         has_ref: depth_ref.is_some(),
417                     });
418                 }
419 
420                 // check texture coordinates type
421                 let num_components = match dim {
422                     crate::ImageDimension::D1 => 1,
423                     crate::ImageDimension::D2 => 2,
424                     crate::ImageDimension::D3 | crate::ImageDimension::Cube => 3,
425                 };
426                 match *resolver.resolve(coordinate)? {
427                     Ti::Scalar {
428                         kind: Sk::Float, ..
429                     } if num_components == 1 => {}
430                     Ti::Vector {
431                         size,
432                         kind: Sk::Float,
433                         ..
434                     } if size as u32 == num_components => {}
435                     _ => return Err(ExpressionError::InvalidImageCoordinateType(dim, coordinate)),
436                 }
437 
438                 // check constant offset
439                 if let Some(const_handle) = offset {
440                     let good = match module.constants[const_handle].inner {
441                         crate::ConstantInner::Scalar {
442                             width: _,
443                             value: crate::ScalarValue::Sint(_),
444                         } => num_components == 1,
445                         crate::ConstantInner::Scalar { .. } => false,
446                         crate::ConstantInner::Composite { ty, .. } => {
447                             match module.types[ty].inner {
448                                 Ti::Vector {
449                                     size,
450                                     kind: Sk::Sint,
451                                     ..
452                                 } => size as u32 == num_components,
453                                 _ => false,
454                             }
455                         }
456                     };
457                     if !good {
458                         return Err(ExpressionError::InvalidSampleOffset(dim, const_handle));
459                     }
460                 }
461 
462                 // check depth reference type
463                 if let Some(expr) = depth_ref {
464                     match *resolver.resolve(expr)? {
465                         Ti::Scalar {
466                             kind: Sk::Float, ..
467                         } => {}
468                         _ => return Err(ExpressionError::InvalidDepthReference(expr)),
469                     }
470                     match level {
471                         crate::SampleLevel::Auto | crate::SampleLevel::Zero => {}
472                         _ => return Err(ExpressionError::InvalidDepthSampleLevel),
473                     }
474                 }
475 
476                 if let Some(component) = gather {
477                     match dim {
478                         crate::ImageDimension::D2 | crate::ImageDimension::Cube => {}
479                         crate::ImageDimension::D1 | crate::ImageDimension::D3 => {
480                             return Err(ExpressionError::InvalidGatherDimension(dim))
481                         }
482                     };
483                     let max_component = match class {
484                         crate::ImageClass::Depth { .. } => crate::SwizzleComponent::X,
485                         _ => crate::SwizzleComponent::W,
486                     };
487                     if component > max_component {
488                         return Err(ExpressionError::InvalidGatherComponent(component));
489                     }
490                     match level {
491                         crate::SampleLevel::Zero => {}
492                         _ => return Err(ExpressionError::InvalidGatherLevel),
493                     }
494                 }
495 
496                 // check level properties
497                 match level {
498                     crate::SampleLevel::Auto => ShaderStages::FRAGMENT,
499                     crate::SampleLevel::Zero => ShaderStages::all(),
500                     crate::SampleLevel::Exact(expr) => {
501                         match *resolver.resolve(expr)? {
502                             Ti::Scalar {
503                                 kind: Sk::Float, ..
504                             } => {}
505                             _ => return Err(ExpressionError::InvalidSampleLevelExactType(expr)),
506                         }
507                         ShaderStages::all()
508                     }
509                     crate::SampleLevel::Bias(expr) => {
510                         match *resolver.resolve(expr)? {
511                             Ti::Scalar {
512                                 kind: Sk::Float, ..
513                             } => {}
514                             _ => return Err(ExpressionError::InvalidSampleLevelBiasType(expr)),
515                         }
516                         ShaderStages::all()
517                     }
518                     crate::SampleLevel::Gradient { x, y } => {
519                         match *resolver.resolve(x)? {
520                             Ti::Scalar {
521                                 kind: Sk::Float, ..
522                             } if num_components == 1 => {}
523                             Ti::Vector {
524                                 size,
525                                 kind: Sk::Float,
526                                 ..
527                             } if size as u32 == num_components => {}
528                             _ => {
529                                 return Err(ExpressionError::InvalidSampleLevelGradientType(dim, x))
530                             }
531                         }
532                         match *resolver.resolve(y)? {
533                             Ti::Scalar {
534                                 kind: Sk::Float, ..
535                             } if num_components == 1 => {}
536                             Ti::Vector {
537                                 size,
538                                 kind: Sk::Float,
539                                 ..
540                             } if size as u32 == num_components => {}
541                             _ => {
542                                 return Err(ExpressionError::InvalidSampleLevelGradientType(dim, y))
543                             }
544                         }
545                         ShaderStages::all()
546                     }
547                 }
548             }
549             E::ImageLoad {
550                 image,
551                 coordinate,
552                 array_index,
553                 index,
554             } => {
555                 let ty = match function.expressions[image] {
556                     crate::Expression::GlobalVariable(var_handle) => {
557                         module.global_variables[var_handle].ty
558                     }
559                     crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
560                     _ => return Err(ExpressionError::ExpectedGlobalVariable),
561                 };
562                 match module.types[ty].inner {
563                     Ti::Image {
564                         class,
565                         arrayed,
566                         dim,
567                     } => {
568                         match resolver.resolve(coordinate)?.image_storage_coordinates() {
569                             Some(coord_dim) if coord_dim == dim => {}
570                             _ => {
571                                 return Err(ExpressionError::InvalidImageCoordinateType(
572                                     dim, coordinate,
573                                 ))
574                             }
575                         };
576                         let needs_index = match class {
577                             crate::ImageClass::Storage { .. } => false,
578                             _ => true,
579                         };
580                         if arrayed != array_index.is_some() {
581                             return Err(ExpressionError::InvalidImageArrayIndex);
582                         }
583                         if needs_index != index.is_some() {
584                             return Err(ExpressionError::InvalidImageOtherIndex);
585                         }
586                         if let Some(expr) = array_index {
587                             match *resolver.resolve(expr)? {
588                                 Ti::Scalar {
589                                     kind: Sk::Sint,
590                                     width: _,
591                                 } => {}
592                                 _ => return Err(ExpressionError::InvalidImageArrayIndexType(expr)),
593                             }
594                         }
595                         if let Some(expr) = index {
596                             match *resolver.resolve(expr)? {
597                                 Ti::Scalar {
598                                     kind: Sk::Sint,
599                                     width: _,
600                                 } => {}
601                                 _ => return Err(ExpressionError::InvalidImageOtherIndexType(expr)),
602                             }
603                         }
604                     }
605                     _ => return Err(ExpressionError::ExpectedImageType(ty)),
606                 }
607                 ShaderStages::all()
608             }
609             E::ImageQuery { image, query } => {
610                 let ty = match function.expressions[image] {
611                     crate::Expression::GlobalVariable(var_handle) => {
612                         module.global_variables[var_handle].ty
613                     }
614                     crate::Expression::FunctionArgument(i) => function.arguments[i as usize].ty,
615                     _ => return Err(ExpressionError::ExpectedGlobalVariable),
616                 };
617                 match module.types[ty].inner {
618                     Ti::Image { class, arrayed, .. } => {
619                         let can_level = match class {
620                             crate::ImageClass::Sampled { multi, .. } => !multi,
621                             crate::ImageClass::Depth { multi } => !multi,
622                             crate::ImageClass::Storage { .. } => false,
623                         };
624                         let good = match query {
625                             crate::ImageQuery::NumLayers => arrayed,
626                             crate::ImageQuery::Size { level: None } => true,
627                             crate::ImageQuery::Size { level: Some(_) }
628                             | crate::ImageQuery::NumLevels => can_level,
629                             //TODO: forbid on storage images
630                             crate::ImageQuery::NumSamples => !can_level,
631                         };
632                         if !good {
633                             return Err(ExpressionError::InvalidImageClass(class));
634                         }
635                     }
636                     _ => return Err(ExpressionError::ExpectedImageType(ty)),
637                 }
638                 ShaderStages::all()
639             }
640             E::Unary { op, expr } => {
641                 use crate::UnaryOperator as Uo;
642                 let inner = resolver.resolve(expr)?;
643                 match (op, inner.scalar_kind()) {
644                     (_, Some(Sk::Sint))
645                     | (_, Some(Sk::Bool))
646                     //TODO: restrict Negate for bools?
647                     | (Uo::Negate, Some(Sk::Float))
648                     | (Uo::Not, Some(Sk::Uint)) => {}
649                     other => {
650                         log::error!("Op {:?} kind {:?}", op, other);
651                         return Err(ExpressionError::InvalidUnaryOperandType(op, expr));
652                     }
653                 }
654                 ShaderStages::all()
655             }
656             E::Binary { op, left, right } => {
657                 use crate::BinaryOperator as Bo;
658                 let left_inner = resolver.resolve(left)?;
659                 let right_inner = resolver.resolve(right)?;
660                 let good = match op {
661                     Bo::Add | Bo::Subtract => match *left_inner {
662                         Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
663                             Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
664                             Sk::Bool => false,
665                         },
666                         Ti::Matrix { .. } => left_inner == right_inner,
667                         _ => false,
668                     },
669                     Bo::Divide | Bo::Modulo => match *left_inner {
670                         Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
671                             Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
672                             Sk::Bool => false,
673                         },
674                         _ => false,
675                     },
676                     Bo::Multiply => {
677                         let kind_match = match left_inner.scalar_kind() {
678                             Some(Sk::Uint) | Some(Sk::Sint) | Some(Sk::Float) => true,
679                             Some(Sk::Bool) | None => false,
680                         };
681                         //TODO: should we be more restrictive here? I.e. expect scalar only to the left.
682                         let types_match = match (left_inner, right_inner) {
683                             (&Ti::Scalar { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. })
684                             | (&Ti::Vector { kind: kind1, .. }, &Ti::Scalar { kind: kind2, .. })
685                             | (&Ti::Scalar { kind: kind1, .. }, &Ti::Vector { kind: kind2, .. }) => {
686                                 kind1 == kind2
687                             }
688                             (
689                                 &Ti::Scalar {
690                                     kind: Sk::Float, ..
691                                 },
692                                 &Ti::Matrix { .. },
693                             )
694                             | (
695                                 &Ti::Matrix { .. },
696                                 &Ti::Scalar {
697                                     kind: Sk::Float, ..
698                                 },
699                             ) => true,
700                             (
701                                 &Ti::Vector {
702                                     kind: kind1,
703                                     size: size1,
704                                     ..
705                                 },
706                                 &Ti::Vector {
707                                     kind: kind2,
708                                     size: size2,
709                                     ..
710                                 },
711                             ) => kind1 == kind2 && size1 == size2,
712                             (
713                                 &Ti::Matrix { columns, .. },
714                                 &Ti::Vector {
715                                     kind: Sk::Float,
716                                     size,
717                                     ..
718                                 },
719                             ) => columns == size,
720                             (
721                                 &Ti::Vector {
722                                     kind: Sk::Float,
723                                     size,
724                                     ..
725                                 },
726                                 &Ti::Matrix { rows, .. },
727                             ) => size == rows,
728                             (&Ti::Matrix { columns, .. }, &Ti::Matrix { rows, .. }) => {
729                                 columns == rows
730                             }
731                             _ => false,
732                         };
733                         let left_width = match *left_inner {
734                             Ti::Scalar { width, .. }
735                             | Ti::Vector { width, .. }
736                             | Ti::Matrix { width, .. } => width,
737                             _ => 0,
738                         };
739                         let right_width = match *right_inner {
740                             Ti::Scalar { width, .. }
741                             | Ti::Vector { width, .. }
742                             | Ti::Matrix { width, .. } => width,
743                             _ => 0,
744                         };
745                         kind_match && types_match && left_width == right_width
746                     }
747                     Bo::Equal | Bo::NotEqual => left_inner.is_sized() && left_inner == right_inner,
748                     Bo::Less | Bo::LessEqual | Bo::Greater | Bo::GreaterEqual => {
749                         match *left_inner {
750                             Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
751                                 Sk::Uint | Sk::Sint | Sk::Float => left_inner == right_inner,
752                                 Sk::Bool => false,
753                             },
754                             ref other => {
755                                 log::error!("Op {:?} left type {:?}", op, other);
756                                 false
757                             }
758                         }
759                     }
760                     Bo::LogicalAnd | Bo::LogicalOr => match *left_inner {
761                         Ti::Scalar { kind: Sk::Bool, .. } | Ti::Vector { kind: Sk::Bool, .. } => {
762                             left_inner == right_inner
763                         }
764                         ref other => {
765                             log::error!("Op {:?} left type {:?}", op, other);
766                             false
767                         }
768                     },
769                     Bo::And | Bo::InclusiveOr => match *left_inner {
770                         Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
771                             Sk::Bool | Sk::Sint | Sk::Uint => left_inner == right_inner,
772                             Sk::Float => false,
773                         },
774                         ref other => {
775                             log::error!("Op {:?} left type {:?}", op, other);
776                             false
777                         }
778                     },
779                     Bo::ExclusiveOr => match *left_inner {
780                         Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => match kind {
781                             Sk::Sint | Sk::Uint => left_inner == right_inner,
782                             Sk::Bool | Sk::Float => false,
783                         },
784                         ref other => {
785                             log::error!("Op {:?} left type {:?}", op, other);
786                             false
787                         }
788                     },
789                     Bo::ShiftLeft | Bo::ShiftRight => {
790                         let (base_size, base_kind) = match *left_inner {
791                             Ti::Scalar { kind, .. } => (Ok(None), kind),
792                             Ti::Vector { size, kind, .. } => (Ok(Some(size)), kind),
793                             ref other => {
794                                 log::error!("Op {:?} base type {:?}", op, other);
795                                 (Err(()), Sk::Bool)
796                             }
797                         };
798                         let shift_size = match *right_inner {
799                             Ti::Scalar { kind: Sk::Uint, .. } => Ok(None),
800                             Ti::Vector {
801                                 size,
802                                 kind: Sk::Uint,
803                                 ..
804                             } => Ok(Some(size)),
805                             ref other => {
806                                 log::error!("Op {:?} shift type {:?}", op, other);
807                                 Err(())
808                             }
809                         };
810                         match base_kind {
811                             Sk::Sint | Sk::Uint => base_size.is_ok() && base_size == shift_size,
812                             Sk::Float | Sk::Bool => false,
813                         }
814                     }
815                 };
816                 if !good {
817                     log::error!(
818                         "Left: {:?} of type {:?}",
819                         function.expressions[left],
820                         left_inner
821                     );
822                     log::error!(
823                         "Right: {:?} of type {:?}",
824                         function.expressions[right],
825                         right_inner
826                     );
827                     return Err(ExpressionError::InvalidBinaryOperandTypes(op, left, right));
828                 }
829                 ShaderStages::all()
830             }
831             E::Select {
832                 condition,
833                 accept,
834                 reject,
835             } => {
836                 let accept_inner = resolver.resolve(accept)?;
837                 let reject_inner = resolver.resolve(reject)?;
838                 let condition_good = match *resolver.resolve(condition)? {
839                     Ti::Scalar {
840                         kind: Sk::Bool,
841                         width: _,
842                     } => {
843                         // When `condition` is a single boolean, `accept` and
844                         // `reject` can be vectors or scalars.
845                         match *accept_inner {
846                             Ti::Scalar { .. } | Ti::Vector { .. } => true,
847                             _ => false,
848                         }
849                     }
850                     Ti::Vector {
851                         size,
852                         kind: Sk::Bool,
853                         width: _,
854                     } => match *accept_inner {
855                         Ti::Vector {
856                             size: other_size, ..
857                         } => size == other_size,
858                         _ => false,
859                     },
860                     _ => false,
861                 };
862                 if !condition_good || accept_inner != reject_inner {
863                     return Err(ExpressionError::InvalidSelectTypes);
864                 }
865                 ShaderStages::all()
866             }
867             E::Derivative { axis: _, expr } => {
868                 match *resolver.resolve(expr)? {
869                     Ti::Scalar {
870                         kind: Sk::Float, ..
871                     }
872                     | Ti::Vector {
873                         kind: Sk::Float, ..
874                     } => {}
875                     _ => return Err(ExpressionError::InvalidDerivative),
876                 }
877                 ShaderStages::FRAGMENT
878             }
879             E::Relational { fun, argument } => {
880                 use crate::RelationalFunction as Rf;
881                 let argument_inner = resolver.resolve(argument)?;
882                 match fun {
883                     Rf::All | Rf::Any => match *argument_inner {
884                         Ti::Vector { kind: Sk::Bool, .. } => {}
885                         ref other => {
886                             log::error!("All/Any of type {:?}", other);
887                             return Err(ExpressionError::InvalidBooleanVector(argument));
888                         }
889                     },
890                     Rf::IsNan | Rf::IsInf | Rf::IsFinite | Rf::IsNormal => match *argument_inner {
891                         Ti::Scalar {
892                             kind: Sk::Float, ..
893                         }
894                         | Ti::Vector {
895                             kind: Sk::Float, ..
896                         } => {}
897                         ref other => {
898                             log::error!("Float test of type {:?}", other);
899                             return Err(ExpressionError::InvalidFloatArgument(argument));
900                         }
901                     },
902                 }
903                 ShaderStages::all()
904             }
905             E::Math {
906                 fun,
907                 arg,
908                 arg1,
909                 arg2,
910                 arg3,
911             } => {
912                 use crate::MathFunction as Mf;
913 
914                 let arg_ty = resolver.resolve(arg)?;
915                 let arg1_ty = arg1.map(|expr| resolver.resolve(expr)).transpose()?;
916                 let arg2_ty = arg2.map(|expr| resolver.resolve(expr)).transpose()?;
917                 let arg3_ty = arg3.map(|expr| resolver.resolve(expr)).transpose()?;
918                 match fun {
919                     Mf::Abs => {
920                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
921                             return Err(ExpressionError::WrongArgumentCount(fun));
922                         }
923                         let good = match *arg_ty {
924                             Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
925                             _ => false,
926                         };
927                         if !good {
928                             return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
929                         }
930                     }
931                     Mf::Min | Mf::Max => {
932                         let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
933                             (Some(ty1), None, None) => ty1,
934                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
935                         };
936                         let good = match *arg_ty {
937                             Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
938                             _ => false,
939                         };
940                         if !good {
941                             return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
942                         }
943                         if arg1_ty != arg_ty {
944                             return Err(ExpressionError::InvalidArgumentType(
945                                 fun,
946                                 1,
947                                 arg1.unwrap(),
948                             ));
949                         }
950                     }
951                     Mf::Clamp => {
952                         let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
953                             (Some(ty1), Some(ty2), None) => (ty1, ty2),
954                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
955                         };
956                         let good = match *arg_ty {
957                             Ti::Scalar { kind, .. } | Ti::Vector { kind, .. } => kind != Sk::Bool,
958                             _ => false,
959                         };
960                         if !good {
961                             return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
962                         }
963                         if arg1_ty != arg_ty {
964                             return Err(ExpressionError::InvalidArgumentType(
965                                 fun,
966                                 1,
967                                 arg1.unwrap(),
968                             ));
969                         }
970                         if arg2_ty != arg_ty {
971                             return Err(ExpressionError::InvalidArgumentType(
972                                 fun,
973                                 2,
974                                 arg2.unwrap(),
975                             ));
976                         }
977                     }
978                     Mf::Cos
979                     | Mf::Cosh
980                     | Mf::Sin
981                     | Mf::Sinh
982                     | Mf::Tan
983                     | Mf::Tanh
984                     | Mf::Acos
985                     | Mf::Asin
986                     | Mf::Atan
987                     | Mf::Asinh
988                     | Mf::Acosh
989                     | Mf::Atanh
990                     | Mf::Radians
991                     | Mf::Degrees
992                     | Mf::Ceil
993                     | Mf::Floor
994                     | Mf::Round
995                     | Mf::Fract
996                     | Mf::Trunc
997                     | Mf::Exp
998                     | Mf::Exp2
999                     | Mf::Log
1000                     | Mf::Log2
1001                     | Mf::Length
1002                     | Mf::Sign
1003                     | Mf::Sqrt
1004                     | Mf::InverseSqrt => {
1005                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1006                             return Err(ExpressionError::WrongArgumentCount(fun));
1007                         }
1008                         match *arg_ty {
1009                             Ti::Scalar {
1010                                 kind: Sk::Float, ..
1011                             }
1012                             | Ti::Vector {
1013                                 kind: Sk::Float, ..
1014                             } => {}
1015                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1016                         }
1017                     }
1018                     Mf::Atan2 | Mf::Pow | Mf::Distance | Mf::Step => {
1019                         let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
1020                             (Some(ty1), None, None) => ty1,
1021                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1022                         };
1023                         match *arg_ty {
1024                             Ti::Scalar {
1025                                 kind: Sk::Float, ..
1026                             }
1027                             | Ti::Vector {
1028                                 kind: Sk::Float, ..
1029                             } => {}
1030                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1031                         }
1032                         if arg1_ty != arg_ty {
1033                             return Err(ExpressionError::InvalidArgumentType(
1034                                 fun,
1035                                 1,
1036                                 arg1.unwrap(),
1037                             ));
1038                         }
1039                     }
1040                     Mf::Modf | Mf::Frexp | Mf::Ldexp => {
1041                         let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
1042                             (Some(ty1), None, None) => ty1,
1043                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1044                         };
1045                         let (size0, width0) = match *arg_ty {
1046                             Ti::Scalar {
1047                                 kind: Sk::Float,
1048                                 width,
1049                             } => (None, width),
1050                             Ti::Vector {
1051                                 kind: Sk::Float,
1052                                 size,
1053                                 width,
1054                             } => (Some(size), width),
1055                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1056                         };
1057                         let good = match *arg1_ty {
1058                             Ti::Pointer { base, class: _ } => module.types[base].inner == *arg_ty,
1059                             Ti::ValuePointer {
1060                                 size,
1061                                 kind: Sk::Float,
1062                                 width,
1063                                 class: _,
1064                             } => size == size0 && width == width0,
1065                             _ => false,
1066                         };
1067                         if !good {
1068                             return Err(ExpressionError::InvalidArgumentType(
1069                                 fun,
1070                                 1,
1071                                 arg1.unwrap(),
1072                             ));
1073                         }
1074                     }
1075                     Mf::Dot | Mf::Outer | Mf::Cross | Mf::Reflect => {
1076                         let arg1_ty = match (arg1_ty, arg2_ty, arg3_ty) {
1077                             (Some(ty1), None, None) => ty1,
1078                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1079                         };
1080                         match *arg_ty {
1081                             Ti::Vector {
1082                                 kind: Sk::Float, ..
1083                             } => {}
1084                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1085                         }
1086                         if arg1_ty != arg_ty {
1087                             return Err(ExpressionError::InvalidArgumentType(
1088                                 fun,
1089                                 1,
1090                                 arg1.unwrap(),
1091                             ));
1092                         }
1093                     }
1094                     Mf::Refract => {
1095                         let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
1096                             (Some(ty1), Some(ty2), None) => (ty1, ty2),
1097                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1098                         };
1099 
1100                         match *arg_ty {
1101                             Ti::Vector {
1102                                 kind: Sk::Float, ..
1103                             } => {}
1104                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1105                         }
1106 
1107                         if arg1_ty != arg_ty {
1108                             return Err(ExpressionError::InvalidArgumentType(
1109                                 fun,
1110                                 1,
1111                                 arg1.unwrap(),
1112                             ));
1113                         }
1114 
1115                         match (arg_ty, arg2_ty) {
1116                             (
1117                                 &Ti::Vector {
1118                                     width: vector_width,
1119                                     ..
1120                                 },
1121                                 &Ti::Scalar {
1122                                     width: scalar_width,
1123                                     kind: Sk::Float,
1124                                 },
1125                             ) if vector_width == scalar_width => {}
1126                             _ => {
1127                                 return Err(ExpressionError::InvalidArgumentType(
1128                                     fun,
1129                                     2,
1130                                     arg2.unwrap(),
1131                                 ))
1132                             }
1133                         }
1134                     }
1135                     Mf::Normalize => {
1136                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1137                             return Err(ExpressionError::WrongArgumentCount(fun));
1138                         }
1139                         match *arg_ty {
1140                             Ti::Vector {
1141                                 kind: Sk::Float, ..
1142                             } => {}
1143                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1144                         }
1145                     }
1146                     Mf::FaceForward | Mf::Fma | Mf::SmoothStep => {
1147                         let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
1148                             (Some(ty1), Some(ty2), None) => (ty1, ty2),
1149                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1150                         };
1151                         match *arg_ty {
1152                             Ti::Scalar {
1153                                 kind: Sk::Float, ..
1154                             }
1155                             | Ti::Vector {
1156                                 kind: Sk::Float, ..
1157                             } => {}
1158                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1159                         }
1160                         if arg1_ty != arg_ty {
1161                             return Err(ExpressionError::InvalidArgumentType(
1162                                 fun,
1163                                 1,
1164                                 arg1.unwrap(),
1165                             ));
1166                         }
1167                         if arg2_ty != arg_ty {
1168                             return Err(ExpressionError::InvalidArgumentType(
1169                                 fun,
1170                                 2,
1171                                 arg2.unwrap(),
1172                             ));
1173                         }
1174                     }
1175                     Mf::Mix => {
1176                         let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
1177                             (Some(ty1), Some(ty2), None) => (ty1, ty2),
1178                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1179                         };
1180                         let arg_width = match *arg_ty {
1181                             Ti::Scalar {
1182                                 kind: Sk::Float,
1183                                 width,
1184                             }
1185                             | Ti::Vector {
1186                                 kind: Sk::Float,
1187                                 width,
1188                                 ..
1189                             } => width,
1190                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1191                         };
1192                         if arg1_ty != arg_ty {
1193                             return Err(ExpressionError::InvalidArgumentType(
1194                                 fun,
1195                                 1,
1196                                 arg1.unwrap(),
1197                             ));
1198                         }
1199                         // the last argument can always be a scalar
1200                         match *arg2_ty {
1201                             Ti::Scalar {
1202                                 kind: Sk::Float,
1203                                 width,
1204                             } if width == arg_width => {}
1205                             _ if arg2_ty == arg_ty => {}
1206                             _ => {
1207                                 return Err(ExpressionError::InvalidArgumentType(
1208                                     fun,
1209                                     2,
1210                                     arg2.unwrap(),
1211                                 ));
1212                             }
1213                         }
1214                     }
1215                     Mf::Inverse | Mf::Determinant => {
1216                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1217                             return Err(ExpressionError::WrongArgumentCount(fun));
1218                         }
1219                         let good = match *arg_ty {
1220                             Ti::Matrix { columns, rows, .. } => columns == rows,
1221                             _ => false,
1222                         };
1223                         if !good {
1224                             return Err(ExpressionError::InvalidArgumentType(fun, 0, arg));
1225                         }
1226                     }
1227                     Mf::Transpose => {
1228                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1229                             return Err(ExpressionError::WrongArgumentCount(fun));
1230                         }
1231                         match *arg_ty {
1232                             Ti::Matrix { .. } => {}
1233                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1234                         }
1235                     }
1236                     Mf::CountOneBits | Mf::ReverseBits | Mf::FindLsb | Mf::FindMsb => {
1237                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1238                             return Err(ExpressionError::WrongArgumentCount(fun));
1239                         }
1240                         match *arg_ty {
1241                             Ti::Scalar { kind: Sk::Sint, .. }
1242                             | Ti::Scalar { kind: Sk::Uint, .. }
1243                             | Ti::Vector { kind: Sk::Sint, .. }
1244                             | Ti::Vector { kind: Sk::Uint, .. } => {}
1245                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1246                         }
1247                     }
1248                     Mf::InsertBits => {
1249                         let (arg1_ty, arg2_ty, arg3_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
1250                             (Some(ty1), Some(ty2), Some(ty3)) => (ty1, ty2, ty3),
1251                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1252                         };
1253                         match *arg_ty {
1254                             Ti::Scalar { kind: Sk::Sint, .. }
1255                             | Ti::Scalar { kind: Sk::Uint, .. }
1256                             | Ti::Vector { kind: Sk::Sint, .. }
1257                             | Ti::Vector { kind: Sk::Uint, .. } => {}
1258                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1259                         }
1260                         if arg1_ty != arg_ty {
1261                             return Err(ExpressionError::InvalidArgumentType(
1262                                 fun,
1263                                 1,
1264                                 arg1.unwrap(),
1265                             ));
1266                         }
1267                         match *arg2_ty {
1268                             Ti::Scalar { kind: Sk::Uint, .. } => {}
1269                             _ => {
1270                                 return Err(ExpressionError::InvalidArgumentType(
1271                                     fun,
1272                                     2,
1273                                     arg2.unwrap(),
1274                                 ))
1275                             }
1276                         }
1277                         match *arg3_ty {
1278                             Ti::Scalar { kind: Sk::Uint, .. } => {}
1279                             _ => {
1280                                 return Err(ExpressionError::InvalidArgumentType(
1281                                     fun,
1282                                     2,
1283                                     arg3.unwrap(),
1284                                 ))
1285                             }
1286                         }
1287                     }
1288                     Mf::ExtractBits => {
1289                         let (arg1_ty, arg2_ty) = match (arg1_ty, arg2_ty, arg3_ty) {
1290                             (Some(ty1), Some(ty2), None) => (ty1, ty2),
1291                             _ => return Err(ExpressionError::WrongArgumentCount(fun)),
1292                         };
1293                         match *arg_ty {
1294                             Ti::Scalar { kind: Sk::Sint, .. }
1295                             | Ti::Scalar { kind: Sk::Uint, .. }
1296                             | Ti::Vector { kind: Sk::Sint, .. }
1297                             | Ti::Vector { kind: Sk::Uint, .. } => {}
1298                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1299                         }
1300                         match *arg1_ty {
1301                             Ti::Scalar { kind: Sk::Uint, .. } => {}
1302                             _ => {
1303                                 return Err(ExpressionError::InvalidArgumentType(
1304                                     fun,
1305                                     2,
1306                                     arg1.unwrap(),
1307                                 ))
1308                             }
1309                         }
1310                         match *arg2_ty {
1311                             Ti::Scalar { kind: Sk::Uint, .. } => {}
1312                             _ => {
1313                                 return Err(ExpressionError::InvalidArgumentType(
1314                                     fun,
1315                                     2,
1316                                     arg2.unwrap(),
1317                                 ))
1318                             }
1319                         }
1320                     }
1321                     Mf::Pack2x16unorm | Mf::Pack2x16snorm | Mf::Pack2x16float => {
1322                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1323                             return Err(ExpressionError::WrongArgumentCount(fun));
1324                         }
1325                         match *arg_ty {
1326                             Ti::Vector {
1327                                 size: crate::VectorSize::Bi,
1328                                 kind: Sk::Float,
1329                                 ..
1330                             } => {}
1331                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1332                         }
1333                     }
1334                     Mf::Pack4x8snorm | Mf::Pack4x8unorm => {
1335                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1336                             return Err(ExpressionError::WrongArgumentCount(fun));
1337                         }
1338                         match *arg_ty {
1339                             Ti::Vector {
1340                                 size: crate::VectorSize::Quad,
1341                                 kind: Sk::Float,
1342                                 ..
1343                             } => {}
1344                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1345                         }
1346                     }
1347                     Mf::Unpack2x16float
1348                     | Mf::Unpack2x16snorm
1349                     | Mf::Unpack2x16unorm
1350                     | Mf::Unpack4x8snorm
1351                     | Mf::Unpack4x8unorm => {
1352                         if arg1_ty.is_some() | arg2_ty.is_some() | arg3_ty.is_some() {
1353                             return Err(ExpressionError::WrongArgumentCount(fun));
1354                         }
1355                         match *arg_ty {
1356                             Ti::Scalar { kind: Sk::Uint, .. } => {}
1357                             _ => return Err(ExpressionError::InvalidArgumentType(fun, 0, arg)),
1358                         }
1359                     }
1360                 }
1361                 ShaderStages::all()
1362             }
1363             E::As {
1364                 expr,
1365                 kind,
1366                 convert,
1367             } => {
1368                 let base_width = match *resolver.resolve(expr)? {
1369                     crate::TypeInner::Scalar { width, .. }
1370                     | crate::TypeInner::Vector { width, .. }
1371                     | crate::TypeInner::Matrix { width, .. } => width,
1372                     _ => return Err(ExpressionError::InvalidCastArgument),
1373                 };
1374                 let width = convert.unwrap_or(base_width);
1375                 if !self.check_width(kind, width) {
1376                     return Err(ExpressionError::InvalidCastArgument);
1377                 }
1378                 ShaderStages::all()
1379             }
1380             E::CallResult(function) => other_infos[function.index()].available_stages,
1381             E::AtomicResult {
1382                 kind,
1383                 width,
1384                 comparison: _,
1385             } => {
1386                 let good = match kind {
1387                     crate::ScalarKind::Uint | crate::ScalarKind::Sint => {
1388                         self.check_width(kind, width)
1389                     }
1390                     _ => false,
1391                 };
1392                 if !good {
1393                     return Err(ExpressionError::InvalidAtomicResultType(kind, width));
1394                 }
1395                 ShaderStages::all()
1396             }
1397             E::ArrayLength(expr) => match *resolver.resolve(expr)? {
1398                 Ti::Pointer { base, .. } => {
1399                     if let Some(&Ti::Array {
1400                         size: crate::ArraySize::Dynamic,
1401                         ..
1402                     }) = resolver.types.get_handle(base).map(|ty| &ty.inner)
1403                     {
1404                         ShaderStages::all()
1405                     } else {
1406                         return Err(ExpressionError::InvalidArrayType(expr));
1407                     }
1408                 }
1409                 ref other => {
1410                     log::error!("Array length of {:?}", other);
1411                     return Err(ExpressionError::InvalidArrayType(expr));
1412                 }
1413             },
1414         };
1415         Ok(stages)
1416     }
1417 }
1418