[valid] check local variable initializer is const

This commit is contained in:
teoxoy
2023-10-11 14:07:20 +02:00
committed by Teodor Tanasoaia
parent a3ba3259fe
commit f7e15bf391
2 changed files with 19 additions and 2 deletions

View File

@@ -978,7 +978,13 @@ pub struct LocalVariable {
pub name: Option<String>,
/// The type of this variable.
pub ty: Handle<Type>,
/// Initial value for this variable. Must be a const-expression.
/// Initial value for this variable.
///
/// This handle refers to this `LocalVariable`'s function's
/// [`expressions`] arena, but it is required to be an evaluated
/// constant expression.
///
/// [`expressions`]: Function::expressions
pub init: Option<Handle<Expression>>,
}

View File

@@ -58,6 +58,8 @@ pub enum LocalVariableError {
InvalidType(Handle<crate::Type>),
#[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,