about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTomasz Miąsko <tomasz.miasko@gmail.com>2021-07-01 00:00:00 +0000
committerTomasz Miąsko <tomasz.miasko@gmail.com>2021-07-01 13:30:00 +0200
commit7a410763facea6aab28cdaeb133179b11a979eb6 (patch)
treec44f9470f57a74d537efe4a48044890b26e77ac4
parentf8ac8fdacf66b351c6479b0c8313e3e57e571ba4 (diff)
downloadrust-7a410763facea6aab28cdaeb133179b11a979eb6.tar.gz
rust-7a410763facea6aab28cdaeb133179b11a979eb6.zip
Avoid byte to char position conversions in is_multiline
Converting a byte position into a char position is currently linear in
the number of multibyte characters in the source code. Avoid it when
checking if a range spans across lines.

This makes it feasible to compile source files with a large number of
multibyte characters.
-rw-r--r--compiler/rustc_span/src/source_map.rs10
1 files changed, 7 insertions, 3 deletions
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 32031ac7071..77a3ad931d5 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -461,9 +461,13 @@ impl SourceMap {
     }
 
     pub fn is_multiline(&self, sp: Span) -> bool {
-        let lo = self.lookup_char_pos(sp.lo());
-        let hi = self.lookup_char_pos(sp.hi());
-        lo.line != hi.line
+        let lo = self.lookup_source_file_idx(sp.lo());
+        let hi = self.lookup_source_file_idx(sp.hi());
+        if lo != hi {
+            return true;
+        }
+        let f = (*self.files.borrow().source_files)[lo].clone();
+        f.lookup_line(sp.lo()) != f.lookup_line(sp.hi())
     }
 
     pub fn is_valid_span(&self, sp: Span) -> Result<(Loc, Loc), SpanLinesError> {