about summary refs log tree commit diff
path: root/compiler/rustc_span
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2021-07-03 16:06:35 +0000
committerbors <bors@rust-lang.org>2021-07-03 16:06:35 +0000
commit96859dbaf6229f131fbd427a32aaa95d4f9cb132 (patch)
treee4fec5b9f22a98f051e19ead1483603e78f96d61 /compiler/rustc_span
parent8649737beefccbef2d6bc0113df4650dd05ad7f2 (diff)
parent7a410763facea6aab28cdaeb133179b11a979eb6 (diff)
downloadrust-96859dbaf6229f131fbd427a32aaa95d4f9cb132.tar.gz
rust-96859dbaf6229f131fbd427a32aaa95d4f9cb132.zip
Auto merge of #86778 - tmiasko:fast-multiline, r=davidtwco
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.
Diffstat (limited to 'compiler/rustc_span')
-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> {