Repository: rust-analyzer/rust-analyzer
Pull request #8221 (2021-03-27 22:32:57)

Prefer adding `mod` declaration to lib.rs over file.rs in UnlinkedFile fix
When there is a `lib.rs` and `main.rs` in one crate, one usually wants the `lib.rs` file to declare the modules.
bors r+

bors[bot]: Build failed:
  * [Rust (macos-latest)](https://github.com/rust-analyzer/rust-analyzer/runs/2210144259)

Patch:
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 229e81dd43..19f5065d13 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -74,7 +74,6 @@ pub(super) fn lower(
             _c: Count::new(),
         },
         expander,
-        statements_in_scope: Vec::new(),
     }
     .collect(params, body)
 }
@@ -84,7 +83,6 @@ struct ExprCollector<'a> {
     expander: Expander,
     body: Body,
     source_map: BodySourceMap,
-    statements_in_scope: Vec<Statement>,
 }
 
 impl ExprCollector<'_> {
@@ -535,13 +533,15 @@ impl ExprCollector<'_> {
                 ids[0]
             }
             ast::Expr::MacroStmts(e) => {
-                e.statements().for_each(|s| self.collect_stmt(s));
-                let tail = e
-                    .expr()
-                    .map(|e| self.collect_expr(e))
-                    .unwrap_or_else(|| self.alloc_expr(Expr::Missing, syntax_ptr.clone()));
-
-                self.alloc_expr(Expr::MacroStmts { tail }, syntax_ptr)
+                // FIXME:  these statements should be held by some hir containter
+                for stmt in e.statements() {
+                    self.collect_stmt(stmt);
+                }
+                if let Some(expr) = e.expr() {
+                    self.collect_expr(expr)
+                } else {
+                    self.alloc_expr(Expr::Missing, syntax_ptr)
+                }
             }
         })
     }
@@ -618,54 +618,58 @@ impl ExprCollector<'_> {
         }
     }
 
