diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index f7210728bb480..8b2a94025f337 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -235,12 +235,27 @@ impl<'a, 'b, 'tcx> DecodeContext<'a, 'b, 'tcx> { pub fn tr_span(&self, span: Span) -> Span { let imported_filemaps = &self.cdata.codemap_import_info[..]; + let span = if span.lo > span.hi { + // Currently macro expansion sometimes produces invalid Span values + // where lo > hi. In order not to crash the compiler when trying to + // translate these values, let's transform them into something we + // can handle (and which will produce useful debug locations at + // least some of the time). + // This workaround is only necessary as long as macro expansion is + // not fixed. FIXME(#23480) + codemap::mk_sp(span.lo, span.lo) + } else { + span + }; + let filemap_index = { // Optimize for the case that most spans within a translated item // originate from the same filemap. let last_filemap_index = self.last_filemap_index.get(); if span.lo >= imported_filemaps[last_filemap_index].original_start_pos && + span.lo <= imported_filemaps[last_filemap_index].original_end_pos && + span.hi >= imported_filemaps[last_filemap_index].original_start_pos && span.hi <= imported_filemaps[last_filemap_index].original_end_pos { last_filemap_index } else { diff --git a/src/test/auxiliary/crate_with_invalid_spans.rs b/src/test/auxiliary/crate_with_invalid_spans.rs new file mode 100644 index 0000000000000..b37533d2da763 --- /dev/null +++ b/src/test/auxiliary/crate_with_invalid_spans.rs @@ -0,0 +1,30 @@ +// 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. + +#![crate_type = "rlib"] +// no-prefer-dynamic + +// compile-flags: -g + +#[macro_use] +mod crate_with_invalid_spans_macros; + +pub fn exported_generic(x: T, y: u32) -> (T, u32) { + // Using the add1 macro will produce an invalid span, because the `y` passed + // to the macro will have a span from this file, but the rest of the code + // generated from the macro will have spans from the macro-defining file. + // The AST node for the (1 + y) expression generated by the macro will then + // take it's `lo` span bound from the `1` literal in the macro-defining file + // and it's `hi` bound from `y` in this file, which should be lower than the + // `lo` and even lower than the lower bound of the FileMap it is supposedly + // contained in because the FileMap for this file was allocated earlier than + // the FileMap of the macro-defining file. + return (x, add1!(y)); +} diff --git a/src/test/auxiliary/crate_with_invalid_spans_macros.rs b/src/test/auxiliary/crate_with_invalid_spans_macros.rs new file mode 100644 index 0000000000000..112315af84485 --- /dev/null +++ b/src/test/auxiliary/crate_with_invalid_spans_macros.rs @@ -0,0 +1,17 @@ +// 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. + +macro_rules! add1 { + ($e:expr) => ({ + let a = 1 + $e; + let b = $e + 1; + a + b - 1 + }) +} diff --git a/src/test/run-pass/import-crate-with-invalid-spans.rs b/src/test/run-pass/import-crate-with-invalid-spans.rs new file mode 100644 index 0000000000000..a949f25f41e09 --- /dev/null +++ b/src/test/run-pass/import-crate-with-invalid-spans.rs @@ -0,0 +1,20 @@ +// 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. + +// aux-build:crate_with_invalid_spans.rs + +extern crate crate_with_invalid_spans; + +fn main() { + // The AST of `exported_generic` stored in crate_with_invalid_spans's + // metadata should contain an invalid span where span.lo > span.hi. + // Let's make sure the compiler doesn't crash when encountering this. + let _ = crate_with_invalid_spans::exported_generic(32u32, 7u32); +}