Skip to content

Commit b7dfc2b

Browse files
authored
Auto merge of #37776 - nrc:save-double-angle, r=@brson
save-analysis: handle << and >> operators inside [] in types Fixes #37700
2 parents 195c42c + 8a949df commit b7dfc2b

File tree

2 files changed

+48
-14
lines changed

2 files changed

+48
-14
lines changed

src/librustc_save_analysis/span_utils.rs

+42-14
Original file line numberDiff line numberDiff line change
@@ -177,25 +177,44 @@ impl<'a> SpanUtils<'a> {
177177
}
178178

179179
// Return the span for the last ident before a `<` and outside any
180-
// brackets, or the last span.
180+
// angle brackets, or the last span.
181181
pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
182182
let mut toks = self.retokenise_span(span);
183183
let mut prev = toks.real_token();
184184
let mut result = None;
185+
186+
// We keep track of the following two counts - the depth of nesting of
187+
// angle brackets, and the depth of nesting of square brackets. For the
188+
// angle bracket count, we only count tokens which occur outside of any
189+
// square brackets (i.e. bracket_count == 0). The intutition here is
190+
// that we want to count angle brackets in the type, but not any which
191+
// could be in expression context (because these could mean 'less than',
192+
// etc.).
193+
let mut angle_count = 0;
185194
let mut bracket_count = 0;
186195
loop {
187196
let next = toks.real_token();
188197

189-
if (next.tok == token::Lt || next.tok == token::Colon) && bracket_count == 0 &&
198+
if (next.tok == token::Lt || next.tok == token::Colon) &&
199+
angle_count == 0 &&
200+
bracket_count == 0 &&
190201
prev.tok.is_ident() {
191202
result = Some(prev.sp);
192203
}
193204

205+
if bracket_count == 0 {
206+
angle_count += match prev.tok {
207+
token::Lt => 1,
208+
token::Gt => -1,
209+
token::BinOp(token::Shl) => 2,
210+
token::BinOp(token::Shr) => -2,
211+
_ => 0,
212+
};
213+
}
214+
194215
bracket_count += match prev.tok {
195-
token::Lt => 1,
196-
token::Gt => -1,
197-
token::BinOp(token::Shl) => 2,
198-
token::BinOp(token::Shr) => -2,
216+
token::OpenDelim(token::Bracket) => 1,
217+
token::CloseDelim(token::Bracket) => -1,
199218
_ => 0,
200219
};
201220

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

230249
let mut toks = self.retokenise_span(span);
231250
// We keep track of how many brackets we're nested in
251+
let mut angle_count: isize = 0;
232252
let mut bracket_count: isize = 0;
233253
let mut found_ufcs_sep = false;
234254
loop {
235255
let ts = toks.real_token();
236256
if ts.tok == token::Eof {
237-
if bracket_count != 0 {
257+
if angle_count != 0 || bracket_count != 0 {
238258
if generated_code(span) {
239259
return vec![];
240260
}
@@ -252,6 +272,14 @@ impl<'a> SpanUtils<'a> {
252272
return result;
253273
}
254274
bracket_count += match ts.tok {
275+
token::OpenDelim(token::Bracket) => 1,
276+
token::CloseDelim(token::Bracket) => -1,
277+
_ => 0,
278+
};
279+
if bracket_count > 0 {
280+
continue;
281+
}
282+
angle_count += match ts.tok {
255283
token::Lt => 1,
256284
token::Gt => -1,
257285
token::BinOp(token::Shl) => 2,
@@ -269,11 +297,11 @@ impl<'a> SpanUtils<'a> {
269297
// path, trying to pull out the non-nested idents (e.g., avoiding 'a
270298
// in `<A as B<'a>>::C`). So we end up with a span for `B>::C` from
271299
// the start of the first ident to the end of the path.
272-
if !found_ufcs_sep && bracket_count == -1 {
300+
if !found_ufcs_sep && angle_count == -1 {
273301
found_ufcs_sep = true;
274-
bracket_count += 1;
302+
angle_count += 1;
275303
}
276-
if ts.tok.is_ident() && bracket_count == nesting {
304+
if ts.tok.is_ident() && angle_count == nesting {
277305
result.push(self.make_sub_span(span, Some(ts.sp)).unwrap());
278306
}
279307
}

src/test/run-make/save-analysis/foo.rs

+6
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ fn test_alias<I: Iterator>(i: Option<<I as Iterator>::Item>) {
5757
let y = x.1;
5858
}
5959

60+
// Issue #37700
61+
const LUT_BITS: usize = 3;
62+
pub struct HuffmanTable {
63+
ac_lut: Option<[(i16, u8); 1 << LUT_BITS]>,
64+
}
65+
6066
struct TupStruct(isize, isize, Box<str>);
6167

6268
fn test_tup_struct(x: TupStruct) -> isize {

0 commit comments

Comments
 (0)