From: Nick Cameron Date: Tue, 15 Nov 2016 04:03:27 +0000 (+1300) Subject: save-analysis: handle << and >> operators inside [] in types X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=8a949dfea2c26d55aad036cf2b4000a2d45f5159;p=rust.git save-analysis: handle << and >> operators inside [] in types Fixes #37700 --- diff --git a/src/librustc_save_analysis/span_utils.rs b/src/librustc_save_analysis/span_utils.rs index 031b9a6a5aa..9ec764b82f8 100644 --- a/src/librustc_save_analysis/span_utils.rs +++ b/src/librustc_save_analysis/span_utils.rs @@ -177,25 +177,44 @@ pub fn sub_span_for_meth_name(&self, span: Span) -> Option { } // 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 { 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, }; @@ -204,7 +223,7 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option { } 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 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option { 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 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option { // 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> - // 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 { let mut result: Vec = 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 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V 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 @@ pub fn spans_with_brackets(&self, span: Span, nesting: isize, limit: isize) -> V // path, trying to pull out the non-nested idents (e.g., avoiding 'a // in `>::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()); } } diff --git a/src/test/run-make/save-analysis/foo.rs b/src/test/run-make/save-analysis/foo.rs index e9ed897bf30..e8b69729af6 100644 --- a/src/test/run-make/save-analysis/foo.rs +++ b/src/test/run-make/save-analysis/foo.rs @@ -57,6 +57,12 @@ fn foo(x: &Write) {} 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); fn test_tup_struct(x: TupStruct) -> isize {