Skip to content

Commit 74b2e99

Browse files
committed
Report errors better when failing to open files for sub-parsers
1 parent 72cc1ac commit 74b2e99

File tree

6 files changed

+72
-25
lines changed

6 files changed

+72
-25
lines changed

src/libsyntax/ext/source_util.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -58,9 +58,10 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg,
5858
_body: ast::mac_body) -> @ast::expr {
5959
let args = get_mac_args(cx, sp, arg, 1u, option::Some(1u), ~"include");
6060
let file = expr_to_str(cx, args[0], ~"include_str! requires a string");
61-
let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(),
62-
&res_rel_file(cx, sp, &Path(file)),
63-
parse::parser::SOURCE_FILE);
61+
let p = parse::new_sub_parser_from_file(
62+
cx.parse_sess(), cx.cfg(),
63+
&res_rel_file(cx, sp, &Path(file)),
64+
parse::parser::SOURCE_FILE, sp);
6465
return p.parse_expr();
6566
}
6667

src/libsyntax/parse.rs

Lines changed: 44 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ export next_node_id;
66
export new_parser_from_file, new_parser_etc_from_file;
77
export new_parser_from_source_str;
88
export new_parser_from_tt;
9+
export new_sub_parser_from_file;
910
export parse_crate_from_file, parse_crate_from_crate_file;
1011
export parse_crate_from_source_str;
1112
export parse_expr_from_source_str, parse_item_from_source_str;
@@ -20,7 +21,7 @@ use util::interner;
2021
use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter};
2122
use lexer::{reader, string_reader};
2223
use parse::token::{ident_interner, mk_ident_interner};
23-
use codemap::{CodeMap, FileMap, CharPos, BytePos};
24+
use codemap::{span, CodeMap, FileMap, CharPos, BytePos};
2425

2526
type parse_sess = @{
2627
cm: @codemap::CodeMap,
@@ -61,8 +62,8 @@ fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg,
6162
6263
fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
6364
sess: parse_sess) -> @ast::crate {
64-
let p = new_parser_from_file(sess, cfg, input,
65-
parser::CRATE_FILE);
65+
let p = new_crate_parser_from_file(sess, cfg, input,
66+
parser::CRATE_FILE);
6667
let lo = p.span.lo;
6768
let prefix = input.dir_path();
6869
let leading_attrs = p.parse_inner_attrs_and_next();
@@ -84,8 +85,8 @@ fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg,
8485
8586
fn parse_crate_from_source_file(input: &Path, cfg: ast::crate_cfg,
8687
sess: parse_sess) -> @ast::crate {
87-
let p = new_parser_from_file(sess, cfg, input,
88-
parser::SOURCE_FILE);
88+
let p = new_crate_parser_from_file(sess, cfg, input,
89+
parser::SOURCE_FILE);
8990
let r = p.parse_crate_mod(cfg);
9091
return r;
9192
}
@@ -163,17 +164,45 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg,
163164
}
164165

165166
fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
166-
path: &Path, ftype: parser::file_type) -> Parser {
167-
let res = io::read_whole_file_str(path);
168-
match res {
169-
result::Ok(_) => { /* Continue. */ }
170-
result::Err(e) => sess.span_diagnostic.handler().fatal(e)
167+
path: &Path,
168+
ftype: parser::file_type) -> Result<Parser, ~str> {
169+
match io::read_whole_file_str(path) {
170+
result::Ok(move src) => {
171+
let filemap = sess.cm.new_filemap(path.to_str(), @move src);
172+
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
173+
sess.interner);
174+
175+
Ok(Parser(sess, cfg, srdr as reader, ftype))
176+
177+
}
178+
result::Err(move e) => Err(move e)
179+
}
180+
}
181+
182+
/// Create a new parser for an entire crate, handling errors as appropriate
183+
/// if the file doesn't exist
184+
fn new_crate_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
185+
path: &Path,
186+
ftype: parser::file_type) -> Parser {
187+
match new_parser_from_file(sess, cfg, path, ftype) {
188+
Ok(move parser) => move parser,
189+
Err(move e) => {
190+
sess.span_diagnostic.handler().fatal(e)
191+
}
192+
}
193+
}
194+
195+
/// Create a new parser based on a span from an existing parser. Handles
196+
/// error messages correctly when the file does not exist.
197+
fn new_sub_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg,
198+
path: &Path, ftype: parser::file_type,
199+
sp: span) -> Parser {
200+
match new_parser_from_file(sess, cfg, path, ftype) {
201+
Ok(move parser) => move parser,
202+
Err(move e) => {
203+
sess.span_diagnostic.span_fatal(sp, e)
204+
}
171205
}
172-
let src = @result::unwrap(res);
173-
let filemap = sess.cm.new_filemap(path.to_str(), src);
174-
let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap,
175-
sess.interner);
176-
return Parser(sess, cfg, srdr as reader, ftype);
177206
}
178207