-    fn collect_stmt(&mut self, s: ast::Stmt) {
-        match s {
+    fn collect_stmt(&mut self, s: ast::Stmt) -> Option<Vec<Statement>> {
+        let stmt = match s {
             ast::Stmt::LetStmt(stmt) => {
-                if self.check_cfg(&stmt).is_none() {
-                    return;
-                }
+                self.check_cfg(&stmt)?;
+
                 let pat = self.collect_pat_opt(stmt.pat());
                 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it));
                 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
-                self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
+                vec![Statement::Let { pat, type_ref, initializer }]
             }
             ast::Stmt::ExprStmt(stmt) => {
-                if self.check_cfg(&stmt).is_none() {
-                    return;
-                }
+                self.check_cfg(&stmt)?;
 
                 // Note that macro could be expended to multiple statements
                 if let Some(ast::Expr::MacroCall(m)) = stmt.expr() {
                     let syntax_ptr = AstPtr::new(&stmt.expr().unwrap());
+                    let mut stmts = vec![];
 
                     self.collect_macro_call(m, syntax_ptr.clone(), false, |this, expansion| {
                         match expansion {
                             Some(expansion) => {
                                 let statements: ast::MacroStmts = expansion;
 
-                                statements.statements().for_each(|stmt| this.collect_stmt(stmt));
+                                statements.statements().for_each(|stmt| {
+                                    if let Some(mut r) = this.collect_stmt(stmt) {
+                                        stmts.append(&mut r);
+                                    }
+                                });
                                 if let Some(expr) = statements.expr() {
-                                    let expr = this.collect_expr(expr);
-                                    this.statements_in_scope.push(Statement::Expr(expr));
+                                    stmts.push(Statement::Expr(this.collect_expr(expr)));
                                 }
                             }
                             None => {
-                                let expr = this.alloc_expr(Expr::Missing, syntax_ptr.clone());
-                                this.statements_in_scope.push(Statement::Expr(expr));
+                                stmts.push(Statement::Expr(
+                                    this.alloc_expr(Expr::Missing, syntax_ptr.clone()),
+                                ));
                             }
                         }
                     });
+                    stmts
                 } else {
-                    let expr = self.collect_expr_opt(stmt.expr());
-                    self.statements_in_scope.push(Statement::Expr(expr));
+                    vec![Statement::Expr(self.collect_expr_opt(stmt.expr()))]
                 }
             }
             ast::Stmt::Item(item) => {
-                if self.check_cfg(&item).is_none() {
-                    return;
-                }
+                self.check_cfg(&item)?;
+
+                return None;
             }
-        }
+        };
+
+        Some(stmt)
     }
 
     fn collect_block(&mut self, block: ast::BlockExpr) -> ExprId {
@@ -681,12 +685,10 @@ impl ExprCollector<'_> {
         let module = if has_def_map { def_map.root() } else { self.expander.module };
         let prev_def_map = mem::replace(&mut self.expander.def_map, def_map);
         let prev_local_module = mem::replace(&mut self.expander.module, module);
-        let prev_statements = std::mem::take(&mut self.statements_in_scope);
-
-        block.statements().for_each(|s| self.collect_stmt(s));
 
+        let statements =
+            block.statements().filter_map(|s| self.collect_stmt(s)).flatten().collect();
         let tail = block.tail_expr().map(|e| self.collect_expr(e));
-        let statements = std::mem::replace(&mut self.statements_in_scope, prev_statements);
         let syntax_node_ptr = AstPtr::new(&block.into());
         let expr_id = self.alloc_expr(
             Expr::Block { id: block_id, statements, tail, label: None },
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad3..24be937739 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -171,9 +171,6 @@ pub enum Expr {
     Unsafe {
         body: ExprId,
     },
-    MacroStmts {
-        tail: ExprId,
-    },
     Array(Array),
     Literal(Literal),
 }
@@ -360,7 +357,6 @@ impl Expr {
                     f(*repeat)
                 }
             },
-            Expr::MacroStmts { tail } => f(*tail),
             Expr::Literal(_) => {}
         }
     }
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index ca0048b163..ae2475b4e4 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -110,6 +110,15 @@ impl ItemTree {
                     // still need to collect inner items.
                     ctx.lower_inner_items(e.syntax())
                 },
+                ast::ExprStmt(stmt) => {
+                    // Macros can expand to stmt. We return an empty item tree in this case, but
+                    // still need to collect inner items.
+                    ctx.lower_inner_items(stmt.syntax())
+                },
+                ast::Item(item) => {
+                    // Macros can expand to stmt and other item, and we add it as top level item
+                    ctx.lower_single_item(item)
+                },
                 _ => {
                     panic!("cannot create item tree from {:?} {}", syntax, syntax);
                 },
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3f558edd81..d3fe1ce1eb 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -87,6 +87,14 @@ impl Ctx {
         self.tree
     }
 
