From 26e6c2bdacb7ccae62190eb75dea22cdb66bba16 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Fri, 19 Feb 2021 21:42:31 -0500 Subject: [PATCH] Use source attribute of errors --- examples/convert.rs | 29 +++++++++++++++-------- src/back/glsl/mod.rs | 4 ++-- src/front/glsl/error.rs | 1 + src/front/spv/error.rs | 1 + src/proc/typifier.rs | 2 +- src/proc/validator.rs | 51 ++++++++++++++++++++++++++--------------- 6 files changed, 57 insertions(+), 31 deletions(-) diff --git a/examples/convert.rs b/examples/convert.rs index 03bdcdae0..2174cdaf1 100644 --- a/examples/convert.rs +++ b/examples/convert.rs @@ -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, #[cfg_attr(not(feature = "msl-out"), allow(dead_code))] - mtl_bindings: Option>, + mtl_bindings: naga::FastHashMap, } trait PrettyResult { @@ -48,12 +48,20 @@ trait PrettyResult { fn unwrap_pretty(self) -> Self::Target; } -impl PrettyResult for Result { +impl PrettyResult for Result { 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")] diff --git a/src/back/glsl/mod.rs b/src/back/glsl/mod.rs index 6a0a74a94..31cabdecd 100644 --- a/src/back/glsl/mod.rs +++ b/src/back/glsl/mod.rs @@ -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) /// diff --git a/src/front/glsl/error.rs b/src/front/glsl/error.rs index 771c99db1..7fd4a2804 100644 --- a/src/front/glsl/error.rs +++ b/src/front/glsl/error.rs @@ -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, diff --git a/src/front/spv/error.rs b/src/front/spv/error.rs index c7bac4b17..b07053f98 100644 --- a/src/front/spv/error.rs +++ b/src/front/spv/error.rs @@ -1,6 +1,7 @@ use super::ModuleState; use crate::arena::Handle; +//TODO: use `thiserror` #[derive(Debug)] pub enum Error { InvalidHeader, diff --git a/src/proc/typifier.rs b/src/proc/typifier.rs index 8cffd5bfd..1ff75bc75 100644 --- a/src/proc/typifier.rs +++ b/src/proc/typifier.rs @@ -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, #[source] ResolveError); pub struct ResolveContext<'a> { diff --git a/src/proc/validator.rs b/src/proc/validator.rs index 4188c8ba3..d44cc5e82 100644 --- a/src/proc/validator.rs +++ b/src/proc/validator.rs @@ -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, } -#[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), } -#[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, 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, name: String, + #[source] error: TypeError, }, - #[error("Constant {handle:?} '{name}' is invalid: {error:?}")] + #[error("Constant {handle:?} '{name}' is invalid")] Constant { handle: Handle, name: String, + #[source] error: ConstantError, }, - #[error("Global variable {handle:?} '{name}' is invalid: {error:?}")] + #[error("Global variable {handle:?} '{name}' is invalid")] GlobalVariable { handle: Handle, name: String, + #[source] error: GlobalVariableError, }, - #[error("Function {0:?} is invalid: {1:?}")] - Function(Handle, FunctionError), - #[error("Entry point {name} at {stage:?} is invalid: {error:?}")] + #[error("Function {handle:?} '{name}' is invalid")] + Function { + handle: Handle, + 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() {