Reduce size of parse error

This commit is contained in:
Kornel 2024-08-23 14:59:56 +01:00 committed by Teodor Tanasoaia
parent a93dcb646a
commit c7e5d07dee
4 changed files with 129 additions and 112 deletions

View File

@ -10,6 +10,9 @@ use std::ops::Range;
use termcolor::{ColorChoice, NoColor, StandardStream}; use termcolor::{ColorChoice, NoColor, StandardStream};
use thiserror::Error; use thiserror::Error;
#[cfg(test)]
use std::mem::size_of;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct ParseError { pub struct ParseError {
message: String, message: String,
@ -144,7 +147,7 @@ pub enum InvalidAssignmentType {
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub enum Error<'a> { pub(crate) enum Error<'a> {
Unexpected(Span, ExpectedToken<'a>), Unexpected(Span, ExpectedToken<'a>),
UnexpectedComponents(Span), UnexpectedComponents(Span),
UnexpectedOperationInConstContext(Span), UnexpectedOperationInConstContext(Span),
@ -154,8 +157,8 @@ pub enum Error<'a> {
BadTexture(Span), BadTexture(Span),
BadTypeCast { BadTypeCast {
span: Span, span: Span,
from_type: String, from_type: Box<str>,
to_type: String, to_type: Box<str>,
}, },
BadTextureSampleType { BadTextureSampleType {
span: Span, span: Span,
@ -188,8 +191,8 @@ pub enum Error<'a> {
TypeNotInferable(Span), TypeNotInferable(Span),
InitializationTypeMismatch { InitializationTypeMismatch {
name: Span, name: Span,
expected: String, expected: Box<str>,
got: String, got: Box<str>,
}, },
DeclMissingTypeAndInit(Span), DeclMissingTypeAndInit(Span),
MissingAttribute(&'static str, Span), MissingAttribute(&'static str, Span),
@ -232,7 +235,7 @@ pub enum Error<'a> {
/// name is `decl` has an identifier at `reference` whose definition is /// name is `decl` has an identifier at `reference` whose definition is
/// the next declaration in the cycle. The last pair's `reference` is /// the next declaration in the cycle. The last pair's `reference` is
/// the same identifier as `ident`, above. /// the same identifier as `ident`, above.
path: Vec<(Span, Span)>, path: Box<[(Span, Span)]>,
}, },
InvalidSwitchValue { InvalidSwitchValue {
uint: bool, uint: bool,
@ -251,25 +254,10 @@ pub enum Error<'a> {
ExpectedNonNegative(Span), ExpectedNonNegative(Span),
ExpectedPositiveArrayLength(Span), ExpectedPositiveArrayLength(Span),
MissingWorkgroupSize(Span), MissingWorkgroupSize(Span),
ConstantEvaluatorError(ConstantEvaluatorError, Span), ConstantEvaluatorError(Box<ConstantEvaluatorError>, Span),
AutoConversion { AutoConversion(Box<AutoConversionError>),
dest_span: Span, AutoConversionLeafScalar(Box<AutoConversionLeafScalarError>),
dest_type: String, ConcretizationFailed(Box<ConcretizationFailedError>),
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,
},
ExceededLimitForNestedBraces { ExceededLimitForNestedBraces {
span: Span, span: Span,
limit: u8, limit: u8,
@ -277,6 +265,30 @@ pub enum Error<'a> {
PipelineConstantIDValue(Span), PipelineConstantIDValue(Span),
} }
#[derive(Clone, Debug)]
pub(crate) struct AutoConversionError {
pub dest_span: Span,
pub dest_type: Box<str>,
pub source_span: Span,
pub source_type: Box<str>,
}
#[derive(Clone, Debug)]
pub(crate) struct AutoConversionLeafScalarError {
pub dest_span: Span,
pub dest_scalar: Box<str>,
pub source_span: Span,
pub source_type: Box<str>,
}
#[derive(Clone, Debug)]
pub(crate) struct ConcretizationFailedError {
pub expr_span: Span,
pub expr_type: Box<str>,
pub scalar: Box<str>,
pub inner: ConstantEvaluatorError,
}
impl<'a> Error<'a> { impl<'a> Error<'a> {
#[cold] #[cold]
#[inline(never)] #[inline(never)]
@ -738,45 +750,55 @@ impl<'a> Error<'a> {
)], )],
notes: vec![], notes: vec![],
}, },
Error::AutoConversion { dest_span, ref dest_type, source_span, ref source_type } => ParseError { Error::AutoConversion(ref error) => {
message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"), // destructuring ensures all fields are handled
labels: vec![ let AutoConversionError { dest_span, ref dest_type, source_span, ref source_type } = **error;
( ParseError {
dest_span, message: format!("automatic conversions cannot convert `{source_type}` to `{dest_type}`"),
format!("a value of type {dest_type} is required here").into(), labels: vec![
), (
( dest_span,
source_span, format!("a value of type {dest_type} is required here").into(),
format!("this expression has type {source_type}").into(), ),
) (
], source_span,
notes: vec![], format!("this expression has type {source_type}").into(),
)
],
notes: vec![],
}
}, },
Error::AutoConversionLeafScalar { dest_span, ref dest_scalar, source_span, ref source_type } => ParseError { Error::AutoConversionLeafScalar(ref error) => {
message: format!("automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"), let AutoConversionLeafScalarError { dest_span, ref dest_scalar, source_span, ref source_type } = **error;
labels: vec![ ParseError {
( message: format!("automatic conversions cannot convert elements of `{source_type}` to `{dest_scalar}`"),
dest_span, labels: vec![
format!("a value with elements of type {dest_scalar} is required here").into(), (
), 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(), (
) source_span,
], format!("this expression has type {source_type}").into(),
notes: vec![], )
],
notes: vec![],
}
}, },
Error::ConcretizationFailed { expr_span, ref expr_type, ref scalar, ref inner } => ParseError { Error::ConcretizationFailed(ref error) => {
message: format!("failed to convert expression to a concrete type: {}", inner), let ConcretizationFailedError { expr_span, ref expr_type, ref scalar, ref inner } = **error;
labels: vec![ ParseError {
( message: format!("failed to convert expression to a concrete type: {}", inner),
expr_span, labels: vec![
format!("this expression has type {}", expr_type).into(), (
) expr_span,
], format!("this expression has type {}", expr_type).into(),
notes: vec![ )
format!("the expression should have been converted to have {} scalar type", scalar), ],
] notes: vec![
format!("the expression should have been converted to have {} scalar type", scalar),
]
}
}, },
Error::ExceededLimitForNestedBraces { span, limit } => ParseError { Error::ExceededLimitForNestedBraces { span, limit } => ParseError {
message: "brace nesting limit reached".into(), message: "brace nesting limit reached".into(),
@ -796,3 +818,8 @@ impl<'a> Error<'a> {
} }
} }
} }
#[test]
fn test_error_size() {
assert!(size_of::<Error<'_>>() <= 48);
}

View File

@ -530,11 +530,11 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
// Bad conversion (type cast) // Bad conversion (type cast)
(Components::One { span, ty_inner, .. }, constructor) => { (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 { return Err(Error::BadTypeCast {
span, span,
from_type, from_type,
to_type: constructor.to_error_string(ctx), to_type: constructor.to_error_string(ctx).into(),
}); });
} }

