]> git.lizzy.rs Git - rust.git/commitdiff
save-analysis: handle << and >> operators inside [] in types
authorNick Cameron <ncameron@mozilla.com>
Tue, 15 Nov 2016 04:03:27 +0000 (17:03 +1300)
committerNick Cameron <ncameron@mozilla.com>
Fri, 18 Nov 2016 00:06:16 +0000 (13:06 +1300)
Fixes #37700

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

index 031b9a6a5aa516049aa70b379719457ef222f507..9ec764b82f869bf1c9c90795b717dd8303e9a024 100644 (file)
@@ -177,25 +177,44 @@ pub fn sub_span_for_meth_name(&self, span: Span) -> Option<Span> {
     }
 
     // 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,
             };
 
@@ -204,7 +223,7 @@ pub fn sub_span_for_type_name(&self, span: Span) -> Option<Span> {
             }
             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<Span> {
                       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<Span> {
     // 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 @@ 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 `<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());
             }
         }
index e9ed897bf302be8e294e8a1224be72358918a6a1..e8b69729af673d6675a793b271e3e8c83a496cfc 100644 (file)
@@ -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<str>);
 
 fn test_tup_struct(x: TupStruct) -> isize {