Skip to content

Commit 2bb2287

Browse files
committed
rustdoc: do not panic all the way when lexing a source snippet fails
Currently, the libsyntax lexer panics on invalid source, which makes rustdoc panic when trying to highlight it. I assume there are efforts underway to make the lexer panic-free, but until this is done this should be an acceptable workaround. Note that the panic is still printed like normal as "thread X panicked, run with RUST_BACKTRACE=1 ...", so I added the printout below to make it seem less like a fatal error. I didn't touch `render_inner_with_highlighting` below, as it is currently unused. It returns a Result whose Err type would have to be changed if it was to support lexer errors. Fixes: rust-lang#30032
1 parent 877dfeb commit 2bb2287

File tree

2 files changed

+39
-12
lines changed

2 files changed

+39
-12
lines changed

src/librustdoc/html/highlight.rs

+21-12
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ use html::escape::Escape;
2424

2525
use std::fmt::Display;
2626
use std::io;
27+
use std::panic::catch_unwind;
2728
use std::io::prelude::*;
2829

2930
use syntax::codemap::CodeMap;
@@ -35,20 +36,28 @@ use syntax_pos::Span;
3536
/// Highlights `src`, returning the HTML output.
3637
pub fn render_with_highlighting(src: &str, class: Option<&str>, id: Option<&str>) -> String {
3738
debug!("highlighting: ================\n{}\n==============", src);
38-
let sess = parse::ParseSess::new();
39-
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
40-
41-
let mut out = Vec::new();
42-
write_header(class, id, &mut out).unwrap();
4339

44-
let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm),
45-
sess.codemap());
46-
if let Err(_) = classifier.write_source(&mut out) {
47-
return format!("<pre>{}</pre>", src);
40+
// As long as the lexer panics...
41+
let result = catch_unwind(|| {
42+
let sess = parse::ParseSess::new();
43+
let fm = sess.codemap().new_filemap("<stdin>".to_string(), None, src.to_string());
44+
let mut out = Vec::new();
45+
write_header(class, id, &mut out).unwrap();
46+
let mut classifier = Classifier::new(lexer::StringReader::new(&sess.span_diagnostic, fm),
47+
sess.codemap());
48+
classifier.write_source(&mut out).unwrap();
49+
write_footer(&mut out).unwrap();
50+
out
51+
});
52+
match result {
53+
// catches both panics from the lexer and the unwrap()s
54+
Err(_) => {
55+
println!("warning: error during source highlighting (see above), \
56+
passing source through unhighlighted");
57+
format!("<pre>{}</pre>", src)
58+
},
59+
Ok(out) => String::from_utf8_lossy(&out[..]).into_owned(),
4860
}
49-
50-
write_footer(&mut out).unwrap();
51-
String::from_utf8_lossy(&out[..]).into_owned()
5261
}
5362

5463
/// Highlights `src`, returning the HTML output. Returns only the inner html to

src/test/rustdoc/issue-30032.rs

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// This used to panic due to the invalid source, so just checking for
12+
// existence of the output file is enough.
13+
14+
// @has issue_30032/fn.main.html
15+
/// ```ignore
16+
/// let invalid = 'abc';
17+
/// ```
18+
pub fn main() {}

0 commit comments

Comments
 (0)