View File

@ -1,5 +1,8 @@
//! WGSL's automatic conversions for abstract types. //! WGSL's automatic conversions for abstract types.
use crate::front::wgsl::error::{
AutoConversionError, AutoConversionLeafScalarError, ConcretizationFailedError,
};
use crate::{Handle, Span}; use crate::{Handle, Span};
impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> { 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, Some(scalars) => scalars,
None => { None => {
let gctx = &self.module.to_ctx(); let gctx = &self.module.to_ctx();
let source_type = expr_resolution.to_wgsl(gctx); let source_type = expr_resolution.to_wgsl(gctx).into();
let dest_type = goal_ty.to_wgsl(gctx); let dest_type = goal_ty.to_wgsl(gctx).into();
return Err(super::Error::AutoConversion { return Err(super::Error::AutoConversion(Box::new(
dest_span: goal_span, AutoConversionError {
dest_type, dest_span: goal_span,
source_span: expr_span, dest_type,
source_type, source_span: expr_span,
}); source_type,
},
)));
} }
}; };
@ -79,13 +84,13 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> {
let make_error = || { let make_error = || {
let gctx = &self.module.to_ctx(); let gctx = &self.module.to_ctx();
let source_type = expr_resolution.to_wgsl(gctx); let source_type = expr_resolution.to_wgsl(gctx).into();
super::Error::AutoConversionLeafScalar { super::Error::AutoConversionLeafScalar(Box::new(AutoConversionLeafScalarError {
dest_span: goal_span, dest_span: goal_span,
dest_scalar: goal_scalar.to_wgsl(), dest_scalar: goal_scalar.to_wgsl().into(),
source_span: expr_span, source_span: expr_span,
source_type, source_type,
} }))
}; };
let expr_scalar = match expr_inner.scalar() { 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 { if let crate::TypeInner::Array { .. } = *expr_inner {
self.as_const_evaluator() self.as_const_evaluator()
.cast_array(expr, goal_scalar, expr_span) .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 { } else {
let cast = crate::Expression::As { let cast = crate::Expression::As {
expr, expr,
@ -254,12 +259,12 @@ impl<'source, 'temp, 'out> super::ExpressionContext<'source, 'temp, 'out> {
// it has one. Also, avoid holding the borrow of `inner` // it has one. Also, avoid holding the borrow of `inner`
// across the call to `cast_array`. // across the call to `cast_array`.
let expr_type = &self.typifier()[expr]; let expr_type = &self.typifier()[expr];
super::Error::ConcretizationFailed { super::Error::ConcretizationFailed(Box::new(ConcretizationFailedError {
expr_span, expr_span,
expr_type: expr_type.to_wgsl(&self.module.to_ctx()), expr_type: expr_type.to_wgsl(&self.module.to_ctx()).into(),
scalar: concretized.to_wgsl(), scalar: concretized.to_wgsl().into(),
inner: err, inner: err,
} }))
})?; })?;
} }
} }

