Use source attribute of errors

This commit is contained in:
Dzmitry Malyshau 2021-02-19 21:42:31 -05:00 committed by Dzmitry Malyshau
parent 99c1add358
commit 26e6c2bdac
6 changed files with 57 additions and 31 deletions

View File

@ -1,4 +1,4 @@
use std::{env, fmt, fs, path::Path};
use std::{env, error::Error, fs, path::Path};
#[derive(Hash, PartialEq, Eq, serde::Deserialize)]
enum Stage {
@ -40,7 +40,7 @@ struct Parameters {
#[cfg_attr(not(feature = "spv-out"), allow(dead_code))]
spv_capabilities: naga::FastHashSet<spirv::Capability>,
#[cfg_attr(not(feature = "msl-out"), allow(dead_code))]
mtl_bindings: Option<naga::FastHashMap<BindSource, BindTarget>>,
mtl_bindings: naga::FastHashMap<BindSource, BindTarget>,
}
trait PrettyResult {
@ -48,12 +48,20 @@ trait PrettyResult {
fn unwrap_pretty(self) -> Self::Target;
}
impl<T, E: fmt::Display> PrettyResult for Result<T, E> {
impl<T, E: Error> PrettyResult for Result<T, E> {
type Target = T;
fn unwrap_pretty(self) -> T {
match self {
Result::Ok(value) => value,
Result::Err(e) => panic!("{}", e),
Result::Err(error) => {
println!("{}:", error);
let mut e = error.source();
while let Some(source) = e {
println!("\t{}", source);
e = source.source();
}
std::process::exit(1);
}
}
}
}
@ -164,6 +172,7 @@ fn main() {
}
// validate the IR
#[allow(unused_variables)]
let analysis = naga::proc::Validator::new()
.validate(&module)
.unwrap_pretty();
@ -183,8 +192,11 @@ fn main() {
spirv_cross_compatibility: false,
fake_missing_bindings: false,
};
if let Some(map) = params.mtl_bindings {
for (key, value) in map {
if params.mtl_bindings.is_empty() {
log::warn!("Metal binding map is missing");
options.fake_missing_bindings = true;
} else {
for (key, value) in params.mtl_bindings {
options.binding_map.insert(
msl::BindSource {
stage: match key.stage {
@ -203,11 +215,8 @@ fn main() {
},
);
}
} else {
log::warn!("Metal binding map is missing");
options.fake_missing_bindings = true;
}
let (msl, _) = msl::write_string(&module, &analysis, &options).unwrap();
let (msl, _) = msl::write_string(&module, &analysis, &options).unwrap_pretty();
fs::write(&args[2], msl).unwrap();
}
#[cfg(feature = "spv-out")]

View File

@ -216,10 +216,10 @@ type BackendResult = Result<(), Error>;
#[derive(Debug, Error)]
pub enum Error {
/// A error occurred while writing to the output
#[error("Io error: {0}")]
#[error("I/O error")]
IoError(#[from] IoError),
/// The [`Module`](crate::Module) failed type resolution
#[error("Type error: {0}")]
#[error("Type error")]
Type(#[from] TypifyError),
/// The specified [`Version`](Version) doesn't have all required [`Features`](super)
///

View File

@ -2,6 +2,7 @@ use super::parser::Token;
use super::token::TokenMetadata;
use std::{borrow::Cow, fmt, io};
//TODO: use `thiserror`
#[derive(Debug)]
pub enum ErrorKind {
EndOfFile,

View File

@ -1,6 +1,7 @@
use super::ModuleState;
use crate::arena::Handle;
//TODO: use `thiserror`
#[derive(Debug)]
pub enum Error {
InvalidHeader,

View File

@ -63,7 +63,7 @@ pub enum ResolveError {
}
#[derive(Clone, Debug, Error, PartialEq)]
#[error("Type resolution of {0:?} failed: {1}")]
#[error("Type resolution of {0:?} failed")]
pub struct TypifyError(Handle<crate::Expression>, #[source] ResolveError);
pub struct ResolveContext<'a> {

View File

@ -4,6 +4,7 @@ use super::{
};
use crate::arena::{Arena, Handle};
use bit_set::BitSet;
use thiserror::Error;
const MAX_WORKGROUP_SIZE: u32 = 0x4000;
@ -26,7 +27,7 @@ pub struct Validator {
bind_group_masks: Vec<BitSet>,
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum TypeError {
#[error("The {0:?} scalar width {1} is not supported")]
InvalidWidth(crate::ScalarKind, crate::Bytes),
@ -40,7 +41,7 @@ pub enum TypeError {
MissingBlockDecoration,
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum ConstantError {
#[error("The type doesn't match the constant")]
InvalidType,
@ -50,7 +51,7 @@ pub enum ConstantError {
UnresolvedSize(Handle<crate::Constant>),
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum GlobalVariableError {
#[error("Usage isn't compatible with the storage class")]
InvalidUsage,
@ -58,7 +59,7 @@ pub enum GlobalVariableError {
InvalidType,
#[error("Interpolation is not valid")]
InvalidInterpolation,
#[error("Storage access {seen:?} exceed the allowed {allowed:?}")]
#[error("Storage access {seen:?} exceeds the allowed {allowed:?}")]
InvalidStorageAccess {
allowed: crate::StorageAccess,
seen: crate::StorageAccess,
@ -69,29 +70,30 @@ pub enum GlobalVariableError {
InvalidBuiltInType(crate::BuiltIn),
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum LocalVariableError {
#[error("Initializer doesn't match the variable type")]
InitializerType,
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum FunctionError {
#[error(transparent)]
Resolve(#[from] TypifyError),
#[error("There are instructions after `return`/`break`/`continue`")]
InvalidControlFlowExitTail,
#[error("Local variable {handle:?} '{name}' is invalid: {error:?}")]
#[error("Local variable {handle:?} '{name}' is invalid")]
LocalVariable {
handle: Handle<crate::LocalVariable>,
name: String,
#[source]
error: LocalVariableError,
},
#[error("Argument '{name}' at index {index} has a type that can't be passed into functions.")]
InvalidArgumentType { index: usize, name: String },
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum EntryPointError {
#[error("Early depth test is not applicable")]
UnexpectedEarlyDepthTest,
@ -115,32 +117,41 @@ pub enum EntryPointError {
Function(#[from] FunctionError),
}
#[derive(Clone, Debug, thiserror::Error)]
#[derive(Clone, Debug, Error)]
pub enum ValidationError {
#[error("Type {handle:?} '{name}' is invalid: {error:?}")]
#[error("Type {handle:?} '{name}' is invalid")]
Type {
handle: Handle<crate::Type>,
name: String,
#[source]
error: TypeError,
},
#[error("Constant {handle:?} '{name}' is invalid: {error:?}")]
#[error("Constant {handle:?} '{name}' is invalid")]
Constant {
handle: Handle<crate::Constant>,
name: String,
#[source]
error: ConstantError,
},
#[error("Global variable {handle:?} '{name}' is invalid: {error:?}")]
#[error("Global variable {handle:?} '{name}' is invalid")]
GlobalVariable {
handle: Handle<crate::GlobalVariable>,
name: String,
#[source]
error: GlobalVariableError,
},
#[error("Function {0:?} is invalid: {1:?}")]
Function(Handle<crate::Function>, FunctionError),
#[error("Entry point {name} at {stage:?} is invalid: {error:?}")]
#[error("Function {handle:?} '{name}' is invalid")]
Function {
handle: Handle<crate::Function>,
name: String,
#[source]
error: FunctionError,
},
#[error("Entry point {name} at {stage:?} is invalid")]
EntryPoint {
stage: crate::ShaderStage,
name: String,
#[source]
error: EntryPointError,
},
#[error(transparent)]
@ -738,9 +749,13 @@ impl Validator {
})?;
}
for (fun_handle, fun) in module.functions.iter() {
self.validate_function(fun, &analysis[fun_handle], module)
.map_err(|e| ValidationError::Function(fun_handle, e))?;
for (handle, fun) in module.functions.iter() {
self.validate_function(fun, &analysis[handle], module)
.map_err(|error| ValidationError::Function {
handle,
name: fun.name.clone().unwrap_or_default(),
error,
})?;
}
for (&(stage, ref name), entry_point) in module.entry_points.iter() {