From 0343c4a815a0e82d5e55e76a01d21b0f7a00ff5b Mon Sep 17 00:00:00 2001
From: Aleksey Kladov <aleksey.kladov@gmail.com>
Date: Fri, 19 Jul 2019 11:24:41 +0300
Subject: migrate ra_assists to the new AST

---
 crates/ra_assists/src/add_derive.rs                |   2 +-
 crates/ra_assists/src/add_explicit_type.rs         |   2 +-
 crates/ra_assists/src/add_impl.rs                  |   6 +-
 crates/ra_assists/src/add_missing_impl_members.rs  |  46 ++++---
 crates/ra_assists/src/assist_ctx.rs                |  14 +-
 crates/ra_assists/src/ast_editor.rs                | 123 +++++++++---------
 crates/ra_assists/src/auto_import.rs               | 143 +++++++++++----------
 crates/ra_assists/src/change_visibility.rs         |   4 +-
 crates/ra_assists/src/fill_match_arms.rs           |   4 +-
 crates/ra_assists/src/flip_binexpr.rs              |   4 +-
 crates/ra_assists/src/flip_comma.rs                |   4 +-
 crates/ra_assists/src/inline_local_variable.rs     |  10 +-
 crates/ra_assists/src/introduce_variable.rs        |  24 ++--
 crates/ra_assists/src/move_guard.rs                |  10 +-
 crates/ra_assists/src/remove_dbg.rs                |   6 +-
 crates/ra_assists/src/replace_if_let_with_match.rs |  13 +-
 16 files changed, 212 insertions(+), 203 deletions(-)

(limited to 'crates/ra_assists')

