diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 5e0cb647c8b..1aaec73be4f 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -667,9 +667,22 @@ impl CodeMap { self.lookup_char_pos(sp.lo).file.name.to_string() } - pub fn span_to_lines(&self, sp: Span) -> FileLines { + pub fn span_to_lines(&self, sp: Span) -> FileLinesResult { + if sp.lo > sp.hi { + return Err(SpanLinesError::IllFormedSpan(sp)); + } + let lo = self.lookup_char_pos(sp.lo); let hi = self.lookup_char_pos(sp.hi); + + if lo.file.start_pos != hi.file.start_pos { + return Err(SpanLinesError::DistinctSources(DistinctSources { + begin: (lo.file.name.clone(), lo.file.start_pos), + end: (hi.file.name.clone(), hi.file.start_pos), + })); + } + assert!(hi.line >= lo.line); + let mut lines = Vec::with_capacity(hi.line - lo.line + 1); // The span starts partway through the first line, @@ -693,7 +706,7 @@ impl CodeMap { start_col: start_col, end_col: hi.col }); - FileLines {file: lo.file, lines: lines} + Ok(FileLines {file: lo.file, lines: lines}) } pub fn span_to_snippet(&self, sp: Span) -> Result { @@ -918,9 +931,17 @@ impl CodeMap { } // _____________________________________________________________________________ -// SpanSnippetError, DistinctSources, MalformedCodemapPositions +// SpanLinesError, SpanSnippetError, DistinctSources, MalformedCodemapPositions // +pub type FileLinesResult = Result; + +#[derive(Clone, PartialEq, Eq, Debug)] +pub enum SpanLinesError { + IllFormedSpan(Span), + DistinctSources(DistinctSources), +} + #[derive(Clone, PartialEq, Eq, Debug)] pub enum SpanSnippetError { IllFormedSpan(Span), @@ -1086,7 +1107,7 @@ mod tests { // Test span_to_lines for a span ending at the end of filemap let cm = init_code_map(); let span = Span {lo: BytePos(12), hi: BytePos(23), expn_id: NO_EXPANSION}; - let file_lines = cm.span_to_lines(span); + let file_lines = cm.span_to_lines(span).unwrap(); assert_eq!(file_lines.file.name, "blork.rs"); assert_eq!(file_lines.lines.len(), 1); @@ -1131,7 +1152,7 @@ mod tests { assert_eq!(&cm.span_to_snippet(span).unwrap(), "BB\nCCC\nDDDDD"); // check that span_to_lines gives us the complete result with the lines/cols we expected - let lines = cm.span_to_lines(span); + let lines = cm.span_to_lines(span).unwrap(); let expected = vec![ LineInfo { line_index: 1, start_col: CharPos(4), end_col: CharPos(6) }, LineInfo { line_index: 2, start_col: CharPos(0), end_col: CharPos(3) }, diff --git a/src/libsyntax/diagnostic.rs b/src/libsyntax/diagnostic.rs index a7453636c44..aa649b4d99a 100644 --- a/src/libsyntax/diagnostic.rs +++ b/src/libsyntax/diagnostic.rs @@ -522,7 +522,7 @@ fn highlight_suggestion(err: &mut EmitterWriter, suggestion: &str) -> io::Result<()> { - let lines = cm.span_to_lines(sp); + let lines = cm.span_to_lines(sp).unwrap(); assert!(!lines.lines.is_empty()); // To build up the result, we want to take the snippet from the first @@ -567,9 +567,17 @@ fn highlight_lines(err: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: codemap::FileLines) + lines: codemap::FileLinesResult) -> io::Result<()> { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut err.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + let fm = &*lines.file; let line_strings: Option> = @@ -690,8 +698,16 @@ fn end_highlight_lines(w: &mut EmitterWriter, cm: &codemap::CodeMap, sp: Span, lvl: Level, - lines: codemap::FileLines) + lines: codemap::FileLinesResult) -> io::Result<()> { + let lines = match lines { + Ok(lines) => lines, + Err(_) => { + try!(write!(&mut w.dst, "(internal compiler error: unprintable span)\n")); + return Ok(()); + } + }; + let fm = &*lines.file; let lines = &lines.lines[..];