+    pub(super) fn lower_single_item(mut self, item: ast::Item) -> ItemTree {
+        self.tree.top_level = self
+            .lower_mod_item(&item, false)
+            .map(|item| item.0)
+            .unwrap_or_else(|| Default::default());
+        self.tree
+    }
+
     pub(super) fn lower_inner_items(mut self, within: &SyntaxNode) -> ItemTree {
         self.collect_inner_items(within);
         self.tree
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index d672f67238..fc73e435bf 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -5,13 +5,7 @@ use std::sync::Arc;
 use base_db::{salsa, SourceDatabase};
 use mbe::{ExpandError, ExpandResult, MacroRules};
 use parser::FragmentKind;
-use syntax::{
-    algo::diff,
-    ast::{MacroStmts, NameOwner},
-    AstNode, GreenNode, Parse,
-    SyntaxKind::*,
-    SyntaxNode,
-};
+use syntax::{algo::diff, ast::NameOwner, AstNode, GreenNode, Parse, SyntaxKind::*, SyntaxNode};
 
 use crate::{
     ast_id_map::AstIdMap, hygiene::HygieneFrame, BuiltinDeriveExpander, BuiltinFnLikeExpander,
@@ -346,19 +340,13 @@ fn parse_macro_with_arg(
         None => return ExpandResult { value: None, err: result.err },
     };
 
-    let fragment_kind = to_fragment_kind(db, macro_call_id);
-
     log::debug!("expanded = {}", tt.as_debug_string());
-    log::debug!("kind = {:?}", fragment_kind);
+
+    let fragment_kind = to_fragment_kind(db, macro_call_id);
 
     let (parse, rev_token_map) = match mbe::token_tree_to_syntax_node(&tt, fragment_kind) {
         Ok(it) => it,
         Err(err) => {
-            log::debug!(
-                "failed to parse expanstion to {:?} = {}",
-                fragment_kind,
-                tt.as_debug_string()
-            );
             return ExpandResult::only_err(err);
         }
     };
@@ -374,34 +362,15 @@ fn parse_macro_with_arg(
                     return ExpandResult::only_err(err);
                 }
             };
-            if is_self_replicating(&node, &call_node.value) {
-                return ExpandResult::only_err(err);
-            } else {
-                ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: Some(err) }
-            }
-        }
-        None => {
-            log::debug!("parse = {:?}", parse.syntax_node().kind());
-            ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: None }
-        }
-    }
-}
 
-fn is_self_replicating(from: &SyntaxNode, to: &SyntaxNode) -> bool {
-    if diff(from, to).is_empty() {
-        return true;
-    }
-    if let Some(stmts) = MacroStmts::cast(from.clone()) {
-        if stmts.statements().any(|stmt| diff(stmt.syntax(), to).is_empty()) {
-            return true;
-        }
-        if let Some(expr) = stmts.expr() {
-            if diff(expr.syntax(), to).is_empty() {
-                return true;
+            if !diff(&node, &call_node.value).is_empty() {
+                ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: Some(err) }
+            } else {
+                return ExpandResult::only_err(err);
             }
         }
+        None => ExpandResult { value: Some((parse, Arc::new(rev_token_map))), err: None },
     }
-    false
 }
 
 fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame> {
@@ -421,15 +390,21 @@ fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
 
     let parent = match syn.parent() {
         Some(it) => it,
-        None => return FragmentKind::Statements,
+        None => {
+            // FIXME:
+            // If it is root, which means the parent HirFile
+            // MacroKindFile must be non-items
+            // return expr now.
+            return FragmentKind::Expr;
+        }
     };
 
     match parent.kind() {
         MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
-        MACRO_STMTS => FragmentKind::Statements,
+        MACRO_STMTS => FragmentKind::Statement,
         ITEM_LIST => FragmentKind::Items,
         LET_STMT => {
-            // FIXME: Handle LHS Pattern
+            // FIXME: Handle Pattern
             FragmentKind::Expr
         }
         EXPR_STMT => FragmentKind::Statements,
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index e6ede05ca1..3f3187ea27 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -767,7 +767,6 @@ impl<'a> InferenceContext<'a> {
                     None => self.table.new_float_var(),
                 },
             },
-            Expr::MacroStmts { tail } => self.infer_expr(*tail, expected),
         };
         // use a new type variable if we got unknown here
         let ty = self.insert_type_vars_shallow(ty);