179208
fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg,

src/libsyntax/parse/eval.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use parser::{Parser, SOURCE_FILE};
22
use attr::parser_attr;
33
use ast_util::mk_sp;
4+
use codemap::span;
45

56
export eval_crate_directives_to_mod;
67
export eval_src_mod;
@@ -64,8 +65,10 @@ fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &Option<Path>)
6465
let modpath = &companion_file(prefix, suffix);
6566
if file_exists(modpath) {
6667
debug!("found companion mod");
67-
let p0 = new_parser_from_file(cx.sess, cx.cfg,
68-
modpath, SOURCE_FILE);
68+
// XXX: Using a dummy span, but this code will go away soon
69+
let p0 = new_sub_parser_from_file(cx.sess, cx.cfg,
70+
modpath, SOURCE_FILE,
71+
ast_util::dummy_sp());
6972
let inner_attrs = p0.parse_inner_attrs_and_next();
7073
let m0 = p0.parse_mod_items(token::EOF, inner_attrs.next);
7174
return (m0.view_items, m0.items, inner_attrs.inner);
@@ -82,7 +85,8 @@ fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str {
8285
}
8386

8487
fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident,
85-
outer_attrs: ~[ast::attribute]) -> (ast::item_, ~[ast::attribute]) {
88+
outer_attrs: ~[ast::attribute],
89+
sp: span) -> (ast::item_, ~[ast::attribute]) {
8690
let file_path = Path(cdir_path_opt(
8791
cx.sess.interner.get(id) + ~".rs", outer_attrs));
8892
let full_path = if file_path.is_absolute {
@@ -91,8 +95,8 @@ fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident,
9195
prefix.push_many(file_path.components)
9296
};
9397
let p0 =
94-
new_parser_from_file(cx.sess, cx.cfg,
95-
&full_path, SOURCE_FILE);
98+
new_sub_parser_from_file(cx.sess, cx.cfg,
99+
&full_path, SOURCE_FILE, sp);
96100
let inner_attrs = p0.parse_inner_attrs_and_next();
97101
let mod_attrs = vec::append(outer_attrs, inner_attrs.inner);
98102
let first_item_outer_attrs = inner_attrs.next;
@@ -117,7 +121,7 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path,
117121
items: &mut ~[@ast::item]) {
118122
match cdir.node {
119123
ast::cdir_src_mod(vis, id, attrs) => {
120-
let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs);
124+
let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs, cdir.span);
121125
let i = mk_item(cx, cdir.span.lo, cdir.span.hi,
122126
/* FIXME (#2543) */ copy id,
123127
m, vis, mod_attrs);

src/libsyntax/parse/parser.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2959,6 +2959,7 @@ impl Parser {
29592959
}
29602960
29612961
fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info {
2962+
let id_span = self.span;
29622963
let id = self.parse_ident();
29632964
if self.token == token::SEMI {
29642965
self.bump();
@@ -2969,7 +2970,8 @@ impl Parser {
29692970
};
29702971
let prefix = Path(self.sess.cm.span_to_filename(copy self.span));
29712972
let prefix = prefix.dir_path();
2972-
let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id, outer_attrs);
2973+
let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id,
2974+
outer_attrs, id_span);
29732975
(id, m, Some(move attrs))
29742976
} else {
29752977
self.expect(token::LBRACE);
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
mod not_a_real_file; //~ ERROR not_a_real_file.rs
2+
3+
fn main() {
4+
assert mod_file_aux::bar() == 10;
5+
}
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#[path = "not_a_real_file.rs"]
2+
mod m; //~ ERROR not_a_real_file.rs
3+
4+
fn main() {
5+
assert m::foo() == 10;
6+
}

0 commit comments

Comments
 (0)