Skip to content

Commit

Permalink
Fix SourceMap::start_point
Browse files Browse the repository at this point in the history
`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
  • Loading branch information
osa1 committed Feb 7, 2021
1 parent 36ecbc9 commit 7e94641
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 12 deletions.
42 changes: 30 additions & 12 deletions compiler/rustc_span/src/source_map.rs
Original file line number Diff line number Diff line change
Expand Up @@ -777,16 +777,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;

Expand Down Expand Up @@ -815,7 +834,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 {
Expand Down Expand Up @@ -862,11 +882,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;
};
Expand Down
2 changes: 2 additions & 0 deletions src/test/ui/span/issue-81800.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
fn x˂- //~ ERROR: unknown start of token
//~^ ERROR: expected one of `#`, `>`, `const`, identifier, or lifetime, found `-`
19 changes: 19 additions & 0 deletions src/test/ui/span/issue-81800.stderr
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 7e94641

Please sign in to comment.