From c115c513632b45d1a4d1b3fb648755a7023269e7 Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Fri, 7 Aug 2015 16:36:56 +0200 Subject: [PATCH 1/2] improve span of erroneous empty macro invocation The ideas is to use the span of the complete macro invocation if the span of a macro error is `DUMMY_SP`. fixes #7970 --- src/libsyntax/ext/tt/macro_parser.rs | 16 -------------- src/libsyntax/ext/tt/macro_rules.rs | 33 +++++++++++++++++++++++----- src/test/compile-fail/issue-7970a.rs | 14 ++++++++++++ src/test/compile-fail/issue-7970b.rs | 14 ++++++++++++ 4 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 src/test/compile-fail/issue-7970a.rs create mode 100644 src/test/compile-fail/issue-7970b.rs diff --git a/src/libsyntax/ext/tt/macro_parser.rs b/src/libsyntax/ext/tt/macro_parser.rs index 4556bd5f8e590..26b4181ea8a66 100644 --- a/src/libsyntax/ext/tt/macro_parser.rs +++ b/src/libsyntax/ext/tt/macro_parser.rs @@ -249,22 +249,6 @@ pub enum ParseResult { pub type NamedParseResult = ParseResult>>; pub type PositionalParseResult = ParseResult>>; -pub fn parse_or_else(sess: &ParseSess, - cfg: ast::CrateConfig, - rdr: TtReader, - ms: Vec ) - -> HashMap> { - match parse(sess, cfg, rdr, &ms[..]) { - Success(m) => m, - Failure(sp, str) => { - panic!(sess.span_diagnostic.span_fatal(sp, &str[..])) - } - Error(sp, str) => { - panic!(sess.span_diagnostic.span_fatal(sp, &str[..])) - } - } -} - /// Perform a token equality check, ignoring syntax context (that is, an /// unhygienic comparison) pub fn token_name_eq(t1 : &Token, t2 : &Token) -> bool { diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index d16fde7bc394e..53e3127086cab 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -14,7 +14,7 @@ use ext::base::{ExtCtxt, MacResult, SyntaxExtension}; use ext::base::{NormalTT, TTMacroExpander}; use ext::tt::macro_parser::{Success, Error, Failure}; use ext::tt::macro_parser::{NamedMatch, MatchedSeq, MatchedNonterminal}; -use ext::tt::macro_parser::{parse, parse_or_else}; +use ext::tt::macro_parser::parse; use parse::lexer::new_tt_reader; use parse::parser::Parser; use parse::token::{self, special_idents, gensym_ident, NtTT, Token}; @@ -211,12 +211,23 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, best_fail_spot = sp; best_fail_msg = (*msg).clone(); }, - Error(sp, ref msg) => panic!(cx.span_fatal(sp, &msg[..])) + Error(mut spp, ref msg) => { + if spp == DUMMY_SP { + spp = sp; + } + + panic!(cx.span_fatal(spp, &msg[..])) + } } } _ => cx.bug("non-matcher found in parsed lhses") } } + + if best_fail_spot == DUMMY_SP { + best_fail_spot = sp; + } + panic!(cx.span_fatal(best_fail_spot, &best_fail_msg[..])); } @@ -266,10 +277,20 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, None, None, def.body.clone()); - let argument_map = parse_or_else(cx.parse_sess(), - cx.cfg(), - arg_reader, - argument_gram); + + let argument_map = match parse(cx.parse_sess(), + cx.cfg(), + arg_reader, + &argument_gram) { + Success(m) => m, + Failure(mut sp, str) | Error(mut sp, str) => { + if sp == DUMMY_SP { + sp = def.span; + } + + panic!(cx.parse_sess().span_diagnostic.span_fatal(sp, &str[..])); + } + }; // Extract the arguments: let lhses = match **argument_map.get(&lhs_nm).unwrap() { diff --git a/src/test/compile-fail/issue-7970a.rs b/src/test/compile-fail/issue-7970a.rs new file mode 100644 index 0000000000000..114db74f42048 --- /dev/null +++ b/src/test/compile-fail/issue-7970a.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + println!(); + //~^ ERROR unexpected end of macro invocation +} diff --git a/src/test/compile-fail/issue-7970b.rs b/src/test/compile-fail/issue-7970b.rs new file mode 100644 index 0000000000000..0cff90f281b90 --- /dev/null +++ b/src/test/compile-fail/issue-7970b.rs @@ -0,0 +1,14 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() {} + +macro_rules! test {} +//~^ ERROR unexpected end of macro invocation From d46e84081f88f22198fbfcd5221faaf922e0500d Mon Sep 17 00:00:00 2001 From: Tim Neumann Date: Mon, 10 Aug 2015 20:40:46 +0200 Subject: [PATCH 2/2] add and use Span.substitute_dummy method --- src/librustc/middle/traits/error_reporting.rs | 8 ++----- src/libsyntax/codemap.rs | 7 ++++++ src/libsyntax/ext/tt/macro_rules.rs | 23 +++++-------------- 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 582873082a68b..1f79db9e5232b 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -29,7 +29,7 @@ use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef}; use middle::ty_fold::TypeFoldable; use std::collections::HashMap; use std::fmt; -use syntax::codemap::{DUMMY_SP, Span}; +use syntax::codemap::Span; use syntax::attr::{AttributeMethods, AttrMetaMethods}; pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, @@ -81,11 +81,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, let mut report = None; for item in infcx.tcx.get_attrs(def_id).iter() { if item.check_name("rustc_on_unimplemented") { - let err_sp = if item.meta().span == DUMMY_SP { - span - } else { - item.meta().span - }; + let err_sp = item.meta().span.substitute_dummy(span); let def = infcx.tcx.lookup_trait_def(def_id); let trait_str = def.trait_ref.to_string(); if let Some(ref istring) = item.value_str() { diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 17e6b2c2e12df..0aeb572b6bcf6 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -135,6 +135,13 @@ pub const COMMAND_LINE_SP: Span = Span { lo: BytePos(0), hi: BytePos(0), expn_id: COMMAND_LINE_EXPN }; +impl Span { + /// Returns `self` if `self` is not the dummy span, and `other` otherwise. + pub fn substitute_dummy(self, other: Span) -> Span { + if self == DUMMY_SP { other } else { self } + } +} + #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Debug, Copy)] pub struct Spanned { pub node: T, diff --git a/src/libsyntax/ext/tt/macro_rules.rs b/src/libsyntax/ext/tt/macro_rules.rs index 53e3127086cab..d728fa59bd1df 100644 --- a/src/libsyntax/ext/tt/macro_rules.rs +++ b/src/libsyntax/ext/tt/macro_rules.rs @@ -211,12 +211,8 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, best_fail_spot = sp; best_fail_msg = (*msg).clone(); }, - Error(mut spp, ref msg) => { - if spp == DUMMY_SP { - spp = sp; - } - - panic!(cx.span_fatal(spp, &msg[..])) + Error(err_sp, ref msg) => { + panic!(cx.span_fatal(err_sp.substitute_dummy(sp), &msg[..])) } } } @@ -224,11 +220,7 @@ fn generic_extension<'cx>(cx: &'cx ExtCtxt, } } - if best_fail_spot == DUMMY_SP { - best_fail_spot = sp; - } - - panic!(cx.span_fatal(best_fail_spot, &best_fail_msg[..])); + panic!(cx.span_fatal(best_fail_spot.substitute_dummy(sp), &best_fail_msg[..])); } // Note that macro-by-example's input is also matched against a token tree: @@ -283,12 +275,9 @@ pub fn compile<'cx>(cx: &'cx mut ExtCtxt, arg_reader, &argument_gram) { Success(m) => m, - Failure(mut sp, str) | Error(mut sp, str) => { - if sp == DUMMY_SP { - sp = def.span; - } - - panic!(cx.parse_sess().span_diagnostic.span_fatal(sp, &str[..])); + Failure(sp, str) | Error(sp, str) => { + panic!(cx.parse_sess().span_diagnostic + .span_fatal(sp.substitute_dummy(def.span), &str[..])); } };