diff --git a/base/src/source.rs b/base/src/source.rs index 800c1f66e5..5100ddc3d2 100644 --- a/base/src/source.rs +++ b/base/src/source.rs @@ -65,18 +65,32 @@ impl<'a> Source<'a> { let line_index = self.line_number_at_byte(byte); self.line(line_index).and_then(|(line_byte, line)| { - for (col, (next_byte, _)) in line.char_indices().enumerate() { + let mut column_index = Column::from(0); + + for (i, (next_byte, _)) in line.char_indices().enumerate() { + column_index = Column::from(i); + let curr_byte = line_byte + BytePos::from(next_byte); if curr_byte == byte { return Some(Location { - line: Line::from(line_index), - column: Column::from(col), + line: line_index, + column: column_index, absolute: byte, }); } } - None + + // Handle the case where `byte` is equal to the source's length + if byte == line_byte + BytePos::from(line.len()) { + Some(Location { + line: line_index, + column: column_index, + absolute: byte, + }) + } else { + None + } }) } } @@ -157,4 +171,15 @@ mod tests { assert_eq!(source.location(BytePos::from(400)), None); } + + #[test] + fn source_location_end_of_source() { + let source = test_source(); + assert_eq!(source.location(BytePos::from(source.src.len())), + Some(Location { + line: Line::from(5), + column: Column::from(0), + absolute: BytePos::from(source.src.len()), + })); + } } diff --git a/tests/error.rs b/tests/error.rs new file mode 100644 index 0000000000..decf0e51ac --- /dev/null +++ b/tests/error.rs @@ -0,0 +1,15 @@ +extern crate env_logger; +extern crate gluon; + +mod support; + +use gluon::Compiler; + +#[test] +fn dont_panic_when_error_span_is_at_eof() { + let _ = ::env_logger::init(); + let vm = support::make_vm(); + let text = r#"abc"#; + let result = Compiler::new().load_script(&vm, "test", text); + assert!(result.is_err()); +}