mirror of
https://github.com/gfx-rs/wgpu.git
synced 2025-02-19 18:33:30 +00:00
Functions can take pointers to unsized structs, but no other unsized types.
This commit is contained in:
parent
fd3b2a93d4
commit
1d0b3f3a75
@ -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 } => {
|
||||
|
@ -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: _,
|
||||
|
@ -128,10 +128,14 @@ macro_rules! check_validation_error {
|
||||
let error = validation_error($source);
|
||||
if ! matches!(&error, $pattern if $guard) {
|
||||
eprintln!("validation error does not match pattern:\n\
|
||||
source code: {}\n\
|
||||
\n\
|
||||
actual result:\n\
|
||||
{:#?}\n\
|
||||
\n\
|
||||
expected match for pattern:\n\
|
||||
{}{}",
|
||||
stringify!($source),
|
||||
error,
|
||||
stringify!($pattern),
|
||||
$guard_string);
|
||||
@ -227,7 +231,12 @@ fn invalid_structs() {
|
||||
#[test]
|
||||
fn invalid_functions() {
|
||||
check_validation_error! {
|
||||
"fn bogus(data: array<f32>) -> f32 { return data[0]; }":
|
||||
"fn unacceptable_unsized(arg: array<f32>) { }",
|
||||
"fn unacceptable_unsized(arg: ptr<storage, array<f32>>) { }",
|
||||
"
|
||||
struct Unsized { data: array<f32>; };
|
||||
fn unacceptable_unsized(arg: Unsized) { }
|
||||
":
|
||||
Err(naga::valid::ValidationError::Function {
|
||||
name: function_name,
|
||||
error: naga::valid::FunctionError::InvalidArgumentType {
|
||||
@ -236,7 +245,16 @@ fn invalid_functions() {
|
||||
},
|
||||
..
|
||||
})
|
||||
if function_name == "bogus" && argument_name == "data"
|
||||
if function_name == "unacceptable_unsized" && argument_name == "arg"
|
||||
}
|
||||
|
||||
// A *valid* way to pass an unsized value.
|
||||
check_validation_error! {
|
||||
"
|
||||
struct Unsized { data: array<f32>; };
|
||||
fn acceptable_ptr_to_unsized(okay: ptr<storage, Unsized>) { }
|
||||
":
|
||||
Ok(_)
|
||||
}
|
||||
}
|
||||
|
||||
@ -357,3 +375,24 @@ fn valid_access() {
|
||||
Ok(_)
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_local_vars() {
|
||||
check_validation_error! {
|
||||
"
|
||||
struct Unsized { data: array<f32>; };
|
||||
fn local_ptr_dynamic_array(okay: ptr<storage, Unsized>) {
|
||||
var not_okay: ptr<storage, array<f32>> = okay.data;
|
||||
}
|
||||
":
|
||||
Err(naga::valid::ValidationError::Function {
|
||||
error: naga::valid::FunctionError::LocalVariable {
|
||||
name: local_var_name,
|
||||
error: naga::valid::LocalVariableError::InvalidType(_),
|
||||
..
|
||||
},
|
||||
..
|
||||
})
|
||||
if local_var_name == "not_okay"
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user