Prevent crash when macro is in different file

This was caused by a macro in a different file.
The `target.span` was be in the file of the macro definition and the
`item.span` in the file of the calling code.
This commit is contained in:
Philipp Hansch 2018-05-01 15:01:28 +02:00
parent 1742229ebb
commit 5d36edc90d
No known key found for this signature in database
GPG Key ID: B6FA06A6E0E2665B
3 changed files with 23 additions and 1 deletions

View File

@ -12,7 +12,7 @@
use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::ast::{FloatTy, IntTy, UintTy};
use syntax::codemap::Span; use syntax::codemap::Span;
use syntax::errors::DiagnosticBuilder; use syntax::errors::DiagnosticBuilder;
use utils::{comparisons, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path, use utils::{comparisons, differing_macro_contexts, higher, in_constant, in_external_macro, in_macro, last_path_segment, match_def_path, match_path,
match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint, match_type, multispan_sugg, opt_def_id, same_tys, snippet, snippet_opt, span_help_and_lint, span_lint,
span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits}; span_lint_and_sugg, span_lint_and_then, clip, unsext, sext, int_bits};
use utils::paths; use utils::paths;
@ -1714,6 +1714,10 @@ fn suggestion<'a, 'tcx>(
vis.visit_ty(ty); vis.visit_ty(ty);
for target in &vis.found { for target in &vis.found {
if differing_macro_contexts(item.span, target.span()) {
return;
}
let generics_suggestion_span = generics.span.substitute_dummy({ let generics_suggestion_span = generics.span.substitute_dummy({
let pos = snippet_opt(cx, item.span.until(target.span())) let pos = snippet_opt(cx, item.span.until(target.span()))
.and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4))) .and_then(|snip| Some(item.span.lo() + BytePos(snip.find("impl")? as u32 + 4)))

View File

@ -0,0 +1,11 @@
pub trait A {}
macro_rules! __implicit_hasher_test_macro {
(impl< $($impl_arg:tt),* > for $kind:ty where $($bounds:tt)*) => {
__implicit_hasher_test_macro!( ($($impl_arg),*) ($kind) ($($bounds)*) );
};
(($($impl_arg:tt)*) ($($kind_arg:tt)*) ($($bounds:tt)*)) => {
impl< $($impl_arg)* > test_macro::A for $($kind_arg)* where $($bounds)* { }
};
}

View File

@ -83,4 +83,11 @@ pub fn $name(_map: &mut HashMap<i32, i32>, _set: &mut HashSet<i32>) {
gen!(impl); gen!(impl);
gen!(fn bar); gen!(fn bar);
// When the macro is in a different file, the suggestion spans can't be combined properly
// and should not cause an ICE
// See #2707
#[macro_use]
#[path = "../auxiliary/test_macro.rs"] pub mod test_macro;
__implicit_hasher_test_macro!(impl<K, V> for HashMap<K, V> where V: test_macro::A);
fn main() {} fn main() {}