diff --git a/crates/ide/src/diagnostics/unlinked_file.rs b/crates/ide/src/diagnostics/unlinked_file.rs
index 019b0b440d..e174fb767f 100644
--- a/crates/ide/src/diagnostics/unlinked_file.rs
+++ b/crates/ide/src/diagnostics/unlinked_file.rs
@@ -63,7 +63,7 @@ impl DiagnosticWithFix for UnlinkedFile {
         // - `$dir.rs` in the parent folder, where `$dir` is the directory containing `self.file_id`
         let parent = our_path.parent()?;
         let mut paths =
-            vec![parent.join("mod.rs")?, parent.join("main.rs")?, parent.join("lib.rs")?];
+            vec![parent.join("mod.rs")?, parent.join("lib.rs")?, parent.join("main.rs")?];
 
         // `submod/bla.rs` -> `submod.rs`
         if let Some(newmod) = (|| {
diff --git a/crates/ide_assists/src/handlers/generate_impl.rs b/crates/ide_assists/src/handlers/generate_impl.rs
index fd2e250bc3..a8e3c4fc24 100644
--- a/crates/ide_assists/src/handlers/generate_impl.rs
+++ b/crates/ide_assists/src/handlers/generate_impl.rs
@@ -69,17 +69,6 @@ mod tests {
             "struct Foo<'a, T: Foo<'a>> {$0}",
             "struct Foo<'a, T: Foo<'a>> {}\n\nimpl<'a, T: Foo<'a>> Foo<'a, T> {\n    $0\n}",
         );
-        check_assist(
-            generate_impl,
-            r#"
-            struct MyOwnArray<T, const S: usize> {}$0"#,
-            r#"
-            struct MyOwnArray<T, const S: usize> {}
-
-            impl<T, const S: usize> MyOwnArray<T, S> {
-                $0
-            }"#,
-        );
         check_assist(
             generate_impl,
             r#"
@@ -125,11 +114,11 @@ mod tests {
         check_assist(
             generate_impl,
             r#"
-            struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String, const S: usize> {}$0"#,
+            struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String> {}$0"#,
             r#"
-            struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String, const S: usize> {}
+            struct Defaulted<'a, 'b: 'a, T: Debug + Clone + 'a + 'b = String> {}
 
-            impl<'a, 'b: 'a, T: Debug + Clone + 'a + 'b, const S: usize> Defaulted<'a, 'b, T, S> {
+            impl<'a, 'b: 'a, T: Debug + Clone + 'a + 'b> Defaulted<'a, 'b, T> {
                 $0
             }"#,
         );
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs
index 5f630ec75a..9de9e4dbd3 100644
--- a/crates/ide_assists/src/utils.rs
+++ b/crates/ide_assists/src/utils.rs
@@ -434,8 +434,7 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
             }
             buf
         });
-        let const_params = generic_params.const_params().map(|t| t.syntax().to_string());
-        let generics = lifetimes.chain(type_params).chain(const_params).format(", ");
+        let generics = lifetimes.chain(type_params).format(", ");
         format_to!(buf, "<{}>", generics);
     }
     buf.push(' ');
