Coverage Report

Created: 2026-10-28 06:31

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/wgpu/naga/src/common/diagnostic_display.rs
Line
Count
Source
1
//! Displaying Naga IR terms in diagnostic output.
2
3
use crate::proc::{GlobalCtx, Rule, TypeResolution};
4
use crate::{Handle, Scalar, Type};
5
6
#[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
7
use crate::common::wgsl::TypeContext;
8
9
use core::fmt;
10
11
/// A wrapper for displaying Naga IR terms in diagnostic output.
12
///
13
/// For some Naga IR type `T`, `DiagnosticDisplay<T>` implements
14
/// [`core::fmt::Display`] in a way that displays values of type `T`
15
/// appropriately for diagnostic messages presented to human readers.
16
///
17
/// For example, the implementation of [`Display`] for
18
/// `DiagnosticDisplay<Scalar>` formats the type represented by the
19
/// given [`Scalar`] appropriately for users.
20
///
21
/// Some types like `Handle<Type>` require contextual information like
22
/// a type arena to be displayed. In such cases, we implement [`Display`]
23
/// for a type like `DiagnosticDisplay<(Handle<Type>, GlobalCtx)>`, where
24
/// the [`GlobalCtx`] type provides the necessary context.
25
///
26
/// Do not implement this type for [`TypeInner`], as that does not
27
/// have enough information to display struct types correctly.
28
///
29
/// If you only need debugging output, [`DiagnosticDebug`] uses
30
/// easier-to-obtain context types but still does a good enough job
31
/// for logging or debugging.
32
///
33
/// [`Display`]: core::fmt::Display
34
/// [`GlobalCtx`]: crate::proc::GlobalCtx
35
/// [`TypeInner`]: crate::ir::TypeInner
36
/// [`DiagnosticDebug`]: super::DiagnosticDebug
37
///
38
/// ## Language-sensitive diagnostics
39
///
40
/// Diagnostic output ought to depend on the source language from
41
/// which the IR was produced: diagnostics resulting from processing
42
/// GLSL code should use GLSL type syntax, for example. That means
43
/// that `DiagnosticDisplay` ought to include some indication of which
44
/// notation to use.
45
///
46
/// For the moment, only WGSL output is implemented, so
47
/// `DiagnosticDisplay` lacks any support for this (#7268). However,
48
/// the plan is that all language-independent code in Naga should use
49
/// `DiagnosticDisplay` wherever appropriate, such that when its
50
/// definition is expanded to include some indication of the right
51
/// source language to use, any use site that does not supply this
52
/// indication will provoke a compile-time error.
53
#[expect(
54
    missing_debug_implementations,
55
    reason = "use this type with `Display`, not `Debug`"
56
)]
57
pub struct DiagnosticDisplay<T>(pub T);
58
59
impl fmt::Display for DiagnosticDisplay<(&TypeResolution, GlobalCtx<'_>)> {
60
2
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
61
2
        let (resolution, ctx) = self.0;
62
63
        #[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
64
2
        ctx.write_type_resolution(resolution, f)?;
65
66
        #[cfg(not(any(feature = "wgsl-in", feature = "wgsl-out")))]
67
        {
68
            let _ = ctx;
69
            write!(f, "{resolution:?}")?;
70
        }
71
72
2
        Ok(())
73
2
    }
74
}
75
76
impl fmt::Display for DiagnosticDisplay<(Handle<Type>, GlobalCtx<'_>)> {
77
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
78
0
        let (handle, ref ctx) = self.0;
79
80
        #[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
81
0
        ctx.write_type(handle, f)?;
82
83
        #[cfg(not(any(feature = "wgsl-in", feature = "wgsl-out")))]
84
        {
85
            let _ = ctx;
86
            write!(f, "{handle:?}")?;
87
        }
88
89
0
        Ok(())
90
0
    }
91
}
92
93
impl fmt::Display for DiagnosticDisplay<(&str, &Rule, GlobalCtx<'_>)> {
94
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95
0
        let (name, rule, ref ctx) = self.0;
96
97
        #[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
98
0
        ctx.write_type_rule(name, rule, f)?;
99
100
        #[cfg(not(any(feature = "wgsl-in", feature = "wgsl-out")))]
101
        {
102
            let _ = ctx;
103
            write!(f, "{name}({:?}) -> {:?}", rule.arguments, rule.conclusion)?;
104
        }
105
106
0
        Ok(())
107
0
    }
108
}
109
110
impl fmt::Display for DiagnosticDisplay<Scalar> {
111
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
112
0
        let scalar = self.0;
113
114
        #[cfg(any(feature = "wgsl-in", feature = "wgsl-out"))]
115
0
        f.write_str(&crate::common::wgsl::TryToWgsl::to_wgsl_for_diagnostics(
116
0
            scalar,
117
0
        ))?;
118
119
        #[cfg(not(any(feature = "wgsl-in", feature = "wgsl-out")))]
120
        write!(f, "{scalar:?}")?;
121
122
0
        Ok(())
123
0
    }
124
}