Functions can take pointers to unsized structs, but no other unsized types.

This commit is contained in:
Jim Blandy
2021-05-27 14:01:40 -07:00
committed by Dzmitry Malyshau
parent fd3b2a93d4
commit 1d0b3f3a75
3 changed files with 68 additions and 3 deletions

View File

@@ -37,6 +37,8 @@ pub enum CallError {
#[derive(Clone, Debug, thiserror::Error)]
#[cfg_attr(test, derive(PartialEq))]
pub enum LocalVariableError {
#[error("Local variable has a type {0:?} that can't be stored in a local variable.")]
InvalidType(Handle<crate::Type>),
#[error("Initializer doesn't match the variable type")]
InitializerType,
}
@@ -517,6 +519,12 @@ impl super::Validator {
constants: &Arena<crate::Constant>,
) -> Result<(), LocalVariableError> {
log::debug!("var {:?}", var);
if !self.types[var.ty.index()]
.flags
.contains(TypeFlags::DATA | TypeFlags::SIZED)
{
return Err(LocalVariableError::InvalidType(var.ty));
}
if let Some(const_handle) = var.init {
match constants[const_handle].inner {
crate::ConstantInner::Scalar { width, ref value } => {

View File

@@ -42,6 +42,8 @@ pub enum TypeError {
InvalidWidth(crate::ScalarKind, crate::Bytes),
#[error("The base handle {0:?} can not be resolved")]
UnresolvedBase(Handle<crate::Type>),
#[error("Invalid type for pointer target {0:?}")]
InvalidPointerBase(Handle<crate::Type>),
#[error("Expected data type, found {0:?}")]
InvalidData(Handle<crate::Type>),
#[error("Structure type {0:?} can not be a block structure")]
@@ -197,7 +199,23 @@ impl super::Validator {
if base >= handle {
return Err(TypeError::UnresolvedBase(base));
}
TypeInfo::new(TypeFlags::DATA | TypeFlags::SIZED, 0)
// Pointers to dynamically-sized arrays are needed, to serve as
// the type of an `AccessIndex` expression referring to a
// dynamically sized array appearing as the final member of a
// top-level `Struct`. But such pointers cannot be passed to
// functions, stored in varibles, etc. So, we mark them as not
// `DATA`.
let base_info = &self.types[base.index()];
let data_flag = if base_info.flags.contains(TypeFlags::SIZED) {
TypeFlags::DATA
} else if let crate::TypeInner::Struct { .. } = types[base].inner {
TypeFlags::DATA
} else {
TypeFlags::empty()
};
TypeInfo::new(data_flag | TypeFlags::SIZED, 0)
}
Ti::ValuePointer {
size: _,