Skip to content

Commit bf8cc43

Browse files
bushrat011899cwfitzgeraldErichDonGubler
authored
Add stderr and termcolor features to Naga (#7482)
Co-authored-by: Connor Fitzgerald <connorwadefitzgerald@gmail.com> Co-authored-by: Erich Gubler <erichdongubler@gmail.com>
1 parent 6666d52 commit bf8cc43

File tree

12 files changed

+144
-42
lines changed

12 files changed

+144
-42
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -351,6 +351,7 @@ By @cwfitzgerald in [#6811](https://github.com/gfx-rs/wgpu/pull/6811), [#6815](h
351351
- Refactored `use` statements to simplify future `no_std` support. By @bushrat011899 in [#7256](https://github.com/gfx-rs/wgpu/pull/7256)
352352
- Naga's WGSL frontend no longer allows using the `&` operator to take the address of a component of a vector,
353353
which is not permitted by the WGSL specification. By @andyleiserson in [#7284](https://github.com/gfx-rs/wgpu/pull/7284)
354+
- Naga's use of `termcolor` and `stderr` are now optional behind features of the same names. By @bushrat011899 in [#7482](https://github.com/gfx-rs/wgpu/pull/7482)
354355

355356
#### Vulkan
356357

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

naga-cli/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ naga = { workspace = true, features = [
3737
"dot-out",
3838
"serialize",
3939
"deserialize",
40+
"termcolor",
41+
"stderr",
4042
] }
4143

4244
bincode.workspace = true

naga/Cargo.toml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,19 @@ hlsl-out-if-target-windows = []
8080

8181
compact = []
8282

83+
## Enables colored output through codespan-reporting and termcolor.
84+
termcolor = ["codespan-reporting/termcolor"]
85+
86+
## Enables writing output to stderr.
87+
stderr = ["codespan-reporting/std"]
88+
8389
[dependencies]
8490
arbitrary = { version = "1.4", features = ["derive"], optional = true }
8591
arrayvec.workspace = true
8692
bitflags.workspace = true
8793
bit-set.workspace = true
88-
codespan-reporting = { workspace = true, default-features = false, features = [
89-
"std",
90-
"termcolor",
91-
] }
94+
cfg-if.workspace = true
95+
codespan-reporting = { workspace = true, default-features = false }
9296
hashbrown.workspace = true
9397
half = { workspace = true, default-features = false, features = ["num-traits"] }
9498
rustc-hash.workspace = true

naga/src/error.rs

Lines changed: 81 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use alloc::{boxed::Box, string::String, vec::Vec};
1+
use alloc::{boxed::Box, string::String};
22
use core::{error::Error, fmt};
33

44
#[derive(Clone, Debug)]
@@ -43,14 +43,88 @@ impl fmt::Display for ShaderError<crate::WithSpan<crate::valid::ValidationError>
4343
let label = self.label.as_deref().unwrap_or_default();
4444
let files = SimpleFile::new(label, &self.source);
4545
let config = term::Config::default();
46-
let mut writer = term::termcolor::NoColor::new(Vec::new());
47-
term::emit(&mut writer, &config, &files, &self.inner.diagnostic())
46+
47+
let writer = {
48+
let mut writer = DiagnosticBuffer::new();
49+
term::emit(
50+
writer.inner_mut(),
51+
&config,
52+
&files,
53+
&self.inner.diagnostic(),
54+
)
4855
.expect("cannot write error");
49-
write!(
50-
f,
51-
"\nShader validation {}",
52-
String::from_utf8_lossy(&writer.into_inner())
56+
writer.into_string()
57+
};
58+
59+
write!(f, "\nShader validation {}", writer)
60+
}
61+
}
62+
63+
cfg_if::cfg_if! {
64+
if #[cfg(feature = "termcolor")] {
65+
type DiagnosticBufferInner = codespan_reporting::term::termcolor::NoColor<alloc::vec::Vec<u8>>;
66+
pub(crate) use codespan_reporting::term::termcolor::WriteColor as _ErrorWrite;
67+
} else if #[cfg(feature = "stderr")] {
68+
type DiagnosticBufferInner = alloc::vec::Vec<u8>;
69+
pub(crate) use std::io::Write as _ErrorWrite;
70+
} else {
71+
type DiagnosticBufferInner = String;
72+
pub(crate) use core::fmt::Write as _ErrorWrite;
73+
}
74+
}
75+
76+
// Using this indirect export to avoid duplicating the expect(...) for all three cases above.
77+
#[cfg_attr(
78+
not(any(feature = "spv-in", feature = "glsl-in")),
79+
expect(
80+
unused_imports,
81+
reason = "only need `ErrorWrite` with an appropriate front-end."
82+
)
83+
)]
84+
pub(crate) use _ErrorWrite as ErrorWrite;
85+
86+
pub(crate) struct DiagnosticBuffer {
87+
inner: DiagnosticBufferInner,
88+
}
89+
90+
impl DiagnosticBuffer {
91+
#[cfg_attr(
92+
not(feature = "termcolor"),
93+
expect(
94+
clippy::missing_const_for_fn,
95+
reason = "`NoColor::new` isn't `const`, but other `inner`s are."
5396
)
97+
)]
98+
pub fn new() -> Self {
99+
cfg_if::cfg_if! {
100+
if #[cfg(feature = "termcolor")] {
101+
let inner = codespan_reporting::term::termcolor::NoColor::new(alloc::vec::Vec::new());
102+
} else if #[cfg(feature = "stderr")] {
103+
let inner = alloc::vec::Vec::new();
104+
} else {
105+
let inner = String::new();
106+
}
107+
};
108+
109+
Self { inner }
110+
}
111+
112+
pub fn inner_mut(&mut self) -> &mut DiagnosticBufferInner {
113+
&mut self.inner
114+
}
115+
116+
pub fn into_string(self) -> String {
117+
let Self { inner } = self;
118+
119+
cfg_if::cfg_if! {
120+
if #[cfg(feature = "termcolor")] {
121+
String::from_utf8(inner.into_inner()).unwrap()
122+
} else if #[cfg(feature = "stderr")] {
123+
String::from_utf8(inner).unwrap()
124+
} else {
125+
inner
126+
}
127+
}
54128
}
55129
}
56130

