Avoid ICE when include! is used by stdin crate

This should also eliminate the ICE when using `include_bytes!`, `include_str!`
and `#[doc(include = "...")]`.

Fixes #63900
This commit is contained in:
Nika Layzell 2019-10-19 13:05:46 -04:00
parent e5b8c118a3
commit 9be0bd8aa1
3 changed files with 40 additions and 8 deletions

View file

@ -1072,7 +1072,11 @@ impl<'a> ExtCtxt<'a> {
/// This unifies the logic used for resolving `include_X!`, and `#[doc(include)]` file paths.
///
/// Returns an absolute path to the file that `path` refers to.
pub fn resolve_path(&self, path: impl Into<PathBuf>, span: Span) -> PathBuf {
pub fn resolve_path(
&self,
path: impl Into<PathBuf>,
span: Span,
) -> Result<PathBuf, DiagnosticBuilder<'a>> {
let path = path.into();
// Relative paths are resolved relative to the file in which they are found
@ -1082,13 +1086,16 @@ impl<'a> ExtCtxt<'a> {
let mut result = match self.source_map().span_to_unmapped_path(callsite) {
FileName::Real(path) => path,
FileName::DocTest(path, _) => path,
other => panic!("cannot resolve relative path in non-file source `{}`", other),
other => return Err(self.struct_span_err(
span,
&format!("cannot resolve relative path in non-file source `{}`", other),
)),
};
result.pop();
result.push(path);
result
Ok(result)
} else {
path
Ok(path)
}
}
}

View file

@ -1418,7 +1418,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
return noop_visit_attribute(at, self);
}
let filename = self.cx.resolve_path(&*file.as_str(), it.span());
let filename = match self.cx.resolve_path(&*file.as_str(), it.span()) {
Ok(filename) => filename,
Err(mut err) => {
err.emit();
continue;
}
};
match self.cx.source_map().load_file(&filename) {
Ok(source_file) => {
let src = source_file.src.as_ref()

View file

@ -76,7 +76,13 @@ pub fn expand_include<'cx>(cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
None => return DummyResult::any(sp),
};
// The file will be added to the code map by the parser
let file = cx.resolve_path(file, sp);
let file = match cx.resolve_path(file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
return DummyResult::any(sp);
},
};
let directory_ownership = DirectoryOwnership::Owned { relative: None };
let p = parse::new_sub_parser_from_file(cx.parse_sess(), &file, directory_ownership, None, sp);
@ -122,7 +128,13 @@ pub fn expand_include_str(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
Some(f) => f,
None => return DummyResult::any(sp)
};
let file = cx.resolve_path(file, sp);
let file = match cx.resolve_path(file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
return DummyResult::any(sp);
},
};
match cx.source_map().load_binary_file(&file) {
Ok(bytes) => match std::str::from_utf8(&bytes) {
Ok(src) => {
@ -147,7 +159,13 @@ pub fn expand_include_bytes(cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream)
Some(f) => f,
None => return DummyResult::any(sp)
};
let file = cx.resolve_path(file, sp);
let file = match cx.resolve_path(file, sp) {
Ok(f) => f,
Err(mut err) => {
err.emit();
return DummyResult::any(sp);
},
};
match cx.source_map().load_binary_file(&file) {
Ok(bytes) => {
base::MacEager::expr(cx.expr_lit(sp, ast::LitKind::ByteStr(Lrc::new(bytes))))