diff --git a/src/lib.rs b/src/lib.rs index 80461e16ff..baa1779af0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -978,7 +978,9 @@ pub struct LocalVariable { pub name: Option, /// The type of this variable. pub ty: Handle, - /// Initial value for this variable. Must be a const-expression. + /// Initial value for this variable. Must be a constant expression. + /// + /// [constant expression]: index.html#constant-expressions pub init: Option>, } diff --git a/src/valid/function.rs b/src/valid/function.rs index a056a1d1f6..ca5877ba1e 100644 --- a/src/valid/function.rs +++ b/src/valid/function.rs @@ -58,6 +58,8 @@ pub enum LocalVariableError { InvalidType(Handle), #[error("Initializer doesn't match the variable type")] InitializerType, + #[error("Initializer is not const")] + NonConstInitializer, } #[derive(Clone, Debug, thiserror::Error)] @@ -942,6 +944,7 @@ impl super::Validator { var: &crate::LocalVariable, gctx: crate::proc::GlobalCtx, fun_info: &FunctionInfo, + expression_constness: &crate::proc::ExpressionConstnessTracker, ) -> Result<(), LocalVariableError> { log::debug!("var {:?}", var); let type_info = self @@ -958,6 +961,10 @@ impl super::Validator { if !decl_ty.equivalent(init_ty, gctx.types) { return Err(LocalVariableError::InitializerType); } + + if !expression_constness.is_const(init) { + return Err(LocalVariableError::NonConstInitializer); + } } Ok(()) @@ -973,9 +980,13 @@ impl super::Validator { #[cfg_attr(not(feature = "validate"), allow(unused_mut))] let mut info = mod_info.process_function(fun, module, self.flags, self.capabilities)?; + #[cfg(feature = "validate")] + let expression_constness = + crate::proc::ExpressionConstnessTracker::from_arena(&fun.expressions); + #[cfg(feature = "validate")] for (var_handle, var) in fun.local_variables.iter() { - self.validate_local_var(var, module.to_ctx(), &info) + self.validate_local_var(var, module.to_ctx(), &info, &expression_constness) .map_err(|source| { FunctionError::LocalVariable { handle: var_handle,