save-analysis: handle << and >> operators inside [] in types
Fixes #37700
This commit is contained in:
parent
766f6e4782
commit
8a949dfea2
@ -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());
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user