diff --git a/crates/ra_assists/src/add_derive.rs b/crates/ra_assists/src/add_derive.rs
index bf7d55d6d..f19196f53 100644
--- a/crates/ra_assists/src/add_derive.rs
+++ b/crates/ra_assists/src/add_derive.rs
@@ -9,7 +9,7 @@ use crate::{Assist, AssistCtx, AssistId};
 
 pub(crate) fn add_derive(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let nominal = ctx.node_at_offset::<ast::NominalDef>()?;
-    let node_start = derive_insertion_offset(nominal)?;
+    let node_start = derive_insertion_offset(&nominal)?;
     ctx.add_action(AssistId("add_derive"), "add `#[derive]`", |edit| {
         let derive_attr = nominal
             .attrs()
diff --git a/crates/ra_assists/src/add_explicit_type.rs b/crates/ra_assists/src/add_explicit_type.rs
index bb47a32f0..a69cfc8e3 100644
--- a/crates/ra_assists/src/add_explicit_type.rs
+++ b/crates/ra_assists/src/add_explicit_type.rs
@@ -27,7 +27,7 @@ pub(crate) fn add_explicit_type(mut ctx: AssistCtx<impl HirDatabase>) -> Option<
     // Infer type
     let db = ctx.db;
     let analyzer = hir::SourceAnalyzer::new(db, ctx.frange.file_id, stmt.syntax(), None);
-    let ty = analyzer.type_of(db, expr)?;
+    let ty = analyzer.type_of(db, &expr)?;
     // Assist not applicable if the type is unknown
     if is_unknown(&ty) {
         return None;
diff --git a/crates/ra_assists/src/add_impl.rs b/crates/ra_assists/src/add_impl.rs
index b81922c1d..cebc19539 100644
--- a/crates/ra_assists/src/add_impl.rs
+++ b/crates/ra_assists/src/add_impl.rs
@@ -16,7 +16,7 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
         let start_offset = nominal.syntax().range().end();
         let mut buf = String::new();
         buf.push_str("\n\nimpl");
-        if let Some(type_params) = type_params {
+        if let Some(type_params) = &type_params {
             type_params.syntax().text().push_to(&mut buf);
         }
         buf.push_str(" ");
@@ -25,9 +25,9 @@ pub(crate) fn add_impl(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
             let lifetime_params = type_params
                 .lifetime_params()
                 .filter_map(|it| it.lifetime_token())
-                .map(|it| it.text());
+                .map(|it| it.text().clone());
             let type_params =
-                type_params.type_params().filter_map(|it| it.name()).map(|it| it.text());
+                type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone());
             join(lifetime_params.chain(type_params)).surround_with("<", ">").to_buf(&mut buf);
         }
         buf.push_str(" {\n");
diff --git a/crates/ra_assists/src/add_missing_impl_members.rs b/crates/ra_assists/src/add_missing_impl_members.rs
index 6ffdad0b1..b992a4dc8 100644
--- a/crates/ra_assists/src/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/add_missing_impl_members.rs
@@ -5,8 +5,8 @@ use crate::{
 
 use hir::{db::HirDatabase, HasSource};
 use ra_db::FilePosition;
-use ra_syntax::ast::{self, AstNode, ImplItem, ImplItemKind, NameOwner};
-use ra_syntax::{SmolStr, TreeArc};
+use ra_syntax::ast::{self, AstNode, ImplItemKind, NameOwner};
+use ra_syntax::SmolStr;
 
 #[derive(PartialEq)]
 enum AddMissingImplMembersMode {
@@ -46,16 +46,16 @@ fn add_missing_impl_members_inner(
         let position = FilePosition { file_id, offset: impl_node.syntax().range().start() };
         let analyzer = hir::SourceAnalyzer::new(ctx.db, position.file_id, impl_node.syntax(), None);
 
-        resolve_target_trait_def(ctx.db, &analyzer, impl_node)?
+        resolve_target_trait_def(ctx.db, &analyzer, &impl_node)?
     };
 
-    let def_name = |kind| -> Option<&SmolStr> {
+    let def_name = |kind| -> Option<SmolStr> {
         match kind {
-            ImplItemKind::FnDef(def) => def.name(),
-            ImplItemKind::TypeAliasDef(def) => def.name(),
-            ImplItemKind::ConstDef(def) => def.name(),
+            ast::ImplItemKind::FnDef(def) => def.name(),
+            ast::ImplItemKind::TypeAliasDef(def) => def.name(),
+            ast::ImplItemKind::ConstDef(def) => def.name(),
         }
-        .map(ast::Name::text)
+        .map(|it| it.text().clone())
     };
 
     let trait_items = trait_def.item_list()?.impl_items();
@@ -78,18 +78,13 @@ fn add_missing_impl_members_inner(
 
     ctx.add_action(AssistId(assist_id), label, |edit| {
         let n_existing_items = impl_item_list.impl_items().count();
-        let items: Vec<_> = missing_items
-            .into_iter()
-            .map(|it| match it.kind() {
-                ImplItemKind::FnDef(def) => {
-                    strip_docstring(ImplItem::cast(add_body(def).syntax()).unwrap())
-                }
-                _ => strip_docstring(it),
-            })
-            .collect();
+        let items = missing_items.into_iter().map(|it| match it.kind() {
+            ImplItemKind::FnDef(def) => strip_docstring(add_body(def).into()),
+            _ => strip_docstring(it),
+        });
         let mut ast_editor = AstEditor::new(impl_item_list);
 
-        ast_editor.append_items(items.iter().map(|it| &**it));
+        ast_editor.append_items(items);
 
         let first_new_item = ast_editor.ast().impl_items().nth(n_existing_items).unwrap();
         let cursor_position = first_new_item.syntax().range().start();
@@ -101,14 +96,14 @@ fn add_missing_impl_members_inner(
     ctx.build()
 }
 
-fn strip_docstring(item: &ast::ImplItem) -> TreeArc<ast::ImplItem> {
+fn strip_docstring(item: ast::ImplItem) -> ast::ImplItem {
     let mut ast_editor = AstEditor::new(item);
     ast_editor.strip_attrs_and_docs();
     ast_editor.ast().to_owned()
 }
 
-fn add_body(fn_def: &ast::FnDef) -> TreeArc<ast::FnDef> {
-    let mut ast_editor = AstEditor::new(fn_def);
+fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
+    let mut ast_editor = AstEditor::new(fn_def.clone());
     if fn_def.body().is_none() {
         ast_editor.set_body(&AstBuilder::<ast::Block>::single_expr(
             &AstBuilder::<ast::Expr>::unimplemented(),
@@ -123,9 +118,12 @@ fn resolve_target_trait_def(
     db: &impl HirDatabase,
     analyzer: &hir::SourceAnalyzer,
     impl_block: &ast::ImplBlock,
-) -> Option<TreeArc<ast::TraitDef>> {
-    let ast_path =
-        impl_block.target_trait().map(AstNode::syntax).and_then(ast::PathType::cast)?.path()?;
+) -> Option<ast::TraitDef> {
+    let ast_path = impl_block
+        .target_trait()
+        .map(|it| it.syntax().clone())
+        .and_then(ast::PathType::cast)?
+        .path()?;
 
     match analyzer.resolve_path(db, &ast_path) {
         Some(hir::PathResolution::Def(hir::ModuleDef::Trait(def))) => Some(def.source(db).ast),
diff --git a/crates/ra_assists/src/assist_ctx.rs b/crates/ra_assists/src/assist_ctx.rs
index 34b207154..e52085f85 100644
--- a/crates/ra_assists/src/assist_ctx.rs
+++ b/crates/ra_assists/src/assist_ctx.rs
@@ -49,7 +49,7 @@ pub(crate) enum Assist {
 pub(crate) struct AssistCtx<'a, DB> {
     pub(crate) db: &'a DB,
     pub(crate) frange: FileRange,
-    source_file: &'a SourceFile,
+    source_file: SourceFile,
     should_compute_edit: bool,
     assist: Assist,
 }
@@ -59,7 +59,7 @@ impl<'a, DB> Clone for AssistCtx<'a, DB> {
         AssistCtx {
             db: self.db,
             frange: self.frange,
-            source_file: self.source_file,
+            source_file: self.source_file.clone(),
             should_compute_edit: self.should_compute_edit,
             assist: self.assist.clone(),
         }
@@ -104,18 +104,18 @@ impl<'a, DB: HirDatabase> AssistCtx<'a, DB> {
         Some(self.assist)
     }
 
-    pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken<'a>> {
+    pub(crate) fn token_at_offset(&self) -> TokenAtOffset<SyntaxToken> {
         find_token_at_offset(self.source_file.syntax(), self.frange.range.start())
     }
 
-    pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<&'a N> {
+    pub(crate) fn node_at_offset<N: AstNode>(&self) -> Option<N> {
         find_node_at_offset(self.source_file.syntax(), self.frange.range.start())
     }
-    pub(crate) fn covering_element(&self) -> SyntaxElement<'a> {
+    pub(crate) fn covering_element(&self) -> SyntaxElement {
         find_covering_element(self.source_file.syntax(), self.frange.range)
     }
 
-    pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement<'a> {
+    pub(crate) fn covering_node_for_range(&self, range: TextRange) -> SyntaxElement {
         find_covering_element(self.source_file.syntax(), range)
     }
 }
@@ -139,7 +139,7 @@ impl AssistBuilder {
     ) {
         let mut replace_with = replace_with.into();
         if let Some(indent) = leading_indent(node) {
-            replace_with = reindent(&replace_with, indent)
+            replace_with = reindent(&replace_with, &indent)
         }
         self.replace(node.range(), replace_with)
     }
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index 7b743c9f0..5fbcadfee 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -4,18 +4,18 @@ use arrayvec::ArrayVec;
 use hir::Name;
 use ra_fmt::leading_indent;
 use ra_syntax::{
-    ast, AstNode, Direction, InsertPosition, SourceFile, SyntaxElement, SyntaxKind::*, TreeArc, T,
+    ast, AstNode, Direction, InsertPosition, SourceFile, SyntaxElement, SyntaxKind::*, T,
 };
 use ra_text_edit::TextEditBuilder;
 
 pub struct AstEditor<N: AstNode> {
-    original_ast: TreeArc<N>,
-    ast: TreeArc<N>,
+    original_ast: N,
+    ast: N,
 }
 
 impl<N: AstNode> AstEditor<N> {
-    pub fn new(node: &N) -> AstEditor<N> {
-        AstEditor { original_ast: node.to_owned(), ast: node.to_owned() }
+    pub fn new(node: N) -> AstEditor<N> {
+        AstEditor { original_ast: node.clone(), ast: node }
     }
 
     pub fn into_text_edit(self, builder: &mut TextEditBuilder) {
@@ -26,27 +26,27 @@ impl<N: AstNode> AstEditor<N> {
     }
 
     pub fn ast(&self) -> &N {
-        &*self.ast
+        &self.ast
     }
 
     #[must_use]
-    fn insert_children<'a>(
+    fn insert_children(
         &self,
-        position: InsertPosition<SyntaxElement<'_>>,
-        to_insert: impl Iterator<Item = SyntaxElement<'a>>,
-    ) -> TreeArc<N> {
+        position: InsertPosition<SyntaxElement>,
+        to_insert: impl Iterator<Item = SyntaxElement>,
+    ) -> N {
         let new_syntax = self.ast().syntax().insert_children(position, to_insert);
-        N::cast(&new_syntax).unwrap().to_owned()
+        N::cast(new_syntax).unwrap()
     }
 
     #[must_use]
-    fn replace_children<'a>(
+    fn replace_children(
         &self,
-        to_delete: RangeInclusive<SyntaxElement<'_>>,
-        to_insert: impl Iterator<Item = SyntaxElement<'a>>,
-    ) -> TreeArc<N> {
+        to_delete: RangeInclusive<SyntaxElement>,
+        to_insert: impl Iterator<Item = SyntaxElement>,
+    ) -> N {
         let new_syntax = self.ast().syntax().replace_children(to_delete, to_insert);
-        N::cast(&new_syntax).unwrap().to_owned()
+        N::cast(new_syntax).unwrap()
     }
 
     fn do_make_multiline(&mut self) {
@@ -66,16 +66,18 @@ impl<N: AstNode> AstEditor<N> {
                 if ws.text().contains('\n') {
                     return;
                 }
-                Some(ws)
+                Some(ws.clone())
             }
         };
 
-        let indent = leading_indent(self.ast().syntax()).unwrap_or("");
+        let indent = leading_indent(self.ast().syntax()).unwrap_or("".into());
         let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
         let to_insert = iter::once(ws.ws().into());
         self.ast = match existing_ws {
             None => self.insert_children(InsertPosition::After(l_curly), to_insert),
-            Some(ws) => self.replace_children(RangeInclusive::new(ws.into(), ws.into()), to_insert),
+            Some(ws) => {
+                self.replace_children(RangeInclusive::new(ws.clone().into(), ws.into()), to_insert)
+            }
         };
     }
 }
@@ -95,7 +97,7 @@ impl AstEditor<ast::NamedFieldList> {
         let space = if is_multiline {
             ws = tokens::WsBuilder::new(&format!(
                 "\n{}    ",
-                leading_indent(self.ast().syntax()).unwrap_or("")
+                leading_indent(self.ast().syntax()).unwrap_or("".into())
             ));
             ws.ws()
         } else {
@@ -104,7 +106,7 @@ impl AstEditor<ast::NamedFieldList> {
 
         let mut to_insert: ArrayVec<[SyntaxElement; 4]> = ArrayVec::new();
         to_insert.push(space.into());
-        to_insert.push(field.syntax().into());
+        to_insert.push(field.syntax().clone().into());
         to_insert.push(tokens::comma().into());
 
         macro_rules! after_l_curly {
@@ -127,7 +129,7 @@ impl AstEditor<ast::NamedFieldList> {
                     InsertPosition::After(comma)
                 } else {
                     to_insert.insert(0, tokens::comma().into());
-                    InsertPosition::After($anchor.syntax().into())
+                    InsertPosition::After($anchor.syntax().clone().into())
                 }
             };
         };
@@ -144,7 +146,9 @@ impl AstEditor<ast::NamedFieldList> {
                     None => after_l_curly!(),
                 }
             }
-            InsertPosition::Before(anchor) => InsertPosition::Before(anchor.syntax().into()),
+            InsertPosition::Before(anchor) => {
+                InsertPosition::Before(anchor.syntax().clone().into())
+            }
             InsertPosition::After(anchor) => after_field!(anchor),
         };
 
@@ -157,7 +161,7 @@ impl AstEditor<ast::NamedFieldList> {
 }
 
 impl AstEditor<ast::ItemList> {
-    pub fn append_items<'a>(&mut self, items: impl Iterator<Item = &'a ast::ImplItem>) {
+    pub fn append_items(&mut self, items: impl Iterator<Item = ast::ImplItem>) {
         let n_existing_items = self.ast().impl_items().count();
         if n_existing_items == 0 {
             self.do_make_multiline();
@@ -165,22 +169,23 @@ impl AstEditor<ast::ItemList> {
         items.for_each(|it| self.append_item(it));
     }
 
-    pub fn append_item(&mut self, item: &ast::ImplItem) {
+    pub fn append_item(&mut self, item: ast::ImplItem) {
         let (indent, position) = match self.ast().impl_items().last() {
             Some(it) => (
-                leading_indent(it.syntax()).unwrap_or("").to_string(),
-                InsertPosition::After(it.syntax().into()),
+                leading_indent(it.syntax()).unwrap_or_default().to_string(),
+                InsertPosition::After(it.syntax().clone().into()),
             ),
             None => match self.l_curly() {
                 Some(it) => (
-                    "    ".to_string() + leading_indent(self.ast().syntax()).unwrap_or(""),
+                    "    ".to_string() + &leading_indent(self.ast().syntax()).unwrap_or_default(),
                     InsertPosition::After(it),
                 ),
                 None => return,
             },
         };
         let ws = tokens::WsBuilder::new(&format!("\n{}", indent));
-        let to_insert: ArrayVec<[SyntaxElement; 2]> = [ws.ws().into(), item.syntax().into()].into();
+        let to_insert: ArrayVec<[SyntaxElement; 2]> =
+            [ws.ws().into(), item.syntax().clone().into()].into();
         self.ast = self.insert_children(position, to_insert.into_iter());
     }
 
@@ -197,9 +202,9 @@ impl AstEditor<ast::ImplItem> {
             .children_with_tokens()
             .find(|it| it.kind() == ATTR || it.kind() == COMMENT)
         {
-            let end = match start.next_sibling_or_token() {
-                Some(el) if el.kind() == WHITESPACE => el,
-                Some(_) | None => start,
+            let end = match &start.next_sibling_or_token() {
+                Some(el) if el.kind() == WHITESPACE => el.clone(),
+                Some(_) | None => start.clone(),
             };
             self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty());
         }
@@ -210,18 +215,18 @@ impl AstEditor<ast::FnDef> {
     pub fn set_body(&mut self, body: &ast::Block) {
         let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new();
         let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.ast().body() {
-            old_body.syntax().into()
+            old_body.syntax().clone().into()
         } else if let Some(semi) = self.ast().semicolon_token() {
             to_insert.push(tokens::single_space().into());
             semi.into()
         } else {
             to_insert.push(tokens::single_space().into());
-            to_insert.push(body.syntax().into());
+            to_insert.push(body.syntax().clone().into());
             self.ast = self.insert_children(InsertPosition::Last, to_insert.into_iter());
             return;
         };
-        to_insert.push(body.syntax().into());
-        let replace_range = RangeInclusive::new(old_body_or_semi, old_body_or_semi);
+        to_insert.push(body.syntax().clone().into());
+        let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi);
         self.ast = self.replace_children(replace_range, to_insert.into_iter())
     }
 }
@@ -231,15 +236,15 @@ pub struct AstBuilder<N: AstNode> {
 }
 
 impl AstBuilder<ast::NamedField> {
-    pub fn from_name(name: &Name) -> TreeArc<ast::NamedField> {
+    pub fn from_name(name: &Name) -> ast::NamedField {
         ast_node_from_file_text(&format!("fn f() {{ S {{ {}: (), }} }}", name))
     }
 
-    fn from_text(text: &str) -> TreeArc<ast::NamedField> {
+    fn from_text(text: &str) -> ast::NamedField {
         ast_node_from_file_text(&format!("fn f() {{ S {{ {}, }} }}", text))
     }
 
-    pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> TreeArc<ast::NamedField> {
+    pub fn from_pieces(name: &ast::NameRef, expr: Option<&ast::Expr>) -> ast::NamedField {
         match expr {
             Some(expr) => Self::from_text(&format!("{}: {}", name.syntax(), expr.syntax())),
             None => Self::from_text(&name.syntax().to_string()),
@@ -248,36 +253,36 @@ impl AstBuilder<ast::NamedField> {
 }
 
 impl AstBuilder<ast::Block> {
-    fn from_text(text: &str) -> TreeArc<ast::Block> {
+    fn from_text(text: &str) -> ast::Block {
         ast_node_from_file_text(&format!("fn f() {}", text))
     }
 
-    pub fn single_expr(e: &ast::Expr) -> TreeArc<ast::Block> {
+    pub fn single_expr(e: &ast::Expr) -> ast::Block {
         Self::from_text(&format!("{{ {} }}", e.syntax()))
     }
 }
 
 impl AstBuilder<ast::Expr> {
-    fn from_text(text: &str) -> TreeArc<ast::Expr> {
+    fn from_text(text: &str) -> ast::Expr {
         ast_node_from_file_text(&format!("fn f() {{ {}; }}", text))
     }
 
-    pub fn unit() -> TreeArc<ast::Expr> {
+    pub fn unit() -> ast::Expr {
         Self::from_text("()")
     }
 
-    pub fn unimplemented() -> TreeArc<ast::Expr> {
+    pub fn unimplemented() -> ast::Expr {
         Self::from_text("unimplemented!()")
     }
 }
 
 impl AstBuilder<ast::NameRef> {
-    pub fn new(text: &str) -> TreeArc<ast::NameRef> {
+    pub fn new(text: &str) -> ast::NameRef {
         ast_node_from_file_text(&format!("fn f() {{ {}; }}", text))
     }
 }
 
-fn ast_node_from_file_text<N: AstNode>(text: &str) -> TreeArc<N> {
+fn ast_node_from_file_text<N: AstNode>(text: &str) -> N {
     let parse = SourceFile::parse(text);
     let res = parse.tree().syntax().descendants().find_map(N::cast).unwrap().to_owned();
     res
@@ -285,47 +290,49 @@ fn ast_node_from_file_text<N: AstNode>(text: &str) -> TreeArc<N> {
 
 mod tokens {
     use once_cell::sync::Lazy;
-    use ra_syntax::{AstNode, SourceFile, SyntaxKind::*, SyntaxToken, TreeArc, T};
+    use ra_syntax::{AstNode, Parse, SourceFile, SyntaxKind::*, SyntaxToken, T};
 
-    static SOURCE_FILE: Lazy<TreeArc<SourceFile>> =
-        Lazy::new(|| SourceFile::parse(",\n; ;").tree().to_owned());
+    static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| SourceFile::parse(",\n; ;"));
 
-    pub(crate) fn comma() -> SyntaxToken<'static> {
+    pub(crate) fn comma() -> SyntaxToken {
         SOURCE_FILE
+            .tree()
             .syntax()
             .descendants_with_tokens()
-            .filter_map(|it| it.as_token())
+            .filter_map(|it| it.as_token().cloned())
             .find(|it| it.kind() == T![,])
             .unwrap()
     }
 
-    pub(crate) fn single_space() -> SyntaxToken<'static> {
+    pub(crate) fn single_space() -> SyntaxToken {
         SOURCE_FILE
+            .tree()
             .syntax()
             .descendants_with_tokens()
-            .filter_map(|it| it.as_token())
+            .filter_map(|it| it.as_token().cloned())
             .find(|it| it.kind() == WHITESPACE && it.text().as_str() == " ")
             .unwrap()
     }
 
     #[allow(unused)]
-    pub(crate) fn single_newline() -> SyntaxToken<'static> {
+    pub(crate) fn single_newline() -> SyntaxToken {
         SOURCE_FILE
+            .tree()
             .syntax()
             .descendants_with_tokens()
-            .filter_map(|it| it.as_token())
+            .filter_map(|it| it.as_token().cloned())
             .find(|it| it.kind() == WHITESPACE && it.text().as_str() == "\n")
             .unwrap()
     }
 
-    pub(crate) struct WsBuilder(TreeArc<SourceFile>);
+    pub(crate) struct WsBuilder(SourceFile);
 
     impl WsBuilder {
         pub(crate) fn new(text: &str) -> WsBuilder {
             WsBuilder(SourceFile::parse(text).ok().unwrap())
         }
-        pub(crate) fn ws(&self) -> SyntaxToken<'_> {
-            self.0.syntax().first_child_or_token().unwrap().as_token().unwrap()
+        pub(crate) fn ws(&self) -> SyntaxToken {
+            self.0.syntax().first_child_or_token().unwrap().as_token().cloned().unwrap()
         }
     }
 
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index f8f37e852..0eb4bdb62 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -12,25 +12,25 @@ use ra_syntax::{
     SyntaxNode, TextRange, T,
 };
 
-fn collect_path_segments_raw<'a>(
-    segments: &mut Vec<&'a ast::PathSegment>,
-    mut path: &'a ast::Path,
+fn collect_path_segments_raw(
+    segments: &mut Vec<ast::PathSegment>,
+    mut path: ast::Path,
 ) -> Option<usize> {
     let oldlen = segments.len();
     loop {
         let mut children = path.syntax().children_with_tokens();
         let (first, second, third) = (
-            children.next().map(|n| (n, n.kind())),
-            children.next().map(|n| (n, n.kind())),
-            children.next().map(|n| (n, n.kind())),
+            children.next().map(|n| (n.clone(), n.kind())),
+            children.next().map(|n| (n.clone(), n.kind())),
+            children.next().map(|n| (n.clone(), n.kind())),
         );
         match (first, second, third) {
             (Some((subpath, PATH)), Some((_, T![::])), Some((segment, PATH_SEGMENT))) => {
-                path = ast::Path::cast(subpath.as_node()?)?;
-                segments.push(ast::PathSegment::cast(segment.as_node()?)?);
+                path = ast::Path::cast(subpath.as_node()?.clone())?;
+                segments.push(ast::PathSegment::cast(segment.as_node()?.clone())?);
             }
             (Some((segment, PATH_SEGMENT)), _, _) => {
-                segments.push(ast::PathSegment::cast(segment.as_node()?)?);
+                segments.push(ast::PathSegment::cast(segment.as_node()?.clone())?);
                 break;
             }
             (_, _, _) => return None,
@@ -60,7 +60,7 @@ fn fmt_segments_raw(segments: &[SmolStr], buf: &mut String) {
 }
 
 // Returns the numeber of common segments.
-fn compare_path_segments(left: &[SmolStr], right: &[&ast::PathSegment]) -> usize {
+fn compare_path_segments(left: &[SmolStr], right: &[ast::PathSegment]) -> usize {
     left.iter().zip(right).filter(|(l, r)| compare_path_segment(l, r)).count()
 }
 
@@ -81,12 +81,12 @@ fn compare_path_segment_with_name(a: &SmolStr, b: &ast::Name) -> bool {
     a == b.text()
 }
 
-#[derive(Copy, Clone)]
-enum ImportAction<'a> {
+#[derive(Clone)]
+enum ImportAction {
     Nothing,
     // Add a brand new use statement.
     AddNewUse {
-        anchor: Option<&'a SyntaxNode>, // anchor node
+        anchor: Option<SyntaxNode>, // anchor node
         add_after_anchor: bool,
     },
 
@@ -94,9 +94,9 @@ enum ImportAction<'a> {
     AddNestedImport {
         // how may segments matched with the target path
         common_segments: usize,
-        path_to_split: &'a ast::Path,
+        path_to_split: ast::Path,
         // the first segment of path_to_split we want to add into the new nested list
-        first_segment_to_split: Option<&'a ast::PathSegment>,
+        first_segment_to_split: Option<ast::PathSegment>,
         // Wether to add 'self' in addition to the target path
         add_self: bool,
     },
@@ -104,20 +104,20 @@ enum ImportAction<'a> {
     AddInTreeList {
         common_segments: usize,
         // The UseTreeList where to add the target path
-        tree_list: &'a ast::UseTreeList,
+        tree_list: ast::UseTreeList,
         add_self: bool,
     },
 }
 
-impl<'a> ImportAction<'a> {
-    fn add_new_use(anchor: Option<&'a SyntaxNode>, add_after_anchor: bool) -> Self {
+impl ImportAction {
+    fn add_new_use(anchor: Option<SyntaxNode>, add_after_anchor: bool) -> Self {
         ImportAction::AddNewUse { anchor, add_after_anchor }
     }
 
     fn add_nested_import(
         common_segments: usize,
-        path_to_split: &'a ast::Path,
-        first_segment_to_split: Option<&'a ast::PathSegment>,
+        path_to_split: ast::Path,
+        first_segment_to_split: Option<ast::PathSegment>,
         add_self: bool,
     ) -> Self {
         ImportAction::AddNestedImport {
@@ -130,14 +130,14 @@ impl<'a> ImportAction<'a> {
 
     fn add_in_tree_list(
         common_segments: usize,
-        tree_list: &'a ast::UseTreeList,
+        tree_list: ast::UseTreeList,
         add_self: bool,
     ) -> Self {
         ImportAction::AddInTreeList { common_segments, tree_list, add_self }
     }
 
-    fn better<'b>(left: &'b ImportAction<'a>, right: &'b ImportAction<'a>) -> &'b ImportAction<'a> {
-        if left.is_better(right) {
+    fn better(left: ImportAction, right: ImportAction) -> ImportAction {
+        if left.is_better(&right) {
             left
         } else {
             right
@@ -166,12 +166,12 @@ impl<'a> ImportAction<'a> {
 
 // Find out the best ImportAction to import target path against current_use_tree.
 // If current_use_tree has a nested import the function gets called recursively on every UseTree inside a UseTreeList.
-fn walk_use_tree_for_best_action<'a>(
-    current_path_segments: &mut Vec<&'a ast::PathSegment>, // buffer containing path segments
-    current_parent_use_tree_list: Option<&'a ast::UseTreeList>, // will be Some value if we are in a nested import
-    current_use_tree: &'a ast::UseTree, // the use tree we are currently examinating
-    target: &[SmolStr],                 // the path we want to import
-) -> ImportAction<'a> {
+fn walk_use_tree_for_best_action(
+    current_path_segments: &mut Vec<ast::PathSegment>, // buffer containing path segments
+    current_parent_use_tree_list: Option<ast::UseTreeList>, // will be Some value if we are in a nested import
+    current_use_tree: ast::UseTree, // the use tree we are currently examinating
+    target: &[SmolStr],             // the path we want to import
+) -> ImportAction {
     // We save the number of segments in the buffer so we can restore the correct segments
     // before returning. Recursive call will add segments so we need to delete them.
     let prev_len = current_path_segments.len();
@@ -188,32 +188,36 @@ fn walk_use_tree_for_best_action<'a>(
                     .syntax()
                     .ancestors()
                     .find_map(ast::UseItem::cast)
-                    .map(AstNode::syntax),
+                    .map(|it| it.syntax().clone()),
                 true,
             );
         }
     };
 
     // This can happen only if current_use_tree is a direct child of a UseItem
-    if let Some(name) = alias.and_then(ast::NameOwner::name) {
-        if compare_path_segment_with_name(&target[0], name) {
+    if let Some(name) = alias.and_then(|it| it.name()) {
+        if compare_path_segment_with_name(&target[0], &name) {
             return ImportAction::Nothing;
         }
     }
 
-    collect_path_segments_raw(current_path_segments, path);
+    collect_path_segments_raw(current_path_segments, path.clone());
 
     // We compare only the new segments added in the line just above.
     // The first prev_len segments were already compared in 'parent' recursive calls.
     let left = target.split_at(prev_len).1;
     let right = current_path_segments.split_at(prev_len).1;
-    let common = compare_path_segments(left, right);
+    let common = compare_path_segments(left, &right);
     let mut action = match common {
         0 => ImportAction::add_new_use(
             // e.g: target is std::fmt and we can have
             // use foo::bar
             // We add a brand new use statement
-            current_use_tree.syntax().ancestors().find_map(ast::UseItem::cast).map(AstNode::syntax),
+            current_use_tree
+                .syntax()
+                .ancestors()
+                .find_map(ast::UseItem::cast)
+                .map(|it| it.syntax().clone()),
             true,
         ),
         common if common == left.len() && left.len() == right.len() => {
@@ -223,9 +227,9 @@ fn walk_use_tree_for_best_action<'a>(
             if let Some(list) = tree_list {
                 // In case 2 we need to add self to the nested list
                 // unless it's already there
-                let has_self = list.use_trees().map(ast::UseTree::path).any(|p| {
-                    p.and_then(ast::Path::segment)
-                        .and_then(ast::PathSegment::kind)
+                let has_self = list.use_trees().map(|it| it.path()).any(|p| {
+                    p.and_then(|it| it.segment())
+                        .and_then(|it| it.kind())
                         .filter(|k| *k == ast::PathSegmentKind::SelfKw)
                         .is_some()
                 });
@@ -248,7 +252,7 @@ fn walk_use_tree_for_best_action<'a>(
             ImportAction::add_nested_import(
                 prev_len + common,
                 path,
-                Some(segments_to_split[0]),
+                Some(segments_to_split[0].clone()),
                 false,
             )
         }
@@ -263,14 +267,18 @@ fn walk_use_tree_for_best_action<'a>(
                     .syntax()
                     .ancestors()
                     .find_map(ast::UseItem::cast)
-                    .map(AstNode::syntax),
+                    .map(|it| it.syntax().clone()),
                 true,
             );
             if let Some(list) = tree_list {
                 // Case 2, check recursively if the path is already imported in the nested list
                 for u in list.use_trees() {
-                    let child_action =
-                        walk_use_tree_for_best_action(current_path_segments, Some(list), u, target);
+                    let child_action = walk_use_tree_for_best_action(
+                        current_path_segments,
+                        Some(list.clone()),
+                        u,
+                        target,
+                    );
                     if child_action.is_better(&better_action) {
                         better_action = child_action;
                         if let ImportAction::Nothing = better_action {
@@ -291,7 +299,7 @@ fn walk_use_tree_for_best_action<'a>(
             ImportAction::add_nested_import(
                 prev_len + common,
                 path,
-                Some(segments_to_split[0]),
+                Some(segments_to_split[0].clone()),
                 true,
             )
         }
@@ -302,7 +310,7 @@ fn walk_use_tree_for_best_action<'a>(
             ImportAction::add_nested_import(
                 prev_len + common,
                 path,
-                Some(segments_to_split[0]),
+                Some(segments_to_split[0].clone()),
                 false,
             )
         }
@@ -311,7 +319,7 @@ fn walk_use_tree_for_best_action<'a>(
 
     // If we are inside a UseTreeList adding a use statement become adding to the existing
     // tree list.
-    action = match (current_parent_use_tree_list, action) {
+    action = match (current_parent_use_tree_list, action.clone()) {
         (Some(use_tree_list), ImportAction::AddNewUse { .. }) => {
             ImportAction::add_in_tree_list(prev_len, use_tree_list, false)
         }
@@ -323,19 +331,20 @@ fn walk_use_tree_for_best_action<'a>(
     action
 }
 
-fn best_action_for_target<'b, 'a: 'b>(
-    container: &'a SyntaxNode,
-    anchor: &'a SyntaxNode,
-    target: &'b [SmolStr],
-) -> ImportAction<'a> {
+fn best_action_for_target(
+    container: SyntaxNode,
+    anchor: SyntaxNode,
+    target: &[SmolStr],
+) -> ImportAction {
     let mut storage = Vec::with_capacity(16); // this should be the only allocation
     let best_action = container
         .children()
         .filter_map(ast::UseItem::cast)
-        .filter_map(ast::UseItem::use_tree)
+        .filter_map(|it| it.use_tree())
         .map(|u| walk_use_tree_for_best_action(&mut storage, None, u, target))
-        .fold(None, |best, a| {
-            best.and_then(|best| Some(*ImportAction::better(&best, &a))).or_else(|| Some(a))
+        .fold(None, |best, a| match best {
+            Some(best) => Some(ImportAction::better(best, a)),
+            None => Some(a),
         });
 
     match best_action {
@@ -386,7 +395,7 @@ fn make_assist(action: &ImportAction, target: &[SmolStr], edit: &mut TextEditBui
 }
 
 fn make_assist_add_new_use(
-    anchor: &Option<&SyntaxNode>,
+    anchor: &Option<SyntaxNode>,
     after: bool,
     target: &[SmolStr],
     edit: &mut TextEditBuilder,
@@ -396,7 +405,7 @@ fn make_assist_add_new_use(
         let mut buf = String::new();
         if after {
             buf.push_str("\n");
-            if let Some(spaces) = indent {
+            if let Some(spaces) = &indent {
                 buf.push_str(spaces);
             }
         }
@@ -405,8 +414,8 @@ fn make_assist_add_new_use(
         buf.push_str(";");
         if !after {
             buf.push_str("\n\n");
-            if let Some(spaces) = indent {
-                buf.push_str(spaces);
+            if let Some(spaces) = &indent {
+                buf.push_str(&spaces);
             }
         }
         let position = if after { anchor.range().end() } else { anchor.range().start() };
@@ -444,7 +453,7 @@ fn make_assist_add_in_tree_list(
 
 fn make_assist_add_nested_import(
     path: &ast::Path,
-    first_segment_to_split: &Option<&ast::PathSegment>,
+    first_segment_to_split: &Option<ast::PathSegment>,
     target: &[SmolStr],
     add_self: bool,
     edit: &mut TextEditBuilder,
@@ -482,7 +491,7 @@ fn apply_auto_import(
     target: &[SmolStr],
     edit: &mut TextEditBuilder,
 ) {
-    let action = best_action_for_target(container, path.syntax(), target);
+    let action = best_action_for_target(container.clone(), path.syntax().clone(), target);
     make_assist(&action, target, edit);
     if let Some(last) = path.segment() {
         // Here we are assuming the assist will provide a  correct use statement
@@ -522,26 +531,26 @@ pub fn auto_import_text_edit(
     edit: &mut TextEditBuilder,
 ) {
     let container = position.ancestors().find_map(|n| {
-        if let Some(module) = ast::Module::cast(n) {
-            return module.item_list().map(ast::AstNode::syntax);
+        if let Some(module) = ast::Module::cast(n.clone()) {
+            return module.item_list().map(|it| it.syntax().clone());
         }
-        ast::SourceFile::cast(n).map(ast::AstNode::syntax)
+        ast::SourceFile::cast(n).map(|it| it.syntax().clone())
     });
 
     if let Some(container) = container {
-        let action = best_action_for_target(container, anchor, target);
+        let action = best_action_for_target(container, anchor.clone(), target);
         make_assist(&action, target, edit);
     }
 }
 
 pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let path: &ast::Path = ctx.node_at_offset()?;
+    let path: ast::Path = ctx.node_at_offset()?;
     // We don't want to mess with use statements
     if path.syntax().ancestors().find_map(ast::UseItem::cast).is_some() {
         return None;
     }
 
-    let hir_path = hir::Path::from_ast(path)?;
+    let hir_path = hir::Path::from_ast(path.clone())?;
     let segments = collect_hir_path_segments(&hir_path);
     if segments.len() < 2 {
         return None;
@@ -554,7 +563,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
                 format!("import {} in mod {}", fmt_segments(&segments), name.text()),
                 |edit| {
                     let mut text_edit = TextEditBuilder::default();
-                    apply_auto_import(item_list.syntax(), path, &segments, &mut text_edit);
+                    apply_auto_import(item_list.syntax(), &path, &segments, &mut text_edit);
                     edit.set_edit_builder(text_edit);
                 },
             );
@@ -566,7 +575,7 @@ pub(crate) fn auto_import(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist
             format!("import {} in the current file", fmt_segments(&segments)),
             |edit| {
                 let mut text_edit = TextEditBuilder::default();
-                apply_auto_import(current_file.syntax(), path, &segments, &mut text_edit);
+                apply_auto_import(current_file.syntax(), &path, &segments, &mut text_edit);
                 edit.set_edit_builder(text_edit);
             },
         );
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index 6cabba3e3..ab10d2aa4 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -35,7 +35,7 @@ fn add_vis(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
         if parent.children().any(|child| child.kind() == VISIBILITY) {
             return None;
         }
-        (vis_offset(parent), keyword.range())
+        (vis_offset(&parent), keyword.range())
     } else {
         let ident = ctx.token_at_offset().find(|leaf| leaf.kind() == IDENT)?;
         let field = ident.parent().ancestors().find_map(ast::NamedFieldDef::cast)?;
@@ -65,7 +65,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
         .unwrap_or_else(|| node.range().start())
 }
 
-fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: &ast::Visibility) -> Option<Assist> {
+fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: ast::Visibility) -> Option<Assist> {
     if vis.syntax().text() == "pub" {
         ctx.add_action(AssistId("change_visibility"), "change to pub(crate)", |edit| {
             edit.target(vis.syntax().range());
diff --git a/crates/ra_assists/src/fill_match_arms.rs b/crates/ra_assists/src/fill_match_arms.rs
index deef166b5..b96806ac6 100644
--- a/crates/ra_assists/src/fill_match_arms.rs
+++ b/crates/ra_assists/src/fill_match_arms.rs
@@ -27,7 +27,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
         let mut arm_iter = arm_list.arms();
         let first = arm_iter.next();
 
-        match first {
+        match &first {
             // If there arm list is empty or there is only one trivial arm, then proceed.
             Some(arm) if is_trivial_arm(arm) => {
                 if arm_iter.next() != None {
@@ -44,7 +44,7 @@ pub(crate) fn fill_match_arms(mut ctx: AssistCtx<impl HirDatabase>) -> Option<As
 
     let expr = match_expr.expr()?;
     let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, expr.syntax(), None);
-    let match_expr_ty = analyzer.type_of(ctx.db, expr)?;
+    let match_expr_ty = analyzer.type_of(ctx.db, &expr)?;
     let enum_def = analyzer.autoderef(ctx.db, match_expr_ty).find_map(|ty| match ty.as_adt() {
         Some((AdtDef::Enum(e), _)) => Some(e),
         _ => None,
diff --git a/crates/ra_assists/src/flip_binexpr.rs b/crates/ra_assists/src/flip_binexpr.rs
index 5e41f9346..2e591ad3b 100644
--- a/crates/ra_assists/src/flip_binexpr.rs
+++ b/crates/ra_assists/src/flip_binexpr.rs
@@ -6,8 +6,8 @@ use crate::{Assist, AssistCtx, AssistId};
 /// Flip binary expression assist.
 pub(crate) fn flip_binexpr(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let expr = ctx.node_at_offset::<BinExpr>()?;
-    let lhs = expr.lhs()?.syntax();
-    let rhs = expr.rhs()?.syntax();
+    let lhs = expr.lhs()?.syntax().clone();
+    let rhs = expr.rhs()?.syntax().clone();
     let op_range = expr.op_token()?.range();
     // The assist should be applied only if the cursor is on the operator
     let cursor_in_range = ctx.frange.range.is_subrange(&op_range);
diff --git a/crates/ra_assists/src/flip_comma.rs b/crates/ra_assists/src/flip_comma.rs
index d8dba779f..13016ae06 100644
--- a/crates/ra_assists/src/flip_comma.rs
+++ b/crates/ra_assists/src/flip_comma.rs
@@ -5,8 +5,8 @@ use crate::{Assist, AssistCtx, AssistId};
 
 pub(crate) fn flip_comma(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let comma = ctx.token_at_offset().find(|leaf| leaf.kind() == T![,])?;
-    let prev = non_trivia_sibling(comma.into(), Direction::Prev)?;
-    let next = non_trivia_sibling(comma.into(), Direction::Next)?;
+    let prev = non_trivia_sibling(comma.clone().into(), Direction::Prev)?;
+    let next = non_trivia_sibling(comma.clone().into(), Direction::Next)?;
     ctx.add_action(AssistId("flip_comma"), "flip comma", |edit| {
         edit.target(comma.range());
         edit.replace(prev.range(), next.to_string());
diff --git a/crates/ra_assists/src/inline_local_variable.rs b/crates/ra_assists/src/inline_local_variable.rs
index 554de8b46..3c17089de 100644
--- a/crates/ra_assists/src/inline_local_variable.rs
+++ b/crates/ra_assists/src/inline_local_variable.rs
@@ -16,18 +16,18 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
     if bind_pat.is_mutable() {
         return None;
     }
-    let initializer_expr = let_stmt.initializer();
+    let initializer_expr = let_stmt.initializer()?;
     let delete_range = if let Some(whitespace) = let_stmt
         .syntax()
         .next_sibling_or_token()
-        .and_then(|it| ast::Whitespace::cast(it.as_token()?))
+        .and_then(|it| ast::Whitespace::cast(it.as_token()?.clone()))
     {
         TextRange::from_to(let_stmt.syntax().range().start(), whitespace.syntax().range().end())
     } else {
         let_stmt.syntax().range()
     };
     let analyzer = hir::SourceAnalyzer::new(ctx.db, ctx.frange.file_id, bind_pat.syntax(), None);
-    let refs = analyzer.find_all_refs(bind_pat);
+    let refs = analyzer.find_all_refs(&bind_pat);
 
     let mut wrap_in_parens = vec![true; refs.len()];
 
@@ -45,7 +45,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
             }
         };
 
-        wrap_in_parens[i] = match (initializer_expr?.kind(), usage_parent.kind()) {
+        wrap_in_parens[i] = match (initializer_expr.kind(), usage_parent.kind()) {
             (ExprKind::CallExpr(_), _)
             | (ExprKind::IndexExpr(_), _)
             | (ExprKind::MethodCallExpr(_), _)
@@ -71,7 +71,7 @@ pub(crate) fn inline_local_varialbe(mut ctx: AssistCtx<impl HirDatabase>) -> Opt
         };
     }
 
-    let init_str = initializer_expr?.syntax().text().to_string();
+    let init_str = initializer_expr.syntax().text().to_string();
     let init_in_paren = format!("({})", &init_str);
 
     ctx.add_action(
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs
index f7f5ccafa..ce28132c9 100644
--- a/crates/ra_assists/src/introduce_variable.rs
+++ b/crates/ra_assists/src/introduce_variable.rs
@@ -20,8 +20,8 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
         return None;
     }
     let expr = node.ancestors().find_map(valid_target_expr)?;
-    let (anchor_stmt, wrap_in_block) = anchor_stmt(expr)?;
-    let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?;
+    let (anchor_stmt, wrap_in_block) = anchor_stmt(expr.clone())?;
+    let indent = anchor_stmt.prev_sibling_or_token()?.as_token()?.clone();
     if indent.kind() != WHITESPACE {
         return None;
     }
@@ -37,9 +37,9 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
         };
 
         expr.syntax().text().push_to(&mut buf);
-        let full_stmt = ast::ExprStmt::cast(anchor_stmt);
-        let is_full_stmt = if let Some(expr_stmt) = full_stmt {
-            Some(expr.syntax()) == expr_stmt.expr().map(|e| e.syntax())
+        let full_stmt = ast::ExprStmt::cast(anchor_stmt.clone());
+        let is_full_stmt = if let Some(expr_stmt) = &full_stmt {
+            Some(expr.syntax().clone()) == expr_stmt.expr().map(|e| e.syntax().clone())
         } else {
             false
         };
@@ -81,7 +81,7 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
 
 /// Check whether the node is a valid expression which can be extracted to a variable.
 /// In general that's true for any expression, but in some cases that would produce invalid code.
-fn valid_target_expr(node: &SyntaxNode) -> Option<&ast::Expr> {
+fn valid_target_expr(node: SyntaxNode) -> Option<ast::Expr> {
     match node.kind() {
         PATH_EXPR => None,
         BREAK_EXPR => ast::BreakExpr::cast(node).and_then(|e| e.expr()),
@@ -96,14 +96,10 @@ fn valid_target_expr(node: &SyntaxNode) -> Option<&ast::Expr> {
 /// to produce correct code.
 /// It can be a statement, the last in a block expression or a wanna be block
 /// expression like a lambda or match arm.
-fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> {
+fn anchor_stmt(expr: ast::Expr) -> Option<(SyntaxNode, bool)> {
     expr.syntax().ancestors().find_map(|node| {
-        if ast::Stmt::cast(node).is_some() {
-            return Some((node, false));
-        }
-
         if let Some(expr) = node.parent().and_then(ast::Block::cast).and_then(|it| it.expr()) {
-            if expr.syntax() == node {
+            if expr.syntax() == &node {
                 tested_by!(test_introduce_var_last_expr);
                 return Some((node, false));
             }
@@ -115,6 +111,10 @@ fn anchor_stmt(expr: &ast::Expr) -> Option<(&SyntaxNode, bool)> {
             }
         }
 
+        if ast::Stmt::cast(node.clone()).is_some() {
+            return Some((node, false));
+        }
+
         None
     })
 }
diff --git a/crates/ra_assists/src/move_guard.rs b/crates/ra_assists/src/move_guard.rs
index e1ce86a33..313c9ad18 100644
--- a/crates/ra_assists/src/move_guard.rs
+++ b/crates/ra_assists/src/move_guard.rs
@@ -18,9 +18,9 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
 
     ctx.add_action(AssistId("move_guard_to_arm_body"), "move guard to arm body", |edit| {
         edit.target(guard.syntax().range());
-        let offseting_amount = match space_before_guard {
+        let offseting_amount = match &space_before_guard {
             Some(SyntaxElement::Token(tok)) => {
-                if let Some(_) = ast::Whitespace::cast(tok) {
+                if let Some(_) = ast::Whitespace::cast(tok.clone()) {
                     let ele = space_before_guard.unwrap().range();
                     edit.delete(ele);
                     ele.len()
@@ -39,11 +39,11 @@ pub(crate) fn move_guard_to_arm_body(mut ctx: AssistCtx<impl HirDatabase>) -> Op
 }
 
 pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let match_arm: &MatchArm = ctx.node_at_offset::<MatchArm>()?;
+    let match_arm: MatchArm = ctx.node_at_offset::<MatchArm>()?;
     let last_match_pat = match_arm.pats().last()?;
 
     let arm_body = match_arm.expr()?;
-    let if_expr: &IfExpr = IfExpr::cast(arm_body.syntax())?;
+    let if_expr: IfExpr = IfExpr::cast(arm_body.syntax().clone())?;
     let cond = if_expr.condition()?;
     let then_block = if_expr.then_branch()?;
 
@@ -65,7 +65,7 @@ pub(crate) fn move_arm_cond_to_match_guard(mut ctx: AssistCtx<impl HirDatabase>)
             edit.target(if_expr.syntax().range());
             let then_only_expr = then_block.statements().next().is_none();
 
-            match then_block.expr() {
+            match &then_block.expr() {
                 Some(then_expr) if then_only_expr => {
                     edit.replace(if_expr.syntax().range(), then_expr.syntax().text())
                 }
diff --git a/crates/ra_assists/src/remove_dbg.rs b/crates/ra_assists/src/remove_dbg.rs
index 5680f76ca..c330bc827 100644
--- a/crates/ra_assists/src/remove_dbg.rs
+++ b/crates/ra_assists/src/remove_dbg.rs
@@ -8,7 +8,7 @@ use ra_syntax::{
 pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
     let macro_call = ctx.node_at_offset::<ast::MacroCall>()?;
 
-    if !is_valid_macrocall(macro_call, "dbg")? {
+    if !is_valid_macrocall(&macro_call, "dbg")? {
         return None;
     }
 
@@ -35,7 +35,7 @@ pub(crate) fn remove_dbg(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist>
     };
 
     let macro_content = {
-        let macro_args = macro_call.token_tree()?.syntax();
+        let macro_args = macro_call.token_tree()?.syntax().clone();
         let range = macro_args.range();
         let start = range.start() + TextUnit::of_char('(');
         let end = range.end() - TextUnit::of_char(')');
@@ -65,7 +65,7 @@ fn is_valid_macrocall(macro_call: &ast::MacroCall, macro_name: &str) -> Option<b
         return None;
     }
 
-    let node = macro_call.token_tree()?.syntax();
+    let node = macro_call.token_tree()?.syntax().clone();
     let first_child = node.first_child_or_token()?;
     let last_child = node.last_child_or_token()?;
 
diff --git a/crates/ra_assists/src/replace_if_let_with_match.rs b/crates/ra_assists/src/replace_if_let_with_match.rs
index c2c7cf70b..5de6aa266 100644
--- a/crates/ra_assists/src/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/replace_if_let_with_match.rs
@@ -5,7 +5,7 @@ use ra_syntax::{ast, AstNode};
 use crate::{Assist, AssistCtx, AssistId};
 
 pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) -> Option<Assist> {
-    let if_expr: &ast::IfExpr = ctx.node_at_offset()?;
+    let if_expr: ast::IfExpr = ctx.node_at_offset()?;
     let cond = if_expr.condition()?;
     let pat = cond.pat()?;
     let expr = cond.expr()?;
@@ -25,16 +25,11 @@ pub(crate) fn replace_if_let_with_match(mut ctx: AssistCtx<impl HirDatabase>) ->
     ctx.build()
 }
 
-fn build_match_expr(
-    expr: &ast::Expr,
-    pat1: &ast::Pat,
-    arm1: &ast::Block,
-    arm2: &ast::Block,
-) -> String {
+fn build_match_expr(expr: ast::Expr, pat1: ast::Pat, arm1: ast::Block, arm2: ast::Block) -> String {
     let mut buf = String::new();
     buf.push_str(&format!("match {} {{\n", expr.syntax().text()));
-    buf.push_str(&format!("    {} => {}\n", pat1.syntax().text(), format_arm(arm1)));
-    buf.push_str(&format!("    _ => {}\n", format_arm(arm2)));
+    buf.push_str(&format!("    {} => {}\n", pat1.syntax().text(), format_arm(&arm1)));
+    buf.push_str(&format!("    _ => {}\n", format_arm(&arm2)));
     buf.push_str("}");
     buf
 }
-- 
cgit v1.2.3