Repository: rust-lang/rust-enhanced (language: rust)

Issue:
Syntax highlighting wrong for unions
### Sublime Text Version
Sublime Text 3 (Build 3143)

### Rust Enhanced Version
v2.10.0

### Operating system
Ubuntu 17.10

### Expected behavior
`union`s should be highlighted like `struct`s.

### Actual behavior
`union` is treated like an unknown keyword.

### Steps to reproduce
1. Write out a union definition like so:
```
#[repr(C)]
union Example {
    u0: u32,
    u1: u32,
}
```
2. Be disappointed that `union` is not highlighted.

Thank you for your work on this project.



Discussion / hints:
I'm not familiar with `union`, but some cursory research suggests we could probably just add `union` as a keyword for our current matching of struct definitions.  Anyone have other info?
Seems unions can't use tuple-definition or unit-definition.  
[This of the union RFC](https://github.com/rust-lang/rfcs/blob/master/text/1444-union.md#contextual-keyword) suggests we may need to be more careful about matching on `union`.
I started work on this a long while ago, but didn't finish because at the time the grammar wasn't really well defined, and I kept finding lots of little problems with the existing Sublime syntax.  Since then, a lot of great progress has been made on the reference.  [The section on unions](https://doc.rust-lang.org/reference/items/unions.html) would be a good start for this particular issue.  I can take another look at my old stuff and see what I have.

Fix patch:
diff --git a/RustEnhanced.sublime-syntax b/RustEnhanced.sublime-syntax
index e2e2f2e8..2f93fb70 100644
--- a/RustEnhanced.sublime-syntax
+++ b/RustEnhanced.sublime-syntax
@@ -67,6 +67,13 @@ contexts:
         2: storage.type.struct.rust
       push: struct-identifier
 
+    - match: '\b(?:(pub)\s+)?(union)\s+'
+      scope: meta.union.rust
+      captures:
+        1: storage.modifier.rust
+        2: storage.type.union.rust
+      push: union-identifier
+
     - match: '\b(?:(pub)\s+)?(type)\s+({{identifier}})\b'
       captures:
         1: storage.modifier.rust
@@ -540,23 +547,53 @@ contexts:
       pop: true
     - match: '\{'
       scope: punctuation.definition.block.begin.rust
+      push: struct-classic-body
+
+  struct-classic-body:
+    - meta_scope: meta.block.rust
+    - match: '(?=\})'
+      pop: true
+    - include: comments
+    - include: attribute
+    - match: \bpub\b
+      scope: storage.modifier.rust
+    - match: '{{identifier}}(?=\s*:)'
+      scope: variable.other.member.rust
       push:
-        - meta_scope: meta.block.rust
-        - match: '(?=\})'
+        - match: ',|(?=\})'
           pop: true
         - include: comments
-        - include: attribute
-        - match: \bpub\b
-          scope: storage.modifier.rust
-        - match: '{{identifier}}(?=\s*:)'
-          scope: variable.other.member.rust
-          push:
-            - match: ',|(?=\})'
-              pop: true
-            - include: comments
-            - match: ':'
-              scope: punctuation.separator.rust
-            - include: type-any-identifier
+        - match: ':'
+          scope: punctuation.separator.rust
+        - include: type-any-identifier
+
+
+  union-identifier:
+    - match: '{{identifier}}(?=<)'
+      scope: entity.name.union.rust
+      set:
+        - meta_scope: meta.union.rust meta.generic.rust
+        - match: '(?=<)'
+          push: generic-angles
+        - match: ''
+          set: union-body
+    - match: '{{identifier}}'
+      scope: entity.name.union.rust
+      set: union-body
+
+  union-body:
+    - meta_scope: meta.union.rust
+    - include: comments
+    - match: '(?=\bwhere\b)'
+      push: impl-where
+    - match: '\{'
+      scope: punctuation.definition.block.begin.rust
+      push: struct-classic-body
+    - match: '\}'
+      scope: meta.block.rust punctuation.definition.block.end.rust
+      pop: true
+    - match: '(?=;)'
+      pop: true
 
   macro-block:
     - meta_scope: meta.macro.rust


Test patch:
diff --git a/syntax_test_rust.rs b/syntax_test_rust.rs
index b7ac6b8d..83319dda 100644
--- a/syntax_test_rust.rs
+++ b/syntax_test_rust.rs
@@ -1160,3 +1160,39 @@ fn main() {
     }.collect::<Vec<_>>();
     println!("{:?}", l);
 }
+
+union Union {
+//^^^ meta.union storage.type.union
+//^^^^^^^^^^^ meta.union
+//    ^^^^^ entity.name.union
+//          ^ meta.block punctuation.definition.block.begin
+    f: u32,
+//  ^ meta.union meta.block variable.other.member
+//   ^ meta.union meta.block punctuation.separator
+//     ^^^ meta.union meta.block storage.type
+}
+// <- meta.union meta.block punctuation.definition.block.end
+
+pub union Foo<'a, Y: Baz>
+// <- storage.modifier
+//^^^^^^^^^^^^^^^^^^^^^^^ meta.union
+//  ^^^^^ meta.union storage.type.union
+//        ^^^ meta.union meta.generic entity.name.union
+//           ^ meta.union meta.generic meta.generic punctuation.definition.generic.begin
+//            ^^ meta.union meta.generic meta.generic storage.modifier.lifetime
+    where X: Whatever,
+//  ^^^^^ meta.union meta.where keyword.other
+//        ^ meta.union meta.where
+//         ^ meta.union meta.where punctuation.separator
+//           ^^^^^^^^^^ meta.union meta.where
+{
+// <- meta.union meta.block punctuation.definition.block.begin
+    f: SomeType, // Comment beside a field
+//               ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.union meta.block comment.line.double-slash
+}
+// <- meta.union meta.block punctuation.definition.block.end
+
+// Union was implemented in such a way that `union` is not a keyword.  Verify
+// that we don't accidentally interpret it as a keyword.
+fn union() {}
+// ^^^^^ meta.function entity.name.function