diff options
| author | bors <bors@rust-lang.org> | 2018-03-10 10:52:07 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-03-10 10:52:07 +0000 |
| commit | 87344aa59af2ebb868253228e2b558d701573dff (patch) | |
| tree | e64ad8739124433604b5a5106a5c8ef617447799 /src/libsyntax | |
| parent | 948e3a30e6ec8417bcfdb923cd414fdf8fc87795 (diff) | |
| parent | 0e68bb97285a1ade22cf6e68103dc54fb75db43f (diff) | |
| download | rust-87344aa59af2ebb868253228e2b558d701573dff.tar.gz rust-87344aa59af2ebb868253228e2b558d701573dff.zip | |
Auto merge of #47574 - zilbuz:issue-14844, r=nikomatsakis
Show the used type variable when issuing a "can't use type parameters from outer function" error message Fix #14844 r? @estebank
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/codemap.rs | 66 |
1 files changed, 63 insertions, 3 deletions
diff --git a/src/libsyntax/codemap.rs b/src/libsyntax/codemap.rs index 53ddbfbfd4a..c340f1b8c8a 100644 --- a/src/libsyntax/codemap.rs +++ b/src/libsyntax/codemap.rs @@ -533,7 +533,12 @@ impl CodeMap { Ok(FileLines {file: lo.file, lines: lines}) } - pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> { + /// Extract the source surrounding the given `Span` using the `extract_source` function. The + /// extract function takes three arguments: a string slice containing the source, an index in + /// the slice for the beginning of the span and an index in the slice for the end of the span. + fn span_to_source<F>(&self, sp: Span, extract_source: F) -> Result<String, SpanSnippetError> + where F: Fn(&str, usize, usize) -> String + { if sp.lo() > sp.hi() { return Err(SpanSnippetError::IllFormedSpan(sp)); } @@ -567,9 +572,9 @@ impl CodeMap { } if let Some(ref src) = local_begin.fm.src { - return Ok((&src[start_index..end_index]).to_string()); + return Ok(extract_source(src, start_index, end_index)); } else if let Some(src) = local_begin.fm.external_src.borrow().get_source() { - return Ok((&src[start_index..end_index]).to_string()); + return Ok(extract_source(src, start_index, end_index)); } else { return Err(SpanSnippetError::SourceNotAvailable { filename: local_begin.fm.name.clone() @@ -578,6 +583,17 @@ impl CodeMap { } } + /// Return the source snippet as `String` corresponding to the given `Span` + pub fn span_to_snippet(&self, sp: Span) -> Result<String, SpanSnippetError> { + self.span_to_source(sp, |src, start_index, end_index| src[start_index..end_index] + .to_string()) + } + + /// Return the source snippet as `String` before the given `Span` + pub fn span_to_prev_source(&self, sp: Span) -> Result<String, SpanSnippetError> { + self.span_to_source(sp, |src, start_index, _| src[..start_index].to_string()) + } + /// Given a `Span`, try to get a shorter span ending before the first occurrence of `c` `char` pub fn span_until_char(&self, sp: Span, c: char) -> Span { match self.span_to_snippet(sp) { @@ -593,6 +609,32 @@ impl CodeMap { } } + /// Extend the given `Span` to just after the previous occurrence of `c`. Return the same span + /// if no character could be found or if an error occurred while retrieving the code snippet. + pub fn span_extend_to_prev_char(&self, sp: Span, c: char) -> Span { + if let Ok(prev_source) = self.span_to_prev_source(sp) { + let prev_source = prev_source.rsplit(c).nth(0).unwrap_or("").trim_left(); + if !prev_source.is_empty() && !prev_source.contains('\n') { + return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); + } + } + + sp + } + + /// Extend the given `Span` to just after the previous occurrence of `pat`. Return the same span + /// if no character could be found or if an error occurred while retrieving the code snippet. + pub fn span_extend_to_prev_str(&self, sp: Span, pat: &str) -> Span { + if let Ok(prev_source) = self.span_to_prev_source(sp) { + let prev_source = prev_source.rsplit(pat).nth(0).unwrap_or("").trim_left(); + if !prev_source.is_empty() && !prev_source.contains('\n') { + return sp.with_lo(BytePos(sp.lo().0 - prev_source.len() as u32)); + } + } + + sp + } + /// Given a `Span`, get a new `Span` covering the first token and all its trailing whitespace or /// the original `Span`. /// @@ -615,6 +657,24 @@ impl CodeMap { sp } + /// Given a `Span`, get a new `Span` covering the first token without its trailing whitespace or + /// the original `Span` in case of error. + /// + /// If `sp` points to `"let mut x"`, then a span pointing at `"let"` will be returned. + pub fn span_until_whitespace(&self, sp: Span) -> Span { + if let Ok(snippet) = self.span_to_snippet(sp) { + let mut offset = 0; + // Get the bytes width of all the non-whitespace characters + for c in snippet.chars().take_while(|c| !c.is_whitespace()) { + offset += c.len_utf8(); + } + if offset > 1 { + return sp.with_hi(BytePos(sp.lo().0 + offset as u32)); + } + } + sp + } + /// Given a `Span`, try to get a shorter span ending just after the first occurrence of `char` /// `c`. pub fn span_through_char(&self, sp: Span, c: char) -> Span { |
