mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
[naga wgsl] Fix generics on naga::common::wgsl::TypeContext.
In `naga::common::wgsl::types`, move the type parameter `<W: Write>`
from the `TypeContext` trait itself to the individual methods of the
trait. It is very unlikely for Naga to need to be able to implement
`TypeContext`, but only for one particular kind of output stream.
The motivation for this change is that the old parameterization makes
it awkward to provide utility methods for generating `String`s on the
trait, which we do in subsequent commits. In order to write to a
`String`, such utility methods need `Self` to implement
`TypeContext<String>`, so you can add bounds to the methods like this:
fn type_to_string(..., out: &mut W) -> ...
where Self: TypeContext<String>
{
... self.write(..., &mut string_buf)?;
}
That will compile, but if you try to actually call it, Rust gets
confused. Remember, the above is not a method on
`TypeContext<String>`, it's a method on `TypeContext<W>` that uses
`TypeContext<String>` internally. So when you write
`ctx.type_to_string(...)`, Rust needs to decide whether `ctx`
implements `TypeContext<W>` for some completely unspecified `W`, and
asks for type annotations.
You could supply type annotations, but this would be basically
supplying some never-used type that implements `core::fmt::Write`.
Instead of
ctx.type_to_string(handle)
you'd have to write
TypeContext::<String>::type_to_string(ctx, handle)
which is dumb.
(I don't *think* this explanation belongs in the code, since it's an
explanation of a design *not* used, replaced by a design that's pretty
natural --- so I'll leave it here.)
This commit is contained in:
@@ -1726,7 +1726,7 @@ struct WriterTypeContext<'m> {
|
||||
names: &'m crate::FastHashMap<NameKey, String>,
|
||||
}
|
||||
|
||||
impl<W: Write> TypeContext<W> for WriterTypeContext<'_> {
|
||||
impl TypeContext for WriterTypeContext<'_> {
|
||||
fn lookup_type(&self, handle: Handle<crate::Type>) -> &crate::Type {
|
||||
&self.module.types[handle]
|
||||
}
|
||||
@@ -1735,15 +1735,15 @@ impl<W: Write> TypeContext<W> for WriterTypeContext<'_> {
|
||||
self.names[&NameKey::Type(handle)].as_str()
|
||||
}
|
||||
|
||||
fn write_override(&self, _: Handle<crate::Override>, _: &mut W) -> core::fmt::Result {
|
||||
fn write_override<W: Write>(&self, _: Handle<crate::Override>, _: &mut W) -> core::fmt::Result {
|
||||
unreachable!("overrides should be validated out");
|
||||
}
|
||||
|
||||
fn write_non_wgsl_inner(&self, _: &TypeInner, _: &mut W) -> core::fmt::Result {
|
||||
fn write_non_wgsl_inner<W: Write>(&self, _: &TypeInner, _: &mut W) -> core::fmt::Result {
|
||||
unreachable!("backends should only be passed validated modules");
|
||||
}
|
||||
|
||||
fn write_non_wgsl_scalar(&self, _: crate::Scalar, _: &mut W) -> core::fmt::Result {
|
||||
fn write_non_wgsl_scalar<W: Write>(&self, _: crate::Scalar, _: &mut W) -> core::fmt::Result {
|
||||
unreachable!("backends should only be passed validated modules");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ use core::fmt::Write;
|
||||
/// [`write_type`]: TypeContext::write_type
|
||||
/// [`write_type_inner`]: TypeContext::write_type_inner
|
||||
/// [`type_name`]: TypeContext::type_name
|
||||
pub trait TypeContext<W: Write> {
|
||||
pub trait TypeContext {
|
||||
/// Return the [`Type`] referred to by `handle`.
|
||||
///
|
||||
/// [`Type`]: crate::Type
|
||||
@@ -32,8 +32,11 @@ pub trait TypeContext<W: Write> {
|
||||
fn type_name(&self, handle: Handle<crate::Type>) -> &str;
|
||||
|
||||
/// Write the WGSL form of `override` to `out`.
|
||||
fn write_override(&self, r#override: Handle<crate::Override>, out: &mut W)
|
||||
-> core::fmt::Result;
|
||||
fn write_override<W: Write>(
|
||||
&self,
|
||||
r#override: Handle<crate::Override>,
|
||||
out: &mut W,
|
||||
) -> core::fmt::Result;
|
||||
|
||||
/// Write a [`TypeInner`] that has no representation as WGSL source,
|
||||
/// even including Naga extensions.
|
||||
@@ -43,7 +46,7 @@ pub trait TypeContext<W: Write> {
|
||||
/// validation, whereas something generating type names to appear in error messages
|
||||
/// might punt to `TypeInner`'s [`core::fmt::Debug`] implementation, since it's
|
||||
/// probably better to show the user something they can act on.
|
||||
fn write_non_wgsl_inner(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result;
|
||||
fn write_non_wgsl_inner<W: Write>(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result;
|
||||
|
||||
/// Write a [`Scalar`] that has no representation as WGSL source,
|
||||
/// even including Naga extensions.
|
||||
@@ -53,13 +56,13 @@ pub trait TypeContext<W: Write> {
|
||||
/// validation, whereas something generating type names to appear in error messages
|
||||
/// might punt to `Scalar`'s [`core::fmt::Debug`] implementation, since it's
|
||||
/// probably better to show the user something they can act on.
|
||||
fn write_non_wgsl_scalar(&self, scalar: Scalar, out: &mut W) -> core::fmt::Result;
|
||||
fn write_non_wgsl_scalar<W: Write>(&self, scalar: Scalar, out: &mut W) -> core::fmt::Result;
|
||||
|
||||
/// Write the type `ty` as it would appear in a value's declaration.
|
||||
///
|
||||
/// Write the type referred to by `ty` in `module` as it would appear in
|
||||
/// a `var`, `let`, etc. declaration, or in a function's argument list.
|
||||
fn write_type(&self, handle: Handle<crate::Type>, out: &mut W) -> core::fmt::Result {
|
||||
fn write_type<W: Write>(&self, handle: Handle<crate::Type>, out: &mut W) -> core::fmt::Result {
|
||||
let ty = self.lookup_type(handle);
|
||||
match ty.inner {
|
||||
TypeInner::Struct { .. } => out.write_str(self.type_name(handle))?,
|
||||
@@ -79,7 +82,7 @@ pub trait TypeContext<W: Write> {
|
||||
/// [`TypeInner`].
|
||||
///
|
||||
/// [`Struct`]: TypeInner::Struct
|
||||
fn write_type_inner(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result {
|
||||
fn write_type_inner<W: Write>(&self, inner: &TypeInner, out: &mut W) -> core::fmt::Result {
|
||||
match try_write_type_inner(self, inner, out) {
|
||||
Ok(()) => Ok(()),
|
||||
Err(WriteTypeError::Format(err)) => Err(err),
|
||||
@@ -88,7 +91,7 @@ pub trait TypeContext<W: Write> {
|
||||
}
|
||||
|
||||
/// Write the [`Scalar`] `scalar` as a WGSL type.
|
||||
fn write_scalar(&self, scalar: Scalar, out: &mut W) -> core::fmt::Result {
|
||||
fn write_scalar<W: Write>(&self, scalar: Scalar, out: &mut W) -> core::fmt::Result {
|
||||
match scalar.try_to_wgsl() {
|
||||
Some(string) => out.write_str(string),
|
||||
None => self.write_non_wgsl_scalar(scalar, out),
|
||||
@@ -96,7 +99,11 @@ pub trait TypeContext<W: Write> {
|
||||
}
|
||||
|
||||
/// Write the [`TypeResolution`] `resolution` as a WGSL type.
|
||||
fn write_type_resolution(&self, resolution: &TypeResolution, out: &mut W) -> core::fmt::Result {
|
||||
fn write_type_resolution<W: Write>(
|
||||
&self,
|
||||
resolution: &TypeResolution,
|
||||
out: &mut W,
|
||||
) -> core::fmt::Result {
|
||||
match *resolution {
|
||||
TypeResolution::Handle(handle) => self.write_type(handle, out),
|
||||
TypeResolution::Value(ref inner) => self.write_type_inner(inner, out),
|
||||
@@ -106,7 +113,7 @@ pub trait TypeContext<W: Write> {
|
||||
|
||||
fn try_write_type_inner<C, W>(ctx: &C, inner: &TypeInner, out: &mut W) -> Result<(), WriteTypeError>
|
||||
where
|
||||
C: TypeContext<W> + ?Sized,
|
||||
C: TypeContext + ?Sized,
|
||||
W: Write,
|
||||
{
|
||||
match *inner {
|
||||
|
||||
Reference in New Issue
Block a user