From 0524161c0be7794a9c508aaa771735da897b555d Mon Sep 17 00:00:00 2001 From: Jakub Bukaj Date: Thu, 20 Nov 2014 21:24:39 +0100 Subject: [PATCH] Fix an ICE on diagnostics originating in external macros --- src/libsyntax/codemap.rs | 22 +++++----- src/libsyntax/diagnostic.rs | 58 +++++++++++++++----------- src/test/compile-fail/issue-14091-2.rs | 26 ++++++++++++ src/test/compile-fail/issue-14091.rs | 13 ++++++ 4 files changed, 85 insertions(+), 34 deletions(-) create mode 100644 src/test/compile-fail/issue-14091-2.rs create mode 100644 src/test/compile-fail/issue-14091.rs diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 7d849ddf1c1..b019b31de5f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -293,15 +293,17 @@ impl FileMap { /// get a line from the list of pre-computed line-beginnings /// - pub fn get_line(&self, line: int) -> String { + pub fn get_line(&self, line_number: uint) -> Option { let lines = self.lines.borrow(); - let begin: BytePos = (*lines)[line as uint] - self.start_pos; - let begin = begin.to_uint(); - let slice = self.src.as_slice().slice_from(begin); - match slice.find('\n') { - Some(e) => slice.slice_to(e).to_string(), - None => slice.to_string() - } + lines.get(line_number).map(|&line| { + let begin: BytePos = line - self.start_pos; + let begin = begin.to_uint(); + let slice = self.src.as_slice().slice_from(begin); + match slice.find('\n') { + Some(e) => slice.slice_to(e), + None => slice + }.to_string() + }) } pub fn record_multibyte_char(&self, pos: BytePos, bytes: uint) { @@ -578,10 +580,10 @@ mod test { let fm = cm.new_filemap("blork.rs".to_string(), "first line.\nsecond line".to_string()); fm.next_line(BytePos(0)); - assert_eq!(&fm.get_line(0),&"first line.".to_string()); + assert_eq!(fm.get_line(0), Some("first line.".to_string())); // TESTING BROKEN BEHAVIOR: fm.next_line(BytePos(10)); - assert_eq!(&fm.get_line(1), &".".to_string()); + assert_eq!(fm.get_line(1), Some(".".to_string())); } #[test] diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index ff600fcc7c2..293c1b3a953 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -436,9 +436,11 @@ fn highlight_lines(err: &mut EmitterWriter, elided = true; } // Print the offending lines - for line in display_lines.iter() { - try!(write!(&mut err.dst, "{}:{} {}\n", fm.name, *line + 1, - fm.get_line(*line as int))); + for &line_number in display_lines.iter() { + if let Some(line) = fm.get_line(line_number) { + try!(write!(&mut err.dst, "{}:{} {}\n", fm.name, + line_number + 1, line)); + } } if elided { let last_line = display_lines[display_lines.len() - 1u]; @@ -465,24 +467,26 @@ fn highlight_lines(err: &mut EmitterWriter, for _ in range(0, skip) { s.push(' '); } - let orig = fm.get_line(lines.lines[0] as int); - for pos in range(0u, left-skip) { - let cur_char = orig.as_bytes()[pos] as char; - // Whenever a tab occurs on the previous line, we insert one on - // the error-point-squiggly-line as well (instead of a space). - // That way the squiggly line will usually appear in the correct - // position. - match cur_char { - '\t' => s.push('\t'), - _ => s.push(' '), - }; + if let Some(orig) = fm.get_line(lines.lines[0]) { + for pos in range(0u, left - skip) { + let cur_char = orig.as_bytes()[pos] as char; + // Whenever a tab occurs on the previous line, we insert one on + // the error-point-squiggly-line as well (instead of a space). + // That way the squiggly line will usually appear in the correct + // position. + match cur_char { + '\t' => s.push('\t'), + _ => s.push(' '), + }; + } } + try!(write!(&mut err.dst, "{}", s)); let mut s = String::from_str("^"); let hi = cm.lookup_char_pos(sp.hi); if hi.col != lo.col { // the ^ already takes up one space - let num_squigglies = hi.col.to_uint()-lo.col.to_uint()-1u; + let num_squigglies = hi.col.to_uint() - lo.col.to_uint() - 1u; for _ in range(0, num_squigglies) { s.push('~'); } @@ -510,16 +514,22 @@ fn custom_highlight_lines(w: &mut EmitterWriter, let lines = lines.lines.as_slice(); if lines.len() > MAX_LINES { - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - lines[0] + 1, fm.get_line(lines[0] as int))); - try!(write!(&mut w.dst, "...\n")); - let last_line = lines[lines.len()-1]; - try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - last_line + 1, fm.get_line(last_line as int))); - } else { - for line in lines.iter() { + if let Some(line) = fm.get_line(lines[0]) { try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, - *line + 1, fm.get_line(*line as int))); + lines[0] + 1, line)); + } + try!(write!(&mut w.dst, "...\n")); + let last_line_number = lines[lines.len() - 1]; + if let Some(last_line) = fm.get_line(last_line_number) { + try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, + last_line_number + 1, last_line)); + } + } else { + for &line_number in lines.iter() { + if let Some(line) = fm.get_line(line_number) { + try!(write!(&mut w.dst, "{}:{} {}\n", fm.name, + line_number + 1, line)); + } } } let last_line_start = format!("{}:{} ", fm.name, lines[lines.len()-1]+1); diff --git a/src/test/compile-fail/issue-14091-2.rs b/src/test/compile-fail/issue-14091-2.rs new file mode 100644 index 00000000000..d3823a8cc55 --- /dev/null +++ b/src/test/compile-fail/issue-14091-2.rs @@ -0,0 +1,26 @@ +// Copyright 2014 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. + +// error-pattern: cannot apply unary operator `!` to type `BytePos` + +// Very + +// sensitive +pub struct BytePos(pub u32); + +// to particular + +// line numberings / offsets + +fn main() { + let x = BytePos(1); + + assert!(x, x); +} diff --git a/src/test/compile-fail/issue-14091.rs b/src/test/compile-fail/issue-14091.rs new file mode 100644 index 00000000000..c2ad09f5cb4 --- /dev/null +++ b/src/test/compile-fail/issue-14091.rs @@ -0,0 +1,13 @@ +// Copyright 2014 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. + +// error-pattern: expected `bool`, found `_` (expected bool, found integral variable) + +fn main(){assert!(1,1);}