View File

@ -397,7 +397,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
) -> Result<Handle<crate::Expression>, Error<'source>> { ) -> Result<Handle<crate::Expression>, Error<'source>> {
let mut eval = self.as_const_evaluator(); let mut eval = self.as_const_evaluator();
eval.try_eval_and_append(expr, span) 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<crate::Expression>) -> Option<u32> { fn const_access(&self, handle: Handle<crate::Expression>) -> Option<u32> {
@ -945,15 +945,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let converted = ectx let converted = ectx
.try_automatic_conversions(lowered, &ty_res, v.name.span) .try_automatic_conversions(lowered, &ty_res, v.name.span)
.map_err(|error| match error { .map_err(|error| match error {
Error::AutoConversion { Error::AutoConversion(e) => Error::InitializationTypeMismatch {
dest_span: _,
dest_type,
source_span: _,
source_type,
} => Error::InitializationTypeMismatch {
name: v.name.span, name: v.name.span,
expected: dest_type, expected: e.dest_type,
got: source_type, got: e.source_type,
}, },
other => other, other => other,
})?; })?;
@ -997,15 +992,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
init = ectx init = ectx
.try_automatic_conversions(init, &explicit_ty_res, c.name.span) .try_automatic_conversions(init, &explicit_ty_res, c.name.span)
.map_err(|error| match error { .map_err(|error| match error {
Error::AutoConversion { Error::AutoConversion(e) => Error::InitializationTypeMismatch {
dest_span: _,
dest_type,
source_span: _,
source_type,
} => Error::InitializationTypeMismatch {
name: c.name.span, name: c.name.span,
expected: dest_type, expected: e.dest_type,
got: source_type, got: e.source_type,
}, },
other => other, other => other,
})?; })?;
@ -1061,8 +1051,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let gctx = ctx.module.to_ctx(); let gctx = ctx.module.to_ctx();
return Err(Error::InitializationTypeMismatch { return Err(Error::InitializationTypeMismatch {
name: o.name.span, name: o.name.span,
expected: explicit_ty.to_wgsl(&gctx), expected: explicit_ty.to_wgsl(&gctx).into(),
got: inferred_type.to_wgsl(&gctx), got: inferred_type.to_wgsl(&gctx).into(),
}); });
} }
} }
@ -1271,8 +1261,8 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let gctx = &ctx.module.to_ctx(); let gctx = &ctx.module.to_ctx();
return Err(Error::InitializationTypeMismatch { return Err(Error::InitializationTypeMismatch {
name: l.name.span, name: l.name.span,
expected: ty.to_wgsl(gctx), expected: ty.to_wgsl(gctx).into(),
got: init_ty.to_wgsl(gctx), got: init_ty.to_wgsl(gctx).into(),
}); });
} }
} }
@ -1302,15 +1292,10 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let init = ectx let init = ectx
.try_automatic_conversions(init, &ty_res, v.name.span) .try_automatic_conversions(init, &ty_res, v.name.span)
.map_err(|error| match error { .map_err(|error| match error {
Error::AutoConversion { Error::AutoConversion(e) => Error::InitializationTypeMismatch {
dest_span: _,
dest_type,
source_span: _,
source_type,
} => Error::InitializationTypeMismatch {
name: v.name.span, name: v.name.span,
expected: dest_type, expected: e.dest_type,
got: source_type, got: e.source_type,
}, },
other => other, other => other,
})?; })?;
@ -1854,9 +1839,9 @@ impl<'source, 'temp> Lowerer<'source, 'temp> {
let ty = resolve!(ctx, expr); let ty = resolve!(ctx, expr);
let gctx = &ctx.module.to_ctx(); let gctx = &ctx.module.to_ctx();
return Err(Error::BadTypeCast { return Err(Error::BadTypeCast {
from_type: ty.to_wgsl(gctx), from_type: ty.to_wgsl(gctx).into(),
span: ty_span, span: ty_span,
to_type: to_resolved.to_wgsl(gctx), to_type: to_resolved.to_wgsl(gctx).into(),
}); });
} }
}; };