@@ -453,11 +452,7 @@ fn generate_impl_text_inner(adt: &ast::Adt, trait_text: Option<&str>, code: &str
             .type_params()
             .filter_map(|it| it.name())
             .map(|it| SmolStr::from(it.text()));
-        let const_params = generic_params
-            .const_params()
-            .filter_map(|it| it.name())
-            .map(|it| SmolStr::from(it.text()));
-        format_to!(buf, "<{}>", lifetime_params.chain(type_params).chain(const_params).format(", "))
+        format_to!(buf, "<{}>", lifetime_params.chain(type_params).format(", "))
     }
 
     match adt.where_clause() {
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index be3a22725a..e681ced801 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -1,6 +1,7 @@
 //! Handle syntactic aspects of inserting a new `use`.
 use std::{cmp::Ordering, iter::successors};
 
+use crate::RootDatabase;
 use hir::Semantics;
 use itertools::{EitherOrBoth, Itertools};
 use syntax::{
@@ -13,8 +14,6 @@ use syntax::{
     AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
 };
 
-use crate::RootDatabase;
-
 pub use hir::PrefixKind;
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
diff --git a/crates/ide_db/src/label.rs b/crates/ide_db/src/label.rs
index 1f1e715c97..c0e89e72f5 100644
--- a/crates/ide_db/src/label.rs
+++ b/crates/ide_db/src/label.rs
@@ -1,4 +1,4 @@
-//! See [`Label`]
+//! See `Label`
 use std::fmt;
 
 /// A type to specify UI label, like an entry in the list of assists. Enforces
diff --git a/crates/ide_db/src/search.rs b/crates/ide_db/src/search.rs
index b55e3851eb..3634b2b267 100644
--- a/crates/ide_db/src/search.rs
+++ b/crates/ide_db/src/search.rs
@@ -12,8 +12,9 @@ use once_cell::unsync::Lazy;
 use rustc_hash::FxHashMap;
 use syntax::{ast, match_ast, AstNode, TextRange, TextSize};
 
+use crate::defs::NameClass;
 use crate::{
-    defs::{Definition, NameClass, NameRefClass},
+    defs::{Definition, NameRefClass},
     RootDatabase,
 };
 
diff --git a/crates/ide_db/src/source_change.rs b/crates/ide_db/src/source_change.rs
index 846530f784..b36455d494 100644
--- a/crates/ide_db/src/source_change.rs
+++ b/crates/ide_db/src/source_change.rs
@@ -37,8 +37,6 @@ impl SourceChange {
         }
     }
 
-    /// Inserts a [`TextEdit`] for the given [`FileId`]. This properly handles merging existing
-    /// edits for a file if some already exist.
     pub fn insert_source_edit(&mut self, file_id: FileId, edit: TextEdit) {
         match self.source_file_edits.entry(file_id) {
             Entry::Occupied(mut entry) => {
diff --git a/crates/ide_db/src/traits.rs b/crates/ide_db/src/traits.rs
index 66ae81c73e..78a43f587a 100644
--- a/crates/ide_db/src/traits.rs
+++ b/crates/ide_db/src/traits.rs
@@ -61,7 +61,7 @@ pub fn get_missing_assoc_items(
     resolve_target_trait(sema, impl_def).map_or(vec![], |target_trait| {
         target_trait
             .items(sema.db)
-            .into_iter()
+            .iter()
             .filter(|i| match i {
                 hir::AssocItem::Function(f) => {
                     !impl_fns_consts.contains(&f.name(sema.db).to_string())
@@ -72,6 +72,7 @@ pub fn get_missing_assoc_items(
                     .map(|n| !impl_fns_consts.contains(&n.to_string()))
                     .unwrap_or_default(),
             })
+            .cloned()
             .collect()
     })
 }
diff --git a/crates/ide_db/src/ty_filter.rs b/crates/ide_db/src/ty_filter.rs
index 988ecd0607..f8406851bd 100644
--- a/crates/ide_db/src/ty_filter.rs
+++ b/crates/ide_db/src/ty_filter.rs
@@ -2,13 +2,11 @@
 //! Use case for structures in this module is, for example, situation when you need to process
 //! only certain `Enum`s.
 
-use std::iter;
-
+use crate::RootDatabase;
 use hir::{Adt, Semantics, Type};
+use std::iter;
 use syntax::ast::{self, make};
 
-use crate::RootDatabase;
-
 /// Enum types that implement `std::ops::Try` trait.
 #[derive(Clone, Copy)]
 pub enum TryEnum {
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index 2772d73644..6d7db5fb26 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -8,23 +8,23 @@ use parser::SyntaxKind;
 
 use crate::{
     ast::{self, support, AstNode, AstToken, AttrsOwner, NameOwner, SyntaxNode},
-    SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
+    SmolStr, SyntaxElement, SyntaxToken, T,
 };
 
 impl ast::Lifetime {
-    pub fn text(&self) -> TokenText {
+    pub fn text(&self) -> SmolStr {
         text_of_first_token(self.syntax())
     }
 }
 
 impl ast::Name {
-    pub fn text(&self) -> TokenText {
+    pub fn text(&self) -> SmolStr {
         text_of_first_token(self.syntax())
     }
 }
 
 impl ast::NameRef {
-    pub fn text(&self) -> TokenText {
+    pub fn text(&self) -> SmolStr {
         text_of_first_token(self.syntax())
     }
 
@@ -33,11 +33,8 @@ impl ast::NameRef {
     }
 }
 
-fn text_of_first_token(node: &SyntaxNode) -> TokenText {
-    let first_token =
-        node.green().children().next().and_then(|it| it.into_token()).unwrap().to_owned();
-
-    TokenText(first_token)
+fn text_of_first_token(node: &SyntaxNode) -> SmolStr {
+    node.green().children().next().and_then(|it| it.into_token()).unwrap().text().into()
 }
 
 pub enum Macro {
@@ -379,7 +376,7 @@ impl fmt::Display for NameOrNameRef {
 }
 
 impl NameOrNameRef {
-    pub fn text(&self) -> TokenText {
+    pub fn text(&self) -> SmolStr {
         match self {
             NameOrNameRef::Name(name) => name.text(),
             NameOrNameRef::NameRef(name_ref) => name_ref.text(),
diff --git a/crates/syntax/src/lib.rs b/crates/syntax/src/lib.rs
index 90de6bef6f..2a5c61171b 100644
--- a/crates/syntax/src/lib.rs
+++ b/crates/syntax/src/lib.rs
@@ -29,7 +29,6 @@ mod syntax_error;
 mod parsing;
 mod validation;
 mod ptr;
-mod token_text;
 #[cfg(test)]
 mod tests;
 
@@ -56,7 +55,6 @@ pub use crate::{
         SyntaxElement, SyntaxElementChildren, SyntaxNode, SyntaxNodeChildren, SyntaxToken,
         SyntaxTreeBuilder,
     },
-    token_text::TokenText,
 };
 pub use parser::{SyntaxKind, T};
 pub use rowan::{
diff --git a/crates/syntax/src/token_text.rs b/crates/syntax/src/token_text.rs
deleted file mode 100644
index d2ed0a12a4..0000000000
--- a/crates/syntax/src/token_text.rs
+++ /dev/null
@@ -1,77 +0,0 @@
-//! Yet another version of owned string, backed by a syntax tree token.
-
-use std::{cmp::Ordering, fmt, ops};
-
-pub struct TokenText(pub(crate) rowan::GreenToken);
-
-impl TokenText {
-    pub fn as_str(&self) -> &str {
-        self.0.text()
-    }
-}
-
-impl ops::Deref for TokenText {
-    type Target = str;
-
-    fn deref(&self) -> &str {
-        self.as_str()
-    }
-}
-impl AsRef<str> for TokenText {
-    fn as_ref(&self) -> &str {
-        self.as_str()
-    }
-}
-
-impl From<TokenText> for String {
-    fn from(token_text: TokenText) -> Self {
-        token_text.as_str().into()
-    }
-}
-
-impl PartialEq<&'_ str> for TokenText {
-    fn eq(&self, other: &&str) -> bool {
-        self.as_str() == *other
-    }
-}
-impl PartialEq<TokenText> for &'_ str {
-    fn eq(&self, other: &TokenText) -> bool {
-        other == self
-    }
-}
-impl PartialEq<String> for TokenText {
-    fn eq(&self, other: &String) -> bool {
-        self.as_str() == other.as_str()
-    }
-}
-impl PartialEq<TokenText> for String {
-    fn eq(&self, other: &TokenText) -> bool {
-        other == self
-    }
-}
-impl PartialEq for TokenText {
-    fn eq(&self, other: &TokenText) -> bool {
-        self.as_str() == other.as_str()
-    }
-}
-impl Eq for TokenText {}
-impl Ord for TokenText {
-    fn cmp(&self, other: &Self) -> Ordering {
-        self.as_str().cmp(other.as_str())
-    }
-}
-impl PartialOrd for TokenText {
-    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
-        Some(self.cmp(other))
-    }
-}
-impl fmt::Display for TokenText {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_str(), f)
-    }
-}
-impl fmt::Debug for TokenText {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.as_str(), f)
-    }
-}
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index b1beeb8838..36a86e78f0 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -178,15 +178,6 @@ $ cargo xtask install --server
 If your editor can't find the binary even though the binary is on your `$PATH`, the likely explanation is that it doesn't see the same `$PATH` as the shell, see https://github.com/rust-analyzer/rust-analyzer/issues/1811[this issue].
 On Unix, running the editor from a shell or changing the `.desktop` file to set the environment should help.
 
-==== `rustup`
-
-`rust-analyzer` is available in `rustup`, but only in the nightly toolchain:
-
-[source,bash]
----
-$ rustup +nightly component add rust-analyzer-preview
----
-
 ==== Arch Linux
 
 The `rust-analyzer` binary can be installed from the repos or AUR (Arch User Repository):


Test patch:
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 01935ec994..7eda518663 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -226,48 +226,11 @@ fn expr_macro_expanded_in_stmts() {
         "#,
         expect![[r#"
             !0..8 'leta=();': ()
-            !0..8 'leta=();': ()
-            !3..4 'a': ()
-            !5..7 '()': ()
             57..84 '{     ...); } }': ()
         "#]],
     );
 }
 
-#[test]
-fn recurisve_macro_expanded_in_stmts() {
-    check_infer(
-        r#"
-        macro_rules! ng {
-            ([$($tts:tt)*]) => {
-                $($tts)*;
-            };
-            ([$($tts:tt)*] $head:tt $($rest:tt)*) => {
-                ng! {
-                    [$($tts)* $head] $($rest)*
-                }
-            };
-        }
-        fn foo() {
-            ng!([] let a = 3);
-            let b = a;
-        }
-        "#,
-        expect![[r#"
-            !0..7 'leta=3;': {unknown}
-            !0..7 'leta=3;': {unknown}
-            !0..13 'ng!{[leta=3]}': {unknown}
-            !0..13 'ng!{[leta=]3}': {unknown}
-            !0..13 'ng!{[leta]=3}': {unknown}
-            !3..4 'a': i32
-            !5..6 '3': i32
-            196..237 '{     ...= a; }': ()
-            229..230 'b': i32
-            233..234 'a': i32
-        "#]],
-    );
-}
-
 #[test]
 fn recursive_inner_item_macro_rules() {
     check_infer(
@@ -283,8 +246,7 @@ fn recursive_inner_item_macro_rules() {
         "#,
         expect![[r#"
             !0..1 '1': i32
-            !0..26 'macro_...>{1};}': {unknown}
-            !0..26 'macro_...>{1};}': {unknown}
+            !0..7 'mac!($)': {unknown}
             107..143 '{     ...!(); }': ()
             129..130 'a': i32
         "#]],
diff --git a/crates/ide_db/src/call_info/tests.rs b/crates/ide_db/src/call_info/tests.rs
index 281a081a38..75ab3eb6ea 100644
--- a/crates/ide_db/src/call_info/tests.rs
+++ b/crates/ide_db/src/call_info/tests.rs
@@ -1,9 +1,8 @@
+use crate::RootDatabase;
 use base_db::{fixture::ChangeFixture, FilePosition};
 use expect_test::{expect, Expect};
 use test_utils::RangeOrOffset;
 
-use crate::RootDatabase;
-
 /// Creates analysis from a multi-file fixture, returns positions marked with $0.
 pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
     let change_fixture = ChangeFixture::parse(ra_fixture);
diff --git a/crates/ide_db/src/traits/tests.rs b/crates/ide_db/src/traits/tests.rs
index 2a5482024d..84bb255059 100644
--- a/crates/ide_db/src/traits/tests.rs
+++ b/crates/ide_db/src/traits/tests.rs
@@ -1,11 +1,10 @@
+use crate::RootDatabase;
 use base_db::{fixture::ChangeFixture, FilePosition};
 use expect_test::{expect, Expect};
 use hir::Semantics;
 use syntax::ast::{self, AstNode};
 use test_utils::RangeOrOffset;
 
-use crate::RootDatabase;
-
 /// Creates analysis from a multi-file fixture, returns positions marked with $0.
 pub(crate) fn position(ra_fixture: &str) -> (RootDatabase, FilePosition) {
     let change_fixture = ChangeFixture::parse(ra_fixture);