Skip to content

Commit dfd285e

Browse files
eddyboisyn
authored andcommitted
linker/test: create Session manually to inject a custom diagnostic writer.
1 parent 9d639d3 commit dfd285e

File tree

1 file changed

+72
-47
lines changed
  • crates/rustc_codegen_spirv/src/linker

1 file changed

+72
-47
lines changed

crates/rustc_codegen_spirv/src/linker/test.rs

Lines changed: 72 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,8 @@ use super::{link, LinkResult, Options};
22
use crate::codegen_cx::SpirvMetadata;
33
use pipe::pipe;
44
use rspirv::dr::{Loader, Module};
5-
use rustc_driver::handle_options;
65
use rustc_errors::registry::Registry;
7-
use rustc_session::config::build_session_options;
8-
use rustc_session::config::Input;
9-
use rustc_session::DiagnosticOutput;
106
use std::io::Read;
11-
use std::path::PathBuf;
127

138
// https://github.com/colin-kiegel/rust-pretty-assertions/issues/24
149
#[derive(PartialEq, Eq)]
@@ -62,60 +57,90 @@ fn load(bytes: &[u8]) -> Module {
6257
fn assemble_and_link(binaries: &[&[u8]]) -> Result<Module, PrettyString> {
6358
let modules = binaries.iter().cloned().map(load).collect::<Vec<_>>();
6459

65-
// need pipe here because Config takes ownership of the writer, and the writer must be 'static.
60+
// FIXME(eddyb) this seems ridiculous, we should be able to write to
61+
// some kind of `Arc<Mutex<Vec<u8>>>` without a separate thread.
62+
//
63+
// need pipe here because the writer must be 'static.
6664
let (mut read_diags, write_diags) = pipe();
6765
let read_diags_thread = std::thread::spawn(move || {
6866
// must spawn thread because pipe crate is synchronous
6967
let mut diags = String::new();
7068
read_diags.read_to_string(&mut diags).unwrap();
71-
let suffix = "\n\nerror: aborting due to previous error\n\n";
72-
if diags.ends_with(suffix) {
73-
diags.truncate(diags.len() - suffix.len());
69+
if let Some(diags_without_trailing_newlines) = diags.strip_suffix("\n\n") {
70+
diags.truncate(diags_without_trailing_newlines.len());
7471
}
7572
diags
7673
});
77-
let matches = handle_options(&["".to_string(), "x.rs".to_string()]).unwrap();
78-
let sopts = build_session_options(&matches);
79-
let config = rustc_interface::Config {
80-
opts: sopts,
81-
crate_cfg: Default::default(),
82-
crate_check_cfg: Default::default(),
83-
input: Input::File(PathBuf::new()),
84-
input_path: None,
85-
output_file: None,
86-
output_dir: None,
87-
file_loader: None,
88-
diagnostic_output: DiagnosticOutput::Raw(Box::new(write_diags)),
89-
lint_caps: Default::default(),
90-
parse_sess_created: None,
91-
register_lints: None,
92-
override_queries: None,
93-
make_codegen_backend: None,
94-
registry: Registry::new(&[]),
95-
};
74+
9675
// NOTE(eddyb) without `catch_fatal_errors`, you'd get the really strange
9776
// effect of test failures with no output (because the `FatalError` "panic"
9877
// is really a silent unwinding device, that should be treated the same as
99-
// `Err(ErrorGuaranteed)` returns from `run_compiler`/`link`).
78+
// `Err(ErrorGuaranteed)` returns from `link`).
10079
rustc_driver::catch_fatal_errors(|| {
101-
rustc_interface::interface::run_compiler(config, |compiler| {
102-
let res = link(
103-
compiler.session(),
104-
modules,
105-
&Options {
106-
compact_ids: true,
107-
dce: false,
108-
structurize: false,
109-
emit_multiple_modules: false,
110-
spirv_metadata: SpirvMetadata::None,
111-
},
112-
);
113-
assert_eq!(compiler.session().has_errors(), res.as_ref().err().copied());
114-
res.map(|res| match res {
115-
LinkResult::SingleModule(m) => *m,
116-
LinkResult::MultipleModules(_) => unreachable!(),
117-
})
118-
})
80+
let matches = rustc_driver::handle_options(&["".to_string(), "x.rs".to_string()]).unwrap();
81+
let sopts = rustc_session::config::build_session_options(&matches);
82+
83+
rustc_interface::util::run_in_thread_pool_with_globals(
84+
sopts.edition,
85+
sopts.unstable_opts.threads,
86+
|| {
87+
let mut sess = rustc_session::build_session(
88+
sopts,
89+
None,
90+
None,
91+
Registry::new(&[]),
92+
rustc_session::DiagnosticOutput::Default,
93+
Default::default(),
94+
None,
95+
None,
96+
);
97+
98+
// HACK(eddyb) inject `write_diags` into `sess`, to work around
99+
// the removals in https://github.com/rust-lang/rust/pull/102992.
100+
sess.parse_sess.span_diagnostic = {
101+
let fallback_bundle = {
102+
extern crate rustc_error_messages;
103+
rustc_error_messages::fallback_fluent_bundle(
104+
rustc_errors::DEFAULT_LOCALE_RESOURCES,
105+
sess.opts.unstable_opts.translate_directionality_markers,
106+
)
107+
};
108+
let emitter = rustc_errors::emitter::EmitterWriter::new(
109+
Box::new(write_diags),
110+
Some(sess.parse_sess.clone_source_map()),
111+
None,
112+
fallback_bundle,
113+
false,
114+
false,
115+
false,
116+
None,
117+
false,
118+
);
119+
120+
rustc_errors::Handler::with_emitter_and_flags(
121+
Box::new(emitter),
122+
sess.opts.unstable_opts.diagnostic_handler_flags(true),
123+
)
124+
};
125+
126+
let res = link(
127+
&sess,
128+
modules,
129+
&Options {
130+
compact_ids: true,
131+
dce: false,
132+
structurize: false,
133+
emit_multiple_modules: false,
134+
spirv_metadata: SpirvMetadata::None,
135+
},
136+
);
137+
assert_eq!(sess.has_errors(), res.as_ref().err().copied());
138+
res.map(|res| match res {
139+
LinkResult::SingleModule(m) => *m,
140+
LinkResult::MultipleModules(_) => unreachable!(),
141+
})
142+
},
143+
)
119144
})
120145
.flatten()
121146
.map_err(|_e| read_diags_thread.join().unwrap())

0 commit comments

Comments
 (0)