diff --git a/src/libsyntax/ext/source_util.rs b/src/libsyntax/ext/source_util.rs index baf92175e7d..1bd3ec8423e 100644 --- a/src/libsyntax/ext/source_util.rs +++ b/src/libsyntax/ext/source_util.rs @@ -58,9 +58,10 @@ fn expand_include(cx: ext_ctxt, sp: span, arg: ast::mac_arg, _body: ast::mac_body) -> @ast::expr { let args = get_mac_args(cx, sp, arg, 1u, option::Some(1u), ~"include"); let file = expr_to_str(cx, args[0], ~"include_str! requires a string"); - let p = parse::new_parser_from_file(cx.parse_sess(), cx.cfg(), - &res_rel_file(cx, sp, &Path(file)), - parse::parser::SOURCE_FILE); + let p = parse::new_sub_parser_from_file( + cx.parse_sess(), cx.cfg(), + &res_rel_file(cx, sp, &Path(file)), + parse::parser::SOURCE_FILE, sp); return p.parse_expr(); } diff --git a/src/libsyntax/parse.rs b/src/libsyntax/parse.rs index 593ff6d034e..fc9474bab24 100644 --- a/src/libsyntax/parse.rs +++ b/src/libsyntax/parse.rs @@ -6,6 +6,7 @@ export next_node_id; export new_parser_from_file, new_parser_etc_from_file; export new_parser_from_source_str; export new_parser_from_tt; +export new_sub_parser_from_file; export parse_crate_from_file, parse_crate_from_crate_file; export parse_crate_from_source_str; export parse_expr_from_source_str, parse_item_from_source_str; @@ -20,7 +21,7 @@ use util::interner; use diagnostic::{span_handler, mk_span_handler, mk_handler, emitter}; use lexer::{reader, string_reader}; use parse::token::{ident_interner, mk_ident_interner}; -use codemap::{CodeMap, FileMap, CharPos, BytePos}; +use codemap::{span, CodeMap, FileMap, CharPos, BytePos}; type parse_sess = @{ cm: @codemap::CodeMap, @@ -61,8 +62,8 @@ fn parse_crate_from_file(input: &Path, cfg: ast::crate_cfg, fn parse_crate_from_crate_file(input: &Path, cfg: ast::crate_cfg, sess: parse_sess) -> @ast::crate { - let p = new_parser_from_file(sess, cfg, input, - parser::CRATE_FILE); + let p = new_crate_parser_from_file(sess, cfg, input, + parser::CRATE_FILE); let lo = p.span.lo; let prefix = input.dir_path(); 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, fn parse_crate_from_source_file(input: &Path, cfg: ast::crate_cfg, sess: parse_sess) -> @ast::crate { - let p = new_parser_from_file(sess, cfg, input, - parser::SOURCE_FILE); + let p = new_crate_parser_from_file(sess, cfg, input, + parser::SOURCE_FILE); let r = p.parse_crate_mod(cfg); return r; } @@ -163,17 +164,45 @@ fn new_parser_from_source_str(sess: parse_sess, cfg: ast::crate_cfg, } fn new_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, - path: &Path, ftype: parser::file_type) -> Parser { - let res = io::read_whole_file_str(path); - match res { - result::Ok(_) => { /* Continue. */ } - result::Err(e) => sess.span_diagnostic.handler().fatal(e) + path: &Path, + ftype: parser::file_type) -> Result { + match io::read_whole_file_str(path) { + result::Ok(move src) => { + let filemap = sess.cm.new_filemap(path.to_str(), @move src); + let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, + sess.interner); + + Ok(Parser(sess, cfg, srdr as reader, ftype)) + + } + result::Err(move e) => Err(move e) + } +} + +/// Create a new parser for an entire crate, handling errors as appropriate +/// if the file doesn't exist +fn new_crate_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, + path: &Path, + ftype: parser::file_type) -> Parser { + match new_parser_from_file(sess, cfg, path, ftype) { + Ok(move parser) => move parser, + Err(move e) => { + sess.span_diagnostic.handler().fatal(e) + } + } +} + +/// Create a new parser based on a span from an existing parser. Handles +/// error messages correctly when the file does not exist. +fn new_sub_parser_from_file(sess: parse_sess, cfg: ast::crate_cfg, + path: &Path, ftype: parser::file_type, + sp: span) -> Parser { + match new_parser_from_file(sess, cfg, path, ftype) { + Ok(move parser) => move parser, + Err(move e) => { + sess.span_diagnostic.span_fatal(sp, e) + } } - let src = @result::unwrap(res); - let filemap = sess.cm.new_filemap(path.to_str(), src); - let srdr = lexer::new_string_reader(sess.span_diagnostic, filemap, - sess.interner); - return Parser(sess, cfg, srdr as reader, ftype); } fn new_parser_from_tt(sess: parse_sess, cfg: ast::crate_cfg, diff --git a/src/libsyntax/parse/eval.rs b/src/libsyntax/parse/eval.rs index 660e88c7101..1873a346270 100644 --- a/src/libsyntax/parse/eval.rs +++ b/src/libsyntax/parse/eval.rs @@ -1,6 +1,7 @@ use parser::{Parser, SOURCE_FILE}; use attr::parser_attr; use ast_util::mk_sp; +use codemap::span; export eval_crate_directives_to_mod; export eval_src_mod; @@ -64,8 +65,10 @@ fn parse_companion_mod(cx: ctx, prefix: &Path, suffix: &Option) let modpath = &companion_file(prefix, suffix); if file_exists(modpath) { debug!("found companion mod"); - let p0 = new_parser_from_file(cx.sess, cx.cfg, - modpath, SOURCE_FILE); + // XXX: Using a dummy span, but this code will go away soon + let p0 = new_sub_parser_from_file(cx.sess, cx.cfg, + modpath, SOURCE_FILE, + ast_util::dummy_sp()); let inner_attrs = p0.parse_inner_attrs_and_next(); let m0 = p0.parse_mod_items(token::EOF, inner_attrs.next); return (m0.view_items, m0.items, inner_attrs.inner); @@ -82,7 +85,8 @@ fn cdir_path_opt(default: ~str, attrs: ~[ast::attribute]) -> ~str { } fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident, - outer_attrs: ~[ast::attribute]) -> (ast::item_, ~[ast::attribute]) { + outer_attrs: ~[ast::attribute], + sp: span) -> (ast::item_, ~[ast::attribute]) { let file_path = Path(cdir_path_opt( cx.sess.interner.get(id) + ~".rs", outer_attrs)); let full_path = if file_path.is_absolute { @@ -91,8 +95,8 @@ fn eval_src_mod(cx: ctx, prefix: &Path, id: ast::ident, prefix.push_many(file_path.components) }; let p0 = - new_parser_from_file(cx.sess, cx.cfg, - &full_path, SOURCE_FILE); + new_sub_parser_from_file(cx.sess, cx.cfg, + &full_path, SOURCE_FILE, sp); let inner_attrs = p0.parse_inner_attrs_and_next(); let mod_attrs = vec::append(outer_attrs, inner_attrs.inner); let first_item_outer_attrs = inner_attrs.next; @@ -117,7 +121,7 @@ fn eval_crate_directive(cx: ctx, cdir: @ast::crate_directive, prefix: &Path, items: &mut ~[@ast::item]) { match cdir.node { ast::cdir_src_mod(vis, id, attrs) => { - let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs); + let (m, mod_attrs) = eval_src_mod(cx, prefix, id, attrs, cdir.span); let i = mk_item(cx, cdir.span.lo, cdir.span.hi, /* FIXME (#2543) */ copy id, m, vis, mod_attrs); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 12ae135e525..9d71f83b28d 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -2959,6 +2959,7 @@ impl Parser { } fn parse_item_mod(outer_attrs: ~[ast::attribute]) -> item_info { + let id_span = self.span; let id = self.parse_ident(); if self.token == token::SEMI { self.bump(); @@ -2969,7 +2970,8 @@ impl Parser { }; let prefix = Path(self.sess.cm.span_to_filename(copy self.span)); let prefix = prefix.dir_path(); - let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id, outer_attrs); + let (m, attrs) = eval::eval_src_mod(eval_ctx, &prefix, id, + outer_attrs, id_span); (id, m, Some(move attrs)) } else { self.expect(token::LBRACE); diff --git a/src/test/compile-fail/mod_file_not_exist.rs b/src/test/compile-fail/mod_file_not_exist.rs new file mode 100644 index 00000000000..5e571af8955 --- /dev/null +++ b/src/test/compile-fail/mod_file_not_exist.rs @@ -0,0 +1,5 @@ +mod not_a_real_file; //~ ERROR not_a_real_file.rs + +fn main() { + assert mod_file_aux::bar() == 10; +} \ No newline at end of file diff --git a/src/test/compile-fail/mod_file_with_path_attr.rs b/src/test/compile-fail/mod_file_with_path_attr.rs new file mode 100644 index 00000000000..3baa18be9f1 --- /dev/null +++ b/src/test/compile-fail/mod_file_with_path_attr.rs @@ -0,0 +1,6 @@ +#[path = "not_a_real_file.rs"] +mod m; //~ ERROR not_a_real_file.rs + +fn main() { + assert m::foo() == 10; +} \ No newline at end of file