about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan DPC <dylan.dpc@gmail.com>2021-02-17 23:51:14 +0100
committerGitHub <noreply@github.com>2021-02-17 23:51:14 +0100
commitd2232506629b3de71db97694889928bf91330566 (patch)
treeef3d134ec91ee6a8a8a237a7d7b53494f0f450a9
parent40e3af5a2131f0f211e2f247faceae4008c94ec9 (diff)
parent7e94641ee956989d57492975a1214fc79dcd1fce (diff)
downloadrust-d2232506629b3de71db97694889928bf91330566.tar.gz
rust-d2232506629b3de71db97694889928bf91330566.zip
Rollup merge of #81860 - osa1:issue81800, r=estebank
Fix SourceMap::start_point

`start_point` needs to return the *first* character's span, but it would
previously call `find_width_of_character_at_span` which returns the span
of the *last* character. The implementation is now fixed.

Other changes:

- Docs for start_point, end_point, find_width_of_character_at_span
  updated

- Minor simplification in find_width_of_character_at_span code

Fixes #81800
-rw-r--r--compiler/rustc_span/src/source_map.rs42
-rw-r--r--src/test/ui/span/issue-81800.rs2
-rw-r--r--src/test/ui/span/issue-81800.stderr19
3 files changed, 51 insertions, 12 deletions
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index 298c995b166..b7eb6d5b379 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -778,16 +778,35 @@ impl SourceMap {
         self.span_until_char(sp, '{')
     }
 
-    /// Returns a new span representing just the start point of this span.
+    /// Returns a new span representing just the first character of the given span.
     pub fn start_point(&self, sp: Span) -> Span {
-        let pos = sp.lo().0;
-        let width = self.find_width_of_character_at_span(sp, false);
-        let corrected_start_position = pos.checked_add(width).unwrap_or(pos);
-        let end_point = BytePos(cmp::max(corrected_start_position, sp.lo().0));
-        sp.with_hi(end_point)
+        let width = {
+            let sp = sp.data();
+            let local_begin = self.lookup_byte_offset(sp.lo);
+            let start_index = local_begin.pos.to_usize();
+            let src = local_begin.sf.external_src.borrow();
+
+            let snippet = if let Some(ref src) = local_begin.sf.src {
+                Some(&src[start_index..])
+            } else if let Some(src) = src.get_source() {
+                Some(&src[start_index..])
+            } else {
+                None
+            };
+
+            match snippet {
+                None => 1,
+                Some(snippet) => match snippet.chars().next() {
+                    None => 1,
+                    Some(c) => c.len_utf8(),
+                },
+            }
+        };
+
+        sp.with_hi(BytePos(sp.lo().0 + width as u32))
     }
 
-    /// Returns a new span representing just the end point of this span.
+    /// Returns a new span representing just the last character of this span.
     pub fn end_point(&self, sp: Span) -> Span {
         let pos = sp.hi().0;
 
@@ -816,7 +835,8 @@ impl SourceMap {
         Span::new(BytePos(start_of_next_point), end_of_next_point, sp.ctxt())
     }
 
-    /// Finds the width of a character, either before or after the provided span.
+    /// Finds the width of the character, either before or after the end of provided span,
+    /// depending on the `forwards` parameter.
     fn find_width_of_character_at_span(&self, sp: Span, forwards: bool) -> u32 {
         let sp = sp.data();
         if sp.lo == sp.hi {
@@ -863,11 +883,9 @@ impl SourceMap {
         // We need to extend the snippet to the end of the src rather than to end_index so when
         // searching forwards for boundaries we've got somewhere to search.
         let snippet = if let Some(ref src) = local_begin.sf.src {
-            let len = src.len();
-            &src[start_index..len]
+            &src[start_index..]
         } else if let Some(src) = src.get_source() {
-            let len = src.len();
-            &src[start_index..len]
+            &src[start_index..]
         } else {
             return 1;
         };
diff --git a/src/test/ui/span/issue-81800.rs b/src/test/ui/span/issue-81800.rs
new file mode 100644
index 00000000000..6ac66fdcb65
--- /dev/null
+++ b/src/test/ui/span/issue-81800.rs
@@ -0,0 +1,2 @@
+fn x˂- //~ ERROR: unknown start of token
+       //~^ ERROR: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-`
diff --git a/src/test/ui/span/issue-81800.stderr b/src/test/ui/span/issue-81800.stderr
new file mode 100644
index 00000000000..d37f13a6683
--- /dev/null
+++ b/src/test/ui/span/issue-81800.stderr
@@ -0,0 +1,19 @@
+error: unknown start of token: \u{2c2}
+  --> $DIR/issue-81800.rs:1:5
+   |
+LL | fn x˂-
+   |     ^
+   |
+help: Unicode character '˂' (Modifier Letter Left Arrowhead) looks like '<' (Less-Than Sign), but it is not
+   |
+LL | fn x<-
+   |     ^
+
+error: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-`
+  --> $DIR/issue-81800.rs:1:6
+   |
+LL | fn x˂-
+   |      ^ expected one of `#`, `>`, `const`, identifier, or lifetime
+
+error: aborting due to 2 previous errors
+