diff --git a/naga/src/front/wgsl/error.rs b/naga/src/front/wgsl/error.rs index bfaba4894..ed7006d50 100644 --- a/naga/src/front/wgsl/error.rs +++ b/naga/src/front/wgsl/error.rs @@ -10,6 +10,9 @@ use std::ops::Range; use termcolor::{ColorChoice, NoColor, StandardStream}; use thiserror::Error; +#[cfg(test)] +use std::mem::size_of; + #[derive(Clone, Debug)] pub struct ParseError { message: String, @@ -144,7 +147,7 @@ pub enum InvalidAssignmentType { } #[derive(Clone, Debug)] -pub enum Error<'a> { +pub(crate) enum Error<'a> { Unexpected(Span, ExpectedToken<'a>), UnexpectedComponents(Span), UnexpectedOperationInConstContext(Span), @@ -154,8 +157,8 @@ pub enum Error<'a> { BadTexture(Span), BadTypeCast { span: Span, - from_type: String, - to_type: String, + from_type: Box, + to_type: Box, }, BadTextureSampleType { span: Span, @@ -188,8 +191,8 @@ pub enum Error<'a> { TypeNotInferable(Span), InitializationTypeMismatch { name: Span, - expected: String, - got: String, + expected: Box, + got: Box, }, DeclMissingTypeAndInit(Span), MissingAttribute(&'static str, Span), @@ -232,7 +235,7 @@ pub enum Error<'a> { /// name is `decl` has an identifier at `reference` whose definition is /// the next declaration in the cycle. The last pair's `reference` is /// the same identifier as `ident`, above. - path: Vec<(Span, Span)>, + path: Box<[(Span, Span)]>, }, InvalidSwitchValue { uint: bool, @@ -251,25 +254,10 @@ pub enum Error<'a> { ExpectedNonNegative(Span), ExpectedPositiveArrayLength(Span), MissingWorkgroupSize(Span), - ConstantEvaluatorError(ConstantEvaluatorError, Span), - AutoConversion { - dest_span: Span, - dest_type: String, - source_span: Span, - source_type: String, - }, - AutoConversionLeafScalar { - dest_span: Span, - dest_scalar: String, - source_span: Span, - source_type: String, - }, - ConcretizationFailed { - expr_span: Span, - expr_type: String, - scalar: String, - inner: ConstantEvaluatorError, - }, + ConstantEvaluatorError(Box, Span), + AutoConversion(Box), + AutoConversionLeafScalar(Box), + ConcretizationFailed(Box), ExceededLimitForNestedBraces { span: Span, limit: u8, @@ -277,6 +265,30 @@ pub enum Error<'a> { PipelineConstantIDValue(Span), } +#[derive(Clone, Debug)] +pub(crate) struct AutoConversionError { + pub dest_span: Span, + pub dest_type: Box, + pub source_span: Span, + pub source_type: Box, +} + +#[derive(Clone, Debug)] +pub(crate) struct AutoConversionLeafScalarError { + pub dest_span: Span, + pub dest_scalar: Box, + pub source_span: Span, + pub source_type: Box, +} + +#[derive(Clone, Debug)] +pub(crate) struct ConcretizationFailedError { + pub expr_span: Span, + pub expr_type: Box, + pub scalar: Box, + pub inner: ConstantEvaluatorError, +} + impl<'a> Error<'a> { #[cold] #[inline(never)] @@ -738,45 +750,55 @@ impl<'a> Error<'a> { )], notes: vec![], }, - Error::AutoConversion { dest_span, ref dest_type, source_span, ref source_type } => ParseError { - message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"), - labels: vec![ - ( - dest_span, - format!("a value of type {dest_type} is required here").into(), - ), - ( - source_span, - format!("this expression has type {source_type}").into(), - ) - ], - notes: vec![], + Error::AutoConversion(ref error) => { + // destructuring ensures all fields are handled + let AutoConversionError { dest_span, ref dest_type, source_span, ref source_type } = **error; + ParseError { + message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"), + labels: vec![ + ( + dest_span, + format!("a value of type {dest_type} is required here").into(), + ), + ( + source_span, + format!("this expression has type {source_type}").into(), + ) + ], + notes: vec![], + } }, - Error::AutoConversionLeafScalar { dest_span, ref dest_scalar, source_span, ref source_type } => ParseError { - message: format!("automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"), - labels: vec![ - ( - dest_span, - format!("a value with elements of type {dest_scalar} is required here").into(), - ), - ( - source_span, - format!("this expression has type {source_type}").into(), - ) - ], - notes: vec![], + Error::AutoConversionLeafScalar(ref error) => { + let AutoConversionLeafScalarError { dest_span, ref dest_scalar, source_span, ref source_type } = **error; + ParseError { + message: format!("automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"), + labels: vec![ + ( + dest_span, + format!("a value with elements of type {dest_scalar} is required here").into(), + ), + ( + source_span, + format!("this expression has type {source_type}").into(), + ) + ], + notes: vec![], + } }, - Error::ConcretizationFailed { expr_span, ref expr_type, ref scalar, ref inner } => ParseError { - message: format!("failed to convert expression to a concrete type: {}", inner), - labels: vec![ - ( - expr_span, - format!("this expression has type {}", expr_type).into(), - ) - ], - notes: vec![ - format!("the expression should have been converted to have {} scalar type", scalar), - ] + Error::ConcretizationFailed(ref error) => { + let ConcretizationFailedError { expr_span, ref expr_type, ref scalar, ref inner } = **error; + ParseError { + message: format!("failed to convert expression to a concrete type: {}", inner), + labels: vec![ + ( + expr_span, + format!("this expression has type {}", expr_type).into(), + ) + ], + notes: vec![ + format!("the expression should have been converted to have {} scalar type", scalar), + ] + } }, Error::ExceededLimitForNestedBraces { span, limit } => ParseError { message: "brace nesting limit reached".into(), @@ -796,3 +818,8 @@ impl<'a> Error<'a> { } } } + +#[test] +fn test_error_size() { + assert!(size_of::>() <= 48); +} diff --git a/naga/src/front/wgsl/lower/construction.rs b/naga/src/front/wgsl/lower/construction.rs index de0d11d22..cb6ceb061 100644 --- a/naga/src/front/wgsl/lower/construction.rs +++ b/naga/src/front/wgsl/lower/construction.rs @@ -530,11 +530,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { // Bad conversion (type cast) (Components::One { span, ty_inner, .. }, constructor) => { - let from_type = ty_inner.to_wgsl(&ctx.module.to_ctx()); + let from_type = ty_inner.to_wgsl(&ctx.module.to_ctx()).into(); return Err(Error::BadTypeCast { span, from_type, - to_type: constructor.to_error_string(ctx), + to_type: constructor.to_error_string(ctx).into(), }); } diff --git a/naga/src/front/wgsl/lower/conversion.rs b/naga/src/front/wgsl/lower/conversion.rs index 2a2690f09..0b2f88463 100644 --- a/naga/src/front/wgsl/lower/conversion.rs +++ b/naga/src/front/wgsl/lower/conversion.rs @@ -1,5 +1,8 @@ //! WGSL's automatic conversions for abstract types. +use crate::front::wgsl::error::{ + AutoConversionError, AutoConversionLeafScalarError, ConcretizationFailedError, +}; use crate::{Handle, Span}; impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { @@ -39,15 +42,17 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { Some(scalars) => scalars, None => { let gctx = &self.module.to_ctx(); - let source_type = expr_resolution.to_wgsl(gctx); - let dest_type = goal_ty.to_wgsl(gctx); + let source_type = expr_resolution.to_wgsl(gctx).into(); + let dest_type = goal_ty.to_wgsl(gctx).into(); - return Err(super::Error::AutoConversion { - dest_span: goal_span, - dest_type, - source_span: expr_span, - source_type, - }); + return Err(super::Error::AutoConversion(Box::new( + AutoConversionError { + dest_span: goal_span, + dest_type, + source_span: expr_span, + source_type, + }, + ))); } }; @@ -79,13 +84,13 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { let make_error = || { let gctx = &self.module.to_ctx(); - let source_type = expr_resolution.to_wgsl(gctx); - super::Error::AutoConversionLeafScalar { + let source_type = expr_resolution.to_wgsl(gctx).into(); + super::Error::AutoConversionLeafScalar(Box::new(AutoConversionLeafScalarError { dest_span: goal_span, - dest_scalar: goal_scalar.to_wgsl(), + dest_scalar: goal_scalar.to_wgsl().into(), source_span: expr_span, source_type, - } + })) }; let expr_scalar = match expr_inner.scalar() { @@ -116,7 +121,7 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { if let crate::TypeInner::Array { .. } = *expr_inner { self.as_const_evaluator() .cast_array(expr, goal_scalar, expr_span) - .map_err(|err| super::Error::ConstantEvaluatorError(err, expr_span)) + .map_err(|err| super::Error::ConstantEvaluatorError(err.into(), expr_span)) } else { let cast = crate::Expression::As { expr, @@ -254,12 +259,12 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { // it has one. Also, avoid holding the borrow of `inner` // across the call to `cast_array`. let expr_type = &self.typifier()[expr]; - super::Error::ConcretizationFailed { + super::Error::ConcretizationFailed(Box::new(ConcretizationFailedError { expr_span, - expr_type: expr_type.to_wgsl(&self.module.to_ctx()), - scalar: concretized.to_wgsl(), + expr_type: expr_type.to_wgsl(&self.module.to_ctx()).into(), + scalar: concretized.to_wgsl().into(), inner: err, - } + })) })?; } } diff --git a/naga/src/front/wgsl/lower/mod.rs b/naga/src/front/wgsl/lower/mod.rs index 34f8daf50..ceed9c399 100644 --- a/naga/src/front/wgsl/lower/mod.rs +++ b/naga/src/front/wgsl/lower/mod.rs @@ -397,7 +397,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> { ) -> Result, Error<'source>> { let mut eval = self.as_const_evaluator(); eval.try_eval_and_append(expr, span) - .map_err(|e| Error::ConstantEvaluatorError(e, span)) + .map_err(|e| Error::ConstantEvaluatorError(e.into(), span)) } fn const_access(&self, handle: Handle) -> Option { @@ -945,15 +945,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let converted = ectx .try_automatic_conversions(lowered, &ty_res, v.name.span) .map_err(|error| match error { - Error::AutoConversion { - dest_span: _, - dest_type, - source_span: _, - source_type, - } => Error::InitializationTypeMismatch { + Error::AutoConversion(e) => Error::InitializationTypeMismatch { name: v.name.span, - expected: dest_type, - got: source_type, + expected: e.dest_type, + got: e.source_type, }, other => other, })?; @@ -997,15 +992,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { init = ectx .try_automatic_conversions(init, &explicit_ty_res, c.name.span) .map_err(|error| match error { - Error::AutoConversion { - dest_span: _, - dest_type, - source_span: _, - source_type, - } => Error::InitializationTypeMismatch { + Error::AutoConversion(e) => Error::InitializationTypeMismatch { name: c.name.span, - expected: dest_type, - got: source_type, + expected: e.dest_type, + got: e.source_type, }, other => other, })?; @@ -1061,8 +1051,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let gctx = ctx.module.to_ctx(); return Err(Error::InitializationTypeMismatch { name: o.name.span, - expected: explicit_ty.to_wgsl(&gctx), - got: inferred_type.to_wgsl(&gctx), + expected: explicit_ty.to_wgsl(&gctx).into(), + got: inferred_type.to_wgsl(&gctx).into(), }); } } @@ -1271,8 +1261,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let gctx = &ctx.module.to_ctx(); return Err(Error::InitializationTypeMismatch { name: l.name.span, - expected: ty.to_wgsl(gctx), - got: init_ty.to_wgsl(gctx), + expected: ty.to_wgsl(gctx).into(), + got: init_ty.to_wgsl(gctx).into(), }); } } @@ -1302,15 +1292,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let init = ectx .try_automatic_conversions(init, &ty_res, v.name.span) .map_err(|error| match error { - Error::AutoConversion { - dest_span: _, - dest_type, - source_span: _, - source_type, - } => Error::InitializationTypeMismatch { + Error::AutoConversion(e) => Error::InitializationTypeMismatch { name: v.name.span, - expected: dest_type, - got: source_type, + expected: e.dest_type, + got: e.source_type, }, other => other, })?; @@ -1854,9 +1839,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> { let ty = resolve!(ctx, expr); let gctx = &ctx.module.to_ctx(); return Err(Error::BadTypeCast { - from_type: ty.to_wgsl(gctx), + from_type: ty.to_wgsl(gctx).into(), span: ty_span, - to_type: to_resolved.to_wgsl(gctx), + to_type: to_resolved.to_wgsl(gctx).into(), }); } };