Repository: rust-lang/rust-analyzer
Pull request #12000 (2022-04-15 17:16:31)

fix: Tag `macro_rules` macro bang with `MacroBang` tag
cc https://github.com/rust-lang/rust-analyzer/issues/11996



Patch:
diff --git a/crates/hir_def/src/builtin_type.rs b/crates/hir_def/src/builtin_type.rs
index 25a408036f..7cbaf30b85 100644
--- a/crates/hir_def/src/builtin_type.rs
+++ b/crates/hir_def/src/builtin_type.rs
@@ -68,10 +68,6 @@ impl BuiltinType {
         (name![f32], BuiltinType::Float(BuiltinFloat::F32)),
         (name![f64], BuiltinType::Float(BuiltinFloat::F64)),
     ];
-
-    pub fn by_name(name: &Name) -> Option<Self> {
-        Self::ALL.iter().find_map(|(n, ty)| if n == name { Some(*ty) } else { None })
-    }
 }
 
 impl AsName for BuiltinType {
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index f12d9a1273..b24ba61ea0 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -90,10 +90,11 @@ impl<'a> Printer<'a> {
         for attr in &**attrs {
             wln!(
                 self,
-                "#{}[{}{}]",
+                "#{}[{}{}]  // {:?}",
                 inner,
                 attr.path,
                 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
+                attr.id,
             );
         }
     }
@@ -241,19 +242,10 @@ impl<'a> Printer<'a> {
                     ast_id: _,
                     flags,
                 } = &self.tree[it];
-                self.print_visibility(*visibility);
-                if flags.contains(FnFlags::HAS_DEFAULT_KW) {
-                    w!(self, "default ");
-                }
-                if flags.contains(FnFlags::HAS_CONST_KW) {
-                    w!(self, "const ");
-                }
-                if flags.contains(FnFlags::HAS_ASYNC_KW) {
-                    w!(self, "async ");
-                }
-                if flags.contains(FnFlags::HAS_UNSAFE_KW) {
-                    w!(self, "unsafe ");
+                if flags.bits != 0 {
+                    wln!(self, "// flags = 0x{:X}", flags.bits);
                 }
+                self.print_visibility(*visibility);
                 if let Some(abi) = abi {
                     w!(self, "extern \"{}\" ", abi);
                 }
@@ -262,7 +254,7 @@ impl<'a> Printer<'a> {
                 w!(self, "(");
                 if !params.is_empty() {
                     self.indented(|this| {
-                        for (i, param) in params.clone().enumerate() {
+                        for param in params.clone() {
                             this.print_attrs_of(param);
                             match &this.tree[param] {
                                 Param::Normal(name, ty) => {
@@ -271,12 +263,7 @@ impl<'a> Printer<'a> {
                                         None => w!(this, "_: "),
                                     }
                                     this.print_type_ref(ty);
-                                    w!(this, ",");
-                                    if flags.contains(FnFlags::HAS_SELF_PARAM) && i == 0 {
-                                        wln!(this, "  // self");
-                                    } else {
-                                        wln!(this);
-                                    }
+                                    wln!(this, ",");
                                 }
                                 Param::Varargs => {
                                     wln!(this, "...");
@@ -288,11 +275,7 @@ impl<'a> Printer<'a> {
                 w!(self, ") -> ");
                 self.print_type_ref(ret_type);
                 self.print_where_clause(explicit_generic_params);
-                if flags.contains(FnFlags::HAS_BODY) {
-                    wln!(self, " {{ ... }}");
-                } else {
-                    wln!(self, ";");
-                }
+                wln!(self, ";");
             }
             ModItem::Struct(it) => {
                 let Struct { visibility, name, fields, generic_params, ast_id: _ } = &self.tree[it];
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 2a990765ea..fe0100fb8c 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -317,18 +317,6 @@ impl Resolver {
             }
         }
 
-        // If a path of the shape `u16::from_le_bytes` failed to resolve at all, then we fall back
-        // to resolving to the primitive type, to allow this to still work in the presence of
-        // `use core::u16;`.
-        if path.kind == PathKind::Plain && path.segments().len() > 1 {
-            match BuiltinType::by_name(&path.segments()[0]) {
-                Some(builtin) => {
-                    return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1));
-                }
-                None => {}
-            }
-        }
-
         None
     }
 
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index 866bba7d1b..3fd0748172 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -98,7 +98,7 @@ fn punctuation(sema: &Semantics<RootDatabase>, token: SyntaxToken, kind: SyntaxK
             }
         }
         (T![::] | T![->] | T![=>] | T![..] | T![=] | T![@] | T![.], _) => HlOperator::Other.into(),
-        (T![!], MACRO_CALL) => HlPunct::MacroBang.into(),
+        (T![!], MACRO_CALL | MACRO_RULES) => HlPunct::MacroBang.into(),
         (T![!], NEVER_TYPE) => HlTag::BuiltinType.into(),
         (T![!], PREFIX_EXPR) => HlOperator::Logical.into(),
         (T![*], PTR_TYPE) => HlTag::Keyword.into(),
diff --git a/crates/ide/src/typing.rs b/crates/ide/src/typing.rs
index a75e6be8b8..0095012791 100644
--- a/crates/ide/src/typing.rs
+++ b/crates/ide/src/typing.rs
@@ -39,11 +39,8 @@ pub(crate) const TRIGGER_CHARS: &str = ".=>{";
 // Some features trigger on typing certain characters:
 //
 // - typing `let =` tries to smartly add `;` if `=` is followed by an existing expression
-// - typing `=` between two expressions adds `;` when in statement position
-// - typing `=` to turn an assignment into an equality comparison removes `;` when in expression position
 // - typing `.` in a chain method call auto-indents
 // - typing `{` in front of an expression inserts a closing `}` after the expression
-// - typing `{` in a use item adds a closing `}` in the right place
 //
 // VS Code::
 //
@@ -169,73 +166,11 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
     if !stdx::always!(file.syntax().text().char_at(offset) == Some('=')) {
         return None;
     }
-
-    if let Some(edit) = let_stmt(file, offset) {
-        return Some(edit);
-    }
-    if let Some(edit) = assign_expr(file, offset) {
-        return Some(edit);
-    }
-    if let Some(edit) = assign_to_eq(file, offset) {
-        return Some(edit);
-    }
-
-    return None;
-
-    fn assign_expr(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let binop: ast::BinExpr = find_node_at_offset(file.syntax(), offset)?;
-        if !matches!(binop.op_kind(), Some(ast::BinaryOp::Assignment { op: None })) {
-            return None;
-        }
-
-        // Parent must be `ExprStmt` or `StmtList` for `;` to be valid.
-        if let Some(expr_stmt) = ast::ExprStmt::cast(binop.syntax().parent()?) {
-            if expr_stmt.semicolon_token().is_some() {
-                return None;
-            }
-        } else {
-            if !ast::StmtList::can_cast(binop.syntax().parent()?.kind()) {
-                return None;
-            }
-        }
-
-        let expr = binop.rhs()?;
-        let expr_range = expr.syntax().text_range();
-        if expr_range.contains(offset) && offset != expr_range.start() {
-            return None;
-        }
-        if file.syntax().text().slice(offset..expr_range.start()).contains_char('\n') {
-            return None;
-        }
-        let offset = expr.syntax().text_range().end();
-        Some(TextEdit::insert(offset, ";".to_string()))
-    }
-
-    /// `a =$0 b;` removes the semicolon if an expression is valid in this context.
-    fn assign_to_eq(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let binop: ast::BinExpr = find_node_at_offset(file.syntax(), offset)?;
-        if !matches!(binop.op_kind(), Some(ast::BinaryOp::CmpOp(ast::CmpOp::Eq { negated: false })))
-        {
-            return None;
-        }
-
-        let expr_stmt = ast::ExprStmt::cast(binop.syntax().parent()?)?;
-        let semi = expr_stmt.semicolon_token()?;
-
-        if expr_stmt.syntax().next_sibling().is_some() {
-            // Not the last statement in the list.
-            return None;
-        }
-
-        Some(TextEdit::delete(semi.text_range()))
+    let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
+    if let_stmt.semicolon_token().is_some() {
+        return None;
     }
-
-    fn let_stmt(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
-        let let_stmt: ast::LetStmt = find_node_at_offset(file.syntax(), offset)?;
-        if let_stmt.semicolon_token().is_some() {
-            return None;
-        }
-        let expr = let_stmt.initializer()?;
+    if let Some(expr) = let_stmt.initializer() {
         let expr_range = expr.syntax().text_range();
         if expr_range.contains(offset) && offset != expr_range.start() {
             return None;
@@ -243,9 +178,11 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
         if file.syntax().text().slice(offset..expr_range.start()).contains_char('\n') {
             return None;
         }
-        let offset = let_stmt.syntax().text_range().end();
-        Some(TextEdit::insert(offset, ";".to_string()))
+    } else {
+        return None;
     }
+    let offset = let_stmt.syntax().text_range().end();
+    Some(TextEdit::insert(offset, ";".to_string()))
 }
 
 /// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
@@ -349,7 +286,7 @@ mod tests {
     }
 
     #[test]
-    fn test_semi_after_let() {
+    fn test_on_eq_typed() {
         //     do_check(r"
         // fn foo() {
         //     let foo =$0
@@ -385,117 +322,6 @@ fn foo() {
         // ");
     }
 
-    #[test]
-    fn test_semi_after_assign() {
-        type_char(
-            '=',
-            r#"
-fn f() {
-    i $0 0
-}
-"#,
-            r#"
-fn f() {
-    i = 0;
-}
-"#,
-        );
-        type_char(
-            '=',
-            r#"
-fn f() {
-    i $0 0
-    i
-}
-"#,
-            r#"
-fn f() {
-    i = 0;
-    i
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0 {}
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(x: u8) {
-    if x $0 0 {}
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f() {
-    g(i $0 0);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn assign_to_eq() {
-        type_char(
-            '=',
-            r#"
-fn f(a: u8) {
-    a =$0 0;
-}
-"#,
-            r#"
-fn f(a: u8) {
-    a == 0
-}
-"#,
-        );
-        type_char(
-            '=',
-            r#"
-fn f(a: u8) {
-    a $0= 0;
-}
-"#,
-            r#"
-fn f(a: u8) {
-    a == 0
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(a: u8) {
-    let e = a =$0 0;
-}
-"#,
-        );
-        type_char_noop(
-            '=',
-            r#"
-fn f(a: u8) {
-    let e = a =$0 0;
-    e
-}
-"#,
-        );
-    }
-
     #[test]
     fn indents_new_chain_call() {
         type_char(
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index ba5a47f4df..3566b1be89 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -52,7 +52,7 @@ pub(crate) fn expand_glob_import(acc: &mut Assists, ctx: &AssistContext) -> Opti
     let current_scope = ctx.sema.scope(&star.parent()?)?;
     let current_module = current_scope.module();
 
-    let refs_in_target = find_refs_in_mod(ctx, target_module, current_module)?;
+    let refs_in_target = find_refs_in_mod(ctx, target_module, Some(current_module))?;
     let imported_defs = find_imported_defs(ctx, star)?;
 
     let target = parent.either(|n| n.syntax().clone(), |n| n.syntax().clone());
@@ -168,12 +168,18 @@ impl Refs {
     }
 }
 
-fn find_refs_in_mod(ctx: &AssistContext, module: Module, visible_from: Module) -> Option<Refs> {
-    if !is_mod_visible_from(ctx, module, visible_from) {
-        return None;
+fn find_refs_in_mod(
+    ctx: &AssistContext,
+    module: Module,
+    visible_from: Option<Module>,
+) -> Option<Refs> {
+    if let Some(from) = visible_from {
+        if !is_mod_visible_from(ctx, module, from) {
+            return None;
+        }
     }
 
-    let module_scope = module.scope(ctx.db(), Some(visible_from));
+    let module_scope = module.scope(ctx.db(), visible_from);
     let refs = module_scope.into_iter().filter_map(|(n, d)| Ref::from_scope_def(n, d)).collect();
     Some(Refs(refs))
 }
@@ -723,34 +729,37 @@ fn qux(bar: Bar, baz: Baz) {
 
     #[test]
     fn expanding_glob_import_with_macro_defs() {
-        check_assist(
-            expand_glob_import,
-            r#"
-//- /lib.rs crate:foo
-#[macro_export]
-macro_rules! bar {
-    () => ()
-}
-
-pub fn baz() {}
-
-//- /main.rs crate:main deps:foo
-use foo::*$0;
-
-fn main() {
-    bar!();
-    baz();
-}
-"#,
-            r#"
-use foo::{bar, baz};
-
-fn main() {
-    bar!();
-    baz();
-}
-"#,
-        );
+        // FIXME: this is currently fails because `Definition::find_usages` ignores macros
+        //       https://github.com/rust-analyzer/rust-analyzer/issues/3484
+        //
+        //         check_assist(
+        //             expand_glob_import,
+        //             r"
+        // //- /lib.rs crate:foo
+        // #[macro_export]
+        // macro_rules! bar {
+        //     () => ()
+        // }
+
+        // pub fn baz() {}
+
+        // //- /main.rs crate:main deps:foo
+        // use foo::*$0;
+
+        // fn main() {
+        //     bar!();
+        //     baz();
+        // }
+        // ",
+        //             r"
+        // use foo::{bar, baz};
+
+        // fn main() {
+        //     bar!();
+        //     baz();
+        // }
+        // ",
+        //         )
     }
 
     #[test]
diff --git a/crates/ide_completion/src/completions/keyword.rs b/crates/ide_completion/src/completions/keyword.rs
index 51405e3523..ac782352fc 100644
--- a/crates/ide_completion/src/completions/keyword.rs
+++ b/crates/ide_completion/src/completions/keyword.rs
@@ -86,7 +86,7 @@ pub(crate) fn complete_expr_keyword(acc: &mut Completions, ctx: &CompletionConte
         add_keyword("mod", "mod $0");
     }
 
-    if expects_item || has_block_expr_parent {
+    if expects_item {
         add_keyword("enum", "enum $1 {\n    $0\n}");
         add_keyword("struct", "struct $0");
         add_keyword("union", "union $1 {\n    $0\n}");
diff --git a/crates/ide_ssr/Cargo.toml b/crates/ide_ssr/Cargo.toml
index db6991d4e5..9135857c38 100644
--- a/crates/ide_ssr/Cargo.toml
+++ b/crates/ide_ssr/Cargo.toml
@@ -3,7 +3,7 @@ name = "ide_ssr"
 version = "0.0.0"
 description = "Structural search and replace of Rust code"
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 edition = "2021"
 rust-version = "1.57"
 
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 99bc30f076..bb4d10207d 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -3,7 +3,7 @@ name = "syntax"
 version = "0.0.0"
 description = "Comment and whitespace preserving parser for the Rust language"
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 edition = "2021"
 rust-version = "1.57"
 
diff --git a/lib/arena/Cargo.toml b/lib/arena/Cargo.toml
index 2d3243a29b..39b005d094 100644
--- a/lib/arena/Cargo.toml
+++ b/lib/arena/Cargo.toml
@@ -3,7 +3,7 @@ name = "la-arena"
 version = "0.3.0"
 description = "Simple index-based arena without deletion."
 license = "MIT OR Apache-2.0"
-repository = "https://github.com/rust-lang/rust-analyzer"
+repository = "https://github.com/rust-analyzer/rust-analyzer"
 documentation = "https://docs.rs/la-arena"
 categories = ["data-structures", "memory-management", "rust-patterns"]
 edition = "2021"


Test patch:
diff --git a/crates/hir_def/src/item_tree/tests.rs b/crates/hir_def/src/item_tree/tests.rs
index fb3811dbd5..65352e7444 100644
--- a/crates/hir_def/src/item_tree/tests.rs
+++ b/crates/hir_def/src/item_tree/tests.rs
@@ -30,9 +30,9 @@ use crate::{A, B};
 use a::{c, d::{e}};
         "#,
         expect![[r##"
-            #![doc = " file comment"]
-            #![no_std]
-            #![doc = " another file comment"]
+            #![doc = " file comment"]  // AttrId { ast_index: 0 }
+            #![no_std]  // AttrId { ast_index: 1 }
+            #![doc = " another file comment"]  // AttrId { ast_index: 2 }
 
             pub(self) extern crate self as renamed;
 
@@ -42,7 +42,7 @@ use a::{c, d::{e}};
 
             pub(self) use globs::*;
 
-            #[doc = " docs on import"]
+            #[doc = " docs on import"]  // AttrId { ast_index: 0 }
             pub(self) use crate::{A, B};
 
             pub(self) use a::{c, d::{e}};
@@ -67,15 +67,15 @@ extern "C" {
 }
         "#,
         expect![[r##"
-            #[on_extern_block]
+            #[on_extern_block]  // AttrId { ast_index: 0 }
             extern "C" {
-                #[on_extern_type]
+                #[on_extern_type]  // AttrId { ast_index: 0 }
                 pub(self) type ExType;
 
-                #[on_extern_static]
+                #[on_extern_static]  // AttrId { ast_index: 0 }
                 pub(self) static EX_STATIC: u8 = _;
 
-                #[on_extern_fn]
+                #[on_extern_fn]  // AttrId { ast_index: 0 }
                 pub(self) fn ex_fn() -> ();
             }
         "##]],
@@ -115,14 +115,14 @@ enum E {
         expect![[r##"
             pub(self) struct Unit;
 
-            #[derive(Debug)]
+            #[derive(Debug)]  // AttrId { ast_index: 0 }
             pub(self) struct Struct {
-                #[doc = " fld docs"]
+                #[doc = " fld docs"]  // AttrId { ast_index: 0 }
                 pub(self) fld: (),
             }
 
             pub(self) struct Tuple(
-                #[attr]
+                #[attr]  // AttrId { ast_index: 0 }
                 pub(self) 0: u8,
             );
 
@@ -132,14 +132,14 @@ enum E {
             }
 
             pub(self) enum E {
-                #[doc = " comment on Unit"]
+                #[doc = " comment on Unit"]  // AttrId { ast_index: 0 }
                 Unit,
-                #[doc = " comment on Tuple"]
+                #[doc = " comment on Tuple"]  // AttrId { ast_index: 0 }
                 Tuple(
                     pub(self) 0: u8,
                 ),
                 Struct {
-                    #[doc = " comment on a: u8"]
+                    #[doc = " comment on a: u8"]  // AttrId { ast_index: 0 }
                     pub(self) a: u8,
                 },
             }
@@ -170,13 +170,14 @@ trait Tr: SuperTrait + 'lifetime {
 
             pub(self) const _: Anon = _;
 
-            #[attr]
-            #[inner_attr_in_fn]
+            #[attr]  // AttrId { ast_index: 0 }
+            #[inner_attr_in_fn]  // AttrId { ast_index: 1 }
+            // flags = 0x2
             pub(self) fn f(
-                #[attr]
+                #[attr]  // AttrId { ast_index: 0 }
                 arg: u8,
                 _: (),
-            ) -> () { ... }
+            ) -> ();
 
             pub(self) trait Tr<Self>
             where
@@ -185,8 +186,9 @@ trait Tr: SuperTrait + 'lifetime {
             {
                 pub(self) type Assoc: AssocBound = Default;
 
+                // flags = 0x1
                 pub(self) fn method(
-                    _: &Self,  // self
+                    _: &Self,
                 ) -> ();
             }
         "##]],
@@ -209,12 +211,13 @@ mod inline {
 mod outline;
         "#,
         expect![[r##"
-            #[doc = " outer"]
-            #[doc = " inner"]
+            #[doc = " outer"]  // AttrId { ast_index: 0 }
+            #[doc = " inner"]  // AttrId { ast_index: 1 }
             pub(self) mod inline {
                 pub(self) use super::*;
 
-                pub(self) fn fn_in_module() -> () { ... }
+                // flags = 0x2
+                pub(self) fn fn_in_module() -> ();
             }
 
             pub(self) mod outline;
@@ -335,11 +338,12 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
                 T: 'a,
                 T: 'b
             {
+                // flags = 0x2
                 pub(self) fn f<G>(
                     arg: impl Copy,
                 ) -> impl Copy
                 where
-                    G: 'a { ... }
+                    G: 'a;
             }
 
             pub(self) enum Enum<'a, T, const U: u8> {
@@ -388,9 +392,10 @@ pub(crate) trait Tr {
             pub(crate) trait Tr<Self> {
                 pub(crate) fn f() -> ();
 
+                // flags = 0x3
                 pub(crate) fn method(
-                    _: &Self,  // self
-                ) -> () { ... }
+                    _: &Self,
+                ) -> ();
             }
         "#]],
     )
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 68463dc068..d97147541a 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1767,26 +1767,3 @@ fn foo() {
 "#,
     );
 }
-
-#[test]
-fn primitive_assoc_fn_shadowed_by_use() {
-    check_types(
-        r#"
-//- /lib.rs crate:lib deps:core
-use core::u16;
-
-fn f() -> u16 {
-    let x = u16::from_le_bytes();
-      x
-    //^ u16
-}
-
-//- /core.rs crate:core
-pub mod u16 {}
-
-impl u16 {
-    pub fn from_le_bytes() -> Self { 0 }
-}
-        "#,
-    )
-}
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
index 36e9ec6333..a747b4bc1f 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_doctest.html
@@ -144,10 +144,10 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 <span class="brace">}</span>
 
 <span class="comment documentation">/// ```</span>
-<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="punctuation injected">!</span><span class="none injected"> </span><span class="macro declaration injected">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="angle injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
+<span class="comment documentation">///</span><span class="comment documentation"> </span><span class="keyword injected">macro_rules</span><span class="macro_bang injected">!</span><span class="none injected"> </span><span class="macro declaration injected">noop</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="parenthesis injected">(</span><span class="punctuation injected">$</span><span class="none injected">expr</span><span class="colon injected">:</span><span class="none injected">expr</span><span class="parenthesis injected">)</span><span class="none injected"> </span><span class="operator injected">=</span><span class="angle injected">&gt;</span><span class="none injected"> </span><span class="brace injected">{</span><span class="none injected"> </span><span class="punctuation injected">$</span><span class="none injected">expr </span><span class="brace injected">}</span><span class="brace injected">}</span>
 <span class="comment documentation">///</span><span class="comment documentation"> </span><span class="macro injected">noop</span><span class="macro_bang injected">!</span><span class="parenthesis injected">(</span><span class="numeric_literal injected">1</span><span class="parenthesis injected">)</span><span class="semicolon injected">;</span>
 <span class="comment documentation">/// ```</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span>expr
     <span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 7cd6a5a72d..ba62b68e9d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -50,7 +50,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="keyword">use</span> <span class="keyword crate_root">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="brace">}</span>
 <span class="macro">void</span><span class="macro_bang">!</span><span class="parenthesis">(</span><span class="keyword">Self</span><span class="parenthesis">)</span><span class="semicolon">;</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
index 71add7e495..b725c80565 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html
@@ -48,7 +48,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
         <span class="comma">,</span><span class="builtin_type">i32</span> <span class="colon">:</span><span class="field declaration public">y</span> <span class="keyword">pub</span>
     <span class="brace">}</span> <span class="struct declaration">Foo</span> <span class="keyword">struct</span>
 <span class="brace">}</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">def_fn</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">def_fn</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="brace">}</span>
 <span class="brace">}</span>
 
@@ -58,17 +58,17 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">dont_color_me_braces</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">dont_color_me_braces</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span><span class="numeric_literal">0</span><span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">noop</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>expr<span class="colon">:</span>expr<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span>expr
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">keyword_frag</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="colon">:</span>ty<span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>type<span class="parenthesis">)</span>
 <span class="brace">}</span>
 
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
index 29a0a9f066..60bc290121 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_strings.html
@@ -42,20 +42,20 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
+<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">println</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="brace">{</span>
         <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>io<span class="colon">:</span><span class="colon">:</span>_print<span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args_nl<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="brace">}</span><span class="parenthesis">)</span>
 <span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">const_format_args</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">const_format_args</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">format_args_nl</span> <span class="brace">{</span><span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">panic</span> <span class="brace">{</span>
     <span class="keyword">pub</span> <span class="keyword">macro</span> <span class="macro declaration">panic_2015</span> <span class="brace">{</span>
@@ -81,13 +81,13 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="parenthesis attribute">(</span><span class="none attribute">std_panic</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">macro_export</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">panic</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">panic</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">assert</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">assert</span> <span class="brace">{</span><span class="brace">}</span>
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="builtin_attr attribute library">rustc_builtin_macro</span><span class="attribute_bracket attribute">]</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">asm</span> <span class="brace">{</span><span class="brace">}</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">asm</span> <span class="brace">{</span><span class="brace">}</span>
 
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">toho</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented"</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="parenthesis">(</span><span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>panic<span class="punctuation">!</span><span class="parenthesis">(</span><span class="string_literal">"not yet implemented: {}"</span><span class="comma">,</span> <span class="punctuation">$</span>crate<span class="colon">:</span><span class="colon">:</span>format_args<span class="punctuation">!</span><span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>arg<span class="parenthesis">)</span><span class="punctuation">+</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
index 113463aa7a..0716bae751 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html
@@ -42,12 +42,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
+<pre><code><span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">id</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="colon">:</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">$</span><span class="parenthesis">(</span><span class="punctuation">$</span>tt<span class="parenthesis">)</span><span class="punctuation">*</span>
     <span class="brace">}</span><span class="semicolon">;</span>
 <span class="brace">}</span>
-<span class="keyword">macro_rules</span><span class="punctuation">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
+<span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">unsafe_deref</span> <span class="brace">{</span>
     <span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="operator">=</span><span class="angle">&gt;</span> <span class="brace">{</span>
         <span class="punctuation">*</span><span class="parenthesis">(</span><span class="operator">&</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="keyword">as</span> <span class="punctuation">*</span><span class="keyword">const</span> <span class="parenthesis">(</span><span class="parenthesis">)</span><span class="parenthesis">)</span>
     <span class="brace">}</span><span class="semicolon">;</span>
diff --git a/crates/ide_completion/src/tests/expression.rs b/crates/ide_completion/src/tests/expression.rs
index f1950235d4..de283c705d 100644
--- a/crates/ide_completion/src/tests/expression.rs
+++ b/crates/ide_completion/src/tests/expression.rs
@@ -137,9 +137,6 @@ impl Unit {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -230,9 +227,6 @@ fn complete_in_block() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -275,9 +269,6 @@ fn complete_after_if_expr() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let
@@ -348,9 +339,6 @@ fn completes_in_loop_ctx() {
             kw trait
             kw static
             kw mod
-            kw enum
-            kw struct
-            kw union
             kw match
             kw while
             kw while let