save-analysis: handle << and >> operators inside [] in types

Fixes #37700
This commit is contained in:
Nick Cameron 2016-11-15 17:03:27 +13:00
parent 766f6e4782
commit 8a949dfea2
2 changed files with 48 additions and 14 deletions

View File

@ -177,34 +177,53 @@ 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);
}
bracket_count += match prev.tok {
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::OpenDelim(token::Bracket) => 1,
token::CloseDelim(token::Bracket) => -1,
_ => 0,
};
if next.tok == token::Eof {
break;
}
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 '{}' \
@ -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)
@ -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![];
}
@ -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,
@ -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());
}
}

View File

@ -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 {