naga/src/front/glsl/error.rs

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,12 @@ use alloc::{
88
use codespan_reporting::diagnostic::{Diagnostic, Label};
99
use codespan_reporting::files::SimpleFile;
1010
use codespan_reporting::term;
11-
use codespan_reporting::term::termcolor::{NoColor, WriteColor};
1211
use pp_rs::token::PreprocessorError;
1312
use thiserror::Error;
1413

1514
use super::token::TokenValue;
1615
use crate::SourceLocation;
17-
use crate::{proc::ConstantEvaluatorError, Span};
16+
use crate::{error::ErrorWrite, proc::ConstantEvaluatorError, Span};
1817

1918
fn join_with_comma(list: &[ExpectedToken]) -> String {
2019
let mut string = "".to_string();
@@ -166,11 +165,11 @@ pub struct ParseErrors {
166165
}
167166

168167
impl ParseErrors {
169-
pub fn emit_to_writer(&self, writer: &mut impl WriteColor, source: &str) {
168+
pub fn emit_to_writer(&self, writer: &mut impl ErrorWrite, source: &str) {
170169
self.emit_to_writer_with_path(writer, source, "glsl");
171170
}
172171

173-
pub fn emit_to_writer_with_path(&self, writer: &mut impl WriteColor, source: &str, path: &str) {
172+
pub fn emit_to_writer_with_path(&self, writer: &mut impl ErrorWrite, source: &str, path: &str) {
174173
let path = path.to_string();
175174
let files = SimpleFile::new(path, source);
176175
let config = term::Config::default();
@@ -187,9 +186,9 @@ impl ParseErrors {
187186
}
188187

189188
pub fn emit_to_string(&self, source: &str) -> String {
190-
let mut writer = NoColor::new(Vec::new());
191-
self.emit_to_writer(&mut writer, source);
192-
String::from_utf8(writer.into_inner()).unwrap()
189+
let mut writer = crate::error::DiagnosticBuffer::new();
190+
self.emit_to_writer(writer.inner_mut(), source);
191+
writer.into_string()
193192
}
194193
}
195194

naga/src/front/spv/error.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,14 @@
11
use alloc::{
22
format,
33
string::{String, ToString},
4-
vec::Vec,
54
};
65

76
use codespan_reporting::diagnostic::Diagnostic;
87
use codespan_reporting::files::SimpleFile;
98
use codespan_reporting::term;
10-
use codespan_reporting::term::termcolor::{NoColor, WriteColor};
119

1210
use super::ModuleState;
13-
use crate::{arena::Handle, front::atomic_upgrade};
11+
use crate::{arena::Handle, error::ErrorWrite, front::atomic_upgrade};
1412

1513
#[derive(Clone, Debug, thiserror::Error)]
1614
pub enum Error {
@@ -153,11 +151,11 @@ pub enum Error {
153151
}
154152

155153
impl Error {
156-
pub fn emit_to_writer(&self, writer: &mut impl WriteColor, source: &str) {
154+
pub fn emit_to_writer(&self, writer: &mut impl ErrorWrite, source: &str) {
157155
self.emit_to_writer_with_path(writer, source, "glsl");
158156
}
159157

160-
pub fn emit_to_writer_with_path(&self, writer: &mut impl WriteColor, source: &str, path: &str) {
158+
pub fn emit_to_writer_with_path(&self, writer: &mut impl ErrorWrite, source: &str, path: &str) {
161159
let path = path.to_string();
162160
let files = SimpleFile::new(path, source);
163161
let config = term::Config::default();
@@ -167,9 +165,9 @@ impl Error {
167165
}
168166

169167
pub fn emit_to_string(&self, source: &str) -> String {
170-
let mut writer = NoColor::new(Vec::new());
171-
self.emit_to_writer(&mut writer, source);
172-
String::from_utf8(writer.into_inner()).unwrap()
168+
let mut writer = crate::error::DiagnosticBuffer::new();
169+
self.emit_to_writer(writer.inner_mut(), source);
170+
writer.into_string()
173171
}
174172
}
175173

naga/src/front/wgsl/error.rs

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ use super::parse::lexer::Token;
1414
use codespan_reporting::diagnostic::{Diagnostic, Label};
1515
use codespan_reporting::files::SimpleFile;
1616
use codespan_reporting::term;
17-
use codespan_reporting::term::termcolor::{ColorChoice, NoColor, StandardStream};
1817
use thiserror::Error;
1918

2019
use alloc::{
@@ -68,19 +67,29 @@ impl ParseError {
6867
}
6968

7069
/// Emits a summary of the error to standard error stream.
70+
#[cfg(feature = "stderr")]
7171
pub fn emit_to_stderr(&self, source: &str) {
7272
self.emit_to_stderr_with_path(source, "wgsl")
7373
}
7474

7575
/// Emits a summary of the error to standard error stream.
76+
#[cfg(feature = "stderr")]
7677
pub fn emit_to_stderr_with_path<P>(&self, source: &str, path: P)
7778
where
7879
P: AsRef<std::path::Path>,
7980
{
8081
let path = path.as_ref().display().to_string();
8182
let files = SimpleFile::new(path, source);
8283
let config = term::Config::default();
83-
let writer = StandardStream::stderr(ColorChoice::Auto);
84+
85+
cfg_if::cfg_if! {
86+
if #[cfg(feature = "termcolor")] {
87+
let writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Auto);
88+
} else {
89+
let writer = std::io::stderr();
90+
}
91+
}
92+
8493
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
8594
.expect("cannot write error");
8695
}
@@ -98,9 +107,11 @@ impl ParseError {
98107
let path = path.as_ref().display().to_string();
99108
let files = SimpleFile::new(path, source);
100109
let config = term::Config::default();
101-
let mut writer = NoColor::new(Vec::new());
102-
term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
103-
String::from_utf8(writer.into_inner()).unwrap()
110+
111+
let mut writer = crate::error::DiagnosticBuffer::new();
112+
term::emit(writer.inner_mut(), &config, &files, &self.diagnostic())
113+
.expect("cannot write error");
114+
writer.into_string()
104115
}
105116

106117
/// Returns a [`SourceLocation`] for the first label in the error message.

naga/src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,9 @@ void main() {
110110
wgsl_out,
111111
112112
feature = "spv-in",
113-
feature = "wgsl-in"
113+
feature = "wgsl-in",
114+
115+
feature = "stderr",
114116
))]
115117
extern crate std;
116118

naga/src/span.rs

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,6 +273,7 @@ impl<E> WithSpan<E> {
273273
}
274274

275275
/// Emits a summary of the error to standard error stream.
276+
#[cfg(feature = "stderr")]
276277
pub fn emit_to_stderr(&self, source: &str)
277278
where
278279
E: Error,
@@ -281,16 +282,24 @@ impl<E> WithSpan<E> {
281282
}
282283

283284
/// Emits a summary of the error to standard error stream.
285+
#[cfg(feature = "stderr")]
284286
pub fn emit_to_stderr_with_path(&self, source: &str, path: &str)
285287
where
286288
E: Error,
287289
{
288-
use codespan_reporting::term::termcolor::{ColorChoice, StandardStream};
289290
use codespan_reporting::{files, term};
290291

291292
let files = files::SimpleFile::new(path, source);
292293
let config = term::Config::default();
293-
let writer = StandardStream::stderr(ColorChoice::Auto);
294+
295+
cfg_if::cfg_if! {
296+
if #[cfg(feature = "termcolor")] {
297+
let writer = term::termcolor::StandardStream::stderr(term::termcolor::ColorChoice::Auto);
298+
} else {
299+
let writer = std::io::stderr();
300+
}
301+
}
302+
294303
term::emit(&mut writer.lock(), &config, &files, &self.diagnostic())
295304
.expect("cannot write error");
296305
}
@@ -308,14 +317,15 @@ impl<E> WithSpan<E> {
308317
where
309318
E: Error,
310319
{
311-
use codespan_reporting::term::termcolor::NoColor;
312320
use codespan_reporting::{files, term};
313321

314322
let files = files::SimpleFile::new(path, source);
315323
let config = term::Config::default();
316-
let mut writer = NoColor::new(Vec::new());
317-
term::emit(&mut writer, &config, &files, &self.diagnostic()).expect("cannot write error");
318-
String::from_utf8(writer.into_inner()).unwrap()
324+
325+
let mut writer = crate::error::DiagnosticBuffer::new();
326+
term::emit(writer.inner_mut(), &config, &files, &self.diagnostic())
327+
.expect("cannot write error");
328+
writer.into_string()
319329
}
320330
}
321331

0 commit comments

Comments
 (0)