[naga wgsl] New TypeContext method write_unnamed_struct.

When asked to generate WGSL for `TypeInner::Struct`, rather than
unconditionally calling `unreachable!`, defer to a new `TypeContext`
method, `write_unnamed_struct`.

Provide appropriate `write_unnamed_struct` implementations:

- In the WGSL backend, implement this as `unreachable!`, since the WGSL
  backend should always know the proper name to use for a struct.

- For diagnostic messages, generate something human-readable that
  indicates that some struct type was encountered.

- For logging and debugging, defer to `TypeInner`'s `Debug`
  implementation.
This commit is contained in:
Jim Blandy 2025-04-09 12:47:50 -07:00 committed by Erich Gubler
parent 25f03960e1
commit aad187f52f
3 changed files with 29 additions and 1 deletions

View File

@ -1764,6 +1764,10 @@ impl TypeContext for WriterTypeContext<'_> {
self.names[&NameKey::Type(handle)].as_str()
}
fn write_unnamed_struct<W: Write>(&self, _: &TypeInner, _: &mut W) -> core::fmt::Result {
unreachable!("the WGSL back end should always provide type handles");
}
fn write_override<W: Write>(&self, _: Handle<crate::Override>, _: &mut W) -> core::fmt::Result {
unreachable!("overrides should be validated out");
}

View File

@ -39,6 +39,14 @@ pub trait TypeContext {
out: &mut W,
) -> core::fmt::Result;
/// Write a [`TypeInner::Struct`] for which we are unable to find a name.
///
/// The names of struct types are only available if we have `Handle<Type>`,
/// not from [`TypeInner`]. For logging and debugging, it's fine to just
/// write something helpful to the developer, but for generating WGSL,
/// this should be unreachable.
fn write_unnamed_struct<W: Write>(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result;
/// Write a [`TypeInner`] that has no representation as WGSL source,
/// even including Naga extensions.
///
@ -363,7 +371,7 @@ where
write!(out, "acceleration_structure{}", caps)?
}
TypeInner::Struct { .. } => {
unreachable!("structs can only be referenced by name in WGSL");
ctx.write_unnamed_struct(inner, out)?;
}
TypeInner::RayQuery { vertex_return } => {
let caps = if vertex_return { "<vertex_return>" } else { "" };
@ -414,6 +422,10 @@ impl TypeContext for crate::proc::GlobalCtx<'_> {
.unwrap_or("{anonymous type}")
}
fn write_unnamed_struct<W: Write>(&self, _: &TypeInner, out: &mut W) -> core::fmt::Result {
write!(out, "{{unnamed struct}}")
}
fn write_override<W: Write>(
&self,
handle: Handle<crate::Override>,
@ -446,6 +458,10 @@ impl TypeContext for crate::UniqueArena<crate::Type> {
self[handle].name.as_deref().unwrap_or("{anonymous type}")
}
fn write_unnamed_struct<W: Write>(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result {
write!(out, "{{unnamed struct {inner:?}}}")
}
fn write_override<W: Write>(
&self,
handle: Handle<crate::Override>,

View File

@ -412,6 +412,14 @@ impl TypeContext for ExpressionContext<'_, '_, '_> {
None => write!(out, "{{anonymous override {handle:?}}}"),
}
}
fn write_unnamed_struct<W: core::fmt::Write>(
&self,
_: &crate::TypeInner,
_: &mut W,
) -> core::fmt::Result {
unreachable!("the WGSL front end should always know the type name");
}
}
impl<'source, 'temp, 'out> ExpressionContext<'source, 'temp, 'out> {