From 5f77a47f6b906bc67d71534c0365c6f9efe9389d Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 18 Mar 2015 17:02:34 +0100 Subject: [PATCH 1/2] Work around invalid spans in imported FileMaps --- src/librustc/middle/astencode.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) 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 { From 1ea971ff87e7aee729c7330a394b975fb3a598b1 Mon Sep 17 00:00:00 2001 From: Michael Woerister Date: Wed, 18 Mar 2015 22:05:24 +0100 Subject: [PATCH 2/2] Add test case for stable import of invalid span information. --- .../auxiliary/crate_with_invalid_spans.rs | 30 +++++++++++++++++++ .../crate_with_invalid_spans_macros.rs | 17 +++++++++++ .../import-crate-with-invalid-spans.rs | 20 +++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 src/test/auxiliary/crate_with_invalid_spans.rs create mode 100644 src/test/auxiliary/crate_with_invalid_spans_macros.rs create mode 100644 src/test/run-pass/import-crate-with-invalid-spans.rs 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); +}