Navigation Menu

Skip to content

Commit

Permalink
save-analysis: handle << and >> operators inside [] in types
Browse files Browse the repository at this point in the history
Fixes #37700
  • Loading branch information
nrc committed Nov 18, 2016
1 parent 766f6e4 commit 8a949df
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 14 deletions.
56 changes: 42 additions & 14 deletions src/librustc_save_analysis/span_utils.rs
Expand Up @@ -177,25 +177,44 @@ impl<'a> SpanUtils<'a> {
}

// Return the span for the last ident before a `<` and outside any
// brackets, or the last span.
// angle brackets, or the last span.
pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
let mut toks = self.retokenise_span(span);
let mut prev = toks.real_token();
let mut result = None;

// We keep track of the following two counts - the depth of nesting of
// angle brackets, and the depth of nesting of square brackets. For the
// angle bracket count, we only count tokens which occur outside of any
// square brackets (i.e. bracket_count == 0). The intutition here is
// that we want to count angle brackets in the type, but not any which
// could be in expression context (because these could mean 'less than',
// etc.).
let mut angle_count = 0;
let mut bracket_count = 0;
loop {
let next = toks.real_token();

if (next.tok == token::Lt || next.tok == token::Colon) && bracket_count == 0 &&
if (next.tok == token::Lt || next.tok == token::Colon) &&
angle_count == 0 &&
bracket_count == 0 &&
prev.tok.is_ident() {
result = Some(prev.sp);
}

if bracket_count == 0 {
angle_count += match prev.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shl) => 2,
token::BinOp(token::Shr) => -2,
_ => 0,
};
}

bracket_count += match prev.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shl) => 2,
token::BinOp(token::Shr) => -2,
token::OpenDelim(token::Bracket) => 1,
token::CloseDelim(token::Bracket) => -1,
_ => 0,
};

Expand All @@ -204,7 +223,7 @@ impl<'a> SpanUtils<'a> {
}
prev = next;
}
if bracket_count != 0 {
if angle_count != 0 || bracket_count != 0 {
let loc = self.sess.codemap().lookup_char_pos(span.lo);
span_bug!(span,
"Mis-counted brackets when breaking path? Parsing '{}' \
Expand All @@ -213,7 +232,7 @@ impl<'a> SpanUtils<'a> {
loc.file.name,
loc.line);
}
if result.is_none() && prev.tok.is_ident() && bracket_count == 0 {
if result.is_none() && prev.tok.is_ident() && angle_count == 0 {
return self.make_sub_span(span, Some(prev.sp));
}
self.make_sub_span(span, result)
Expand All @@ -222,19 +241,20 @@ impl<'a> SpanUtils<'a> {
// Reparse span and return an owned vector of sub spans of the first limit
// identifier tokens in the given nesting level.
// example with Foo<Bar<T,V>, Bar<T,V>>
// Nesting = 0: all idents outside of brackets: [Foo]
// Nesting = 1: idents within one level of brackets: [Bar, Bar]
// Nesting = 0: all idents outside of angle brackets: [Foo]
// Nesting = 1: idents within one level of angle brackets: [Bar, Bar]
pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> Vec<Span> {
let mut result: Vec<Span> = vec![];

let mut toks = self.retokenise_span(span);
// We keep track of how many brackets we're nested in
let mut angle_count: isize = 0;
let mut bracket_count: isize = 0;
let mut found_ufcs_sep = false;
loop {
let ts = toks.real_token();
if ts.tok == token::Eof {
if bracket_count != 0 {
if angle_count != 0 || bracket_count != 0 {
if generated_code(span) {
return vec![];
}
Expand All @@ -252,6 +272,14 @@ impl<'a> SpanUtils<'a> {
return result;
}
bracket_count += match ts.tok {
token::OpenDelim(token::Bracket) => 1,
token::CloseDelim(token::Bracket) => -1,
_ => 0,
};
if bracket_count > 0 {
continue;
}
angle_count += match ts.tok {
token::Lt => 1,
token::Gt => -1,
token::BinOp(token::Shl) => 2,
Expand All @@ -269,11 +297,11 @@ impl<'a> SpanUtils<'a> {
// path, trying to pull out the non-nested idents (e.g., avoiding 'a
// in `<A as B<'a>>::C`). So we end up with a span for `B>::C` from
// the start of the first ident to the end of the path.
if !found_ufcs_sep && bracket_count == -1 {
if !found_ufcs_sep && angle_count == -1 {
found_ufcs_sep = true;
bracket_count += 1;
angle_count += 1;
}
if ts.tok.is_ident() && bracket_count == nesting {
if ts.tok.is_ident() && angle_count == nesting {
result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
}
}
Expand Down
6 changes: 6 additions & 0 deletions src/test/run-make/save-analysis/foo.rs
Expand Up @@ -57,6 +57,12 @@ fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
let y = x.1;
}

// Issue #37700
const LUT_BITS: usize = 3;
pub struct HuffmanTable {
ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
}

struct TupStruct(isize, isize, Box<str>);

fn test_tup_struct(x: TupStruct) -> isize {
Expand Down

0 comments on commit 8a949df

Please sign in to comment.