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 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<str>,
to_type: Box<str>,
},
BadTextureSampleType {
span: Span,
@ -188,8 +191,8 @@ pub enum Error<'a> {
TypeNotInferable(Span),
InitializationTypeMismatch {
name: Span,
expected: String,
got: String,
expected: Box<str>,
got: Box<str>,
},
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<ConstantEvaluatorError>, Span),
AutoConversion(Box<AutoConversionError>),
AutoConversionLeafScalar(Box<AutoConversionLeafScalarError>),
ConcretizationFailed(Box<ConcretizationFailedError>),
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<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> {
#[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::<Error<'_>>() <= 48);
}

View File

@ -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(),
});
}

View File

@ -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,
}
}))
})?;
}
}

View File

@ -397,7 +397,7 @@ impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {
) -> Result<Handle<crate::Expression>, 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<crate::Expression>) -> Option<u32> {
@ -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(),
});
}
};