Repository: rust-analyzer/rust-analyzer
Pull request #4394 (2020-05-09 17:53:26)

Simplify


Patch:
diff --git a/crates/ra_assists/src/assist_context.rs b/crates/ra_assists/src/assist_context.rs
index a680f752b3..3085c4330c 100644
--- a/crates/ra_assists/src/assist_context.rs
+++ b/crates/ra_assists/src/assist_context.rs
@@ -49,7 +49,7 @@ use crate::{Assist, AssistId, GroupLabel, ResolvedAssist};
 /// easier to just compute the edit eagerly :-)
 pub(crate) struct AssistContext<'a> {
     pub(crate) sema: Semantics<'a, RootDatabase>,
-    pub(crate) db: &'a RootDatabase,
+    pub(super) db: &'a RootDatabase,
     pub(crate) frange: FileRange,
     source_file: SourceFile,
 }
diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs
index 146cc75df2..55409e5013 100644
--- a/crates/ra_assists/src/handlers/add_explicit_type.rs
+++ b/crates/ra_assists/src/handlers/add_explicit_type.rs
@@ -23,7 +23,6 @@ use crate::{AssistContext, AssistId, Assists};
 // ```
 pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let stmt = ctx.find_node_at_offset::<LetStmt>()?;
-    let module = ctx.sema.scope(stmt.syntax()).module()?;
     let expr = stmt.initializer()?;
     let pat = stmt.pat()?;
     // Must be a binding
@@ -58,17 +57,17 @@ pub(crate) fn add_explicit_type(acc: &mut Assists, ctx: &AssistContext) -> Optio
         return None;
     }
 
-    let inferred_type = ty.display_source_code(ctx.db, module.into()).ok()?;
+    let db = ctx.db;
+    let new_type_string = ty.display_truncated(db, None).to_string();
     acc.add(
         AssistId("add_explicit_type"),
-        format!("Insert explicit type '{}'", inferred_type),
+        format!("Insert explicit type '{}'", new_type_string),
         pat_range,
-        |builder| match ascribed_ty {
-            Some(ascribed_ty) => {
-                builder.replace(ascribed_ty.syntax().text_range(), inferred_type);
-            }
-            None => {
-                builder.insert(name_range.end(), format!(": {}", inferred_type));
+        |edit| {
+            if let Some(ascribed_ty) = ascribed_ty {
+                edit.replace(ascribed_ty.syntax().text_range(), new_type_string);
+            } else {
+                edit.insert(name_range.end(), format!(": {}", new_type_string));
             }
         },
     )
@@ -209,7 +208,7 @@ struct Test<K, T = u8> {
 }
 
 fn main() {
-    let test<|>: Test<i32, u8> = Test { t: 23, k: 33 };
+    let test<|>: Test<i32> = Test { t: 23, k: 33 };
 }"#,
         );
     }
diff --git a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
index 6a49b7dbd1..275184e246 100644
--- a/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
+++ b/crates/ra_assists/src/handlers/add_from_impl_for_enum.rs
@@ -1,5 +1,8 @@
 use ra_ide_db::RootDatabase;
-use ra_syntax::ast::{self, AstNode, NameOwner};
+use ra_syntax::{
+    ast::{self, AstNode, NameOwner},
+    TextSize,
+};
 use stdx::format_to;
 use test_utils::tested_by;
 
@@ -66,6 +69,7 @@ impl From<{0}> for {1} {{
                 variant_name
             );
             edit.insert(start_offset, buf);
+            edit.set_cursor(start_offset + TextSize::of("\n\n"));
         },
     )
 }
@@ -93,20 +97,19 @@ fn existing_from_impl(
 
 #[cfg(test)]
 mod tests {
-    use test_utils::covers;
+    use super::*;
 
     use crate::tests::{check_assist, check_assist_not_applicable};
-
-    use super::*;
+    use test_utils::covers;
 
     #[test]
     fn test_add_from_impl_for_enum() {
         check_assist(
             add_from_impl_for_enum,
             "enum A { <|>One(u32) }",
-            r#"enum A { <|>One(u32) }
+            r#"enum A { One(u32) }
 
-impl From<u32> for A {
+<|>impl From<u32> for A {
     fn from(v: u32) -> Self {
         A::One(v)
     }
@@ -118,10 +121,10 @@ impl From<u32> for A {
     fn test_add_from_impl_for_enum_complicated_path() {
         check_assist(
             add_from_impl_for_enum,
-            r#"enum A { <|>One(foo::bar::baz::Boo) }"#,
-            r#"enum A { <|>One(foo::bar::baz::Boo) }
+            "enum A { <|>One(foo::bar::baz::Boo) }",
+            r#"enum A { One(foo::bar::baz::Boo) }
 
-impl From<foo::bar::baz::Boo> for A {
+<|>impl From<foo::bar::baz::Boo> for A {
     fn from(v: foo::bar::baz::Boo) -> Self {
         A::One(v)
     }
@@ -181,9 +184,9 @@ impl From<String> for A {
 pub trait From<T> {
     fn from(T) -> Self;
 }"#,
-            r#"enum A { <|>One(u32), Two(String), }
+            r#"enum A { One(u32), Two(String), }
 
-impl From<u32> for A {
+<|>impl From<u32> for A {
     fn from(v: u32) -> Self {
         A::One(v)
     }
diff --git a/crates/ra_assists/src/handlers/add_function.rs b/crates/ra_assists/src/handlers/add_function.rs
index de016ae4e1..6b5616aa9c 100644
--- a/crates/ra_assists/src/handlers/add_function.rs
+++ b/crates/ra_assists/src/handlers/add_function.rs
@@ -1,11 +1,7 @@
 use hir::HirDisplay;
 use ra_db::FileId;
 use ra_syntax::{
-    ast::{
-        self,
-        edit::{AstNodeEdit, IndentLevel},
-        ArgListOwner, AstNode, ModuleItemOwner,
-    },
+    ast::{self, edit::IndentLevel, ArgListOwner, AstNode, ModuleItemOwner},
     SyntaxKind, SyntaxNode, TextSize,
 };
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -47,12 +43,16 @@ pub(crate) fn add_function(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
         return None;
     }
 
-    let target_module = match path.qualifier() {
-        Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
-            Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => Some(module),
-            _ => return None,
-        },
-        None => None,
+    let target_module = if let Some(qualifier) = path.qualifier() {
+        if let Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) =
+            ctx.sema.resolve_path(&qualifier)
+        {
+            Some(module.definition_source(ctx.sema.db))
+        } else {
+            return None;
+        }
+    } else {
+        None
     };
 
     let function_builder = FunctionBuilder::from_call(&ctx, &call, &path, target_module)?;
@@ -83,29 +83,25 @@ struct FunctionBuilder {
 }
 
 impl FunctionBuilder {
-    /// Prepares a generated function that matches `call`.
-    /// The function is generated in `target_module` or next to `call`
+    /// Prepares a generated function that matches `call` in `generate_in`
+    /// (or as close to `call` as possible, if `generate_in` is `None`)
     fn from_call(
         ctx: &AssistContext,
         call: &ast::CallExpr,
         path: &ast::Path,
-        target_module: Option<hir::Module>,
+        target_module: Option<hir::InFile<hir::ModuleSource>>,
     ) -> Option<Self> {
+        let needs_pub = target_module.is_some();
         let mut file = ctx.frange.file_id;
-        let target = match &target_module {
-            Some(target_module) => {
-                let module_source = target_module.definition_source(ctx.db);
-                let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, &module_source)?;
-                file = in_file;
-                target
-            }
-            None => next_space_for_fn_after_call_site(&call)?,
+        let target = if let Some(target_module) = target_module {
+            let (in_file, target) = next_space_for_fn_in_module(ctx.sema.db, target_module)?;
+            file = in_file;
+            target
+        } else {
+            next_space_for_fn_after_call_site(&call)?
         };
-        let needs_pub = target_module.is_some();
-        let target_module = target_module.or_else(|| ctx.sema.scope(target.syntax()).module())?;
         let fn_name = fn_name(&path)?;
-        let (type_params, params) = fn_args(ctx, target_module, &call)?;
-
+        let (type_params, params) = fn_args(ctx, &call)?;
         Some(Self { target, fn_name, type_params, params, file, needs_pub })
     }
 
@@ -120,16 +116,17 @@ impl FunctionBuilder {
         let (fn_def, insert_offset) = match self.target {
             GeneratedFunctionTarget::BehindItem(it) => {
                 let with_leading_blank_line = ast::make::add_leading_newlines(2, fn_def);
-                let indented = with_leading_blank_line.indent(IndentLevel::from_node(&it));
+                let indented = IndentLevel::from_node(&it).increase_indent(with_leading_blank_line);
                 (indented, it.text_range().end())
             }
             GeneratedFunctionTarget::InEmptyItemList(it) => {
                 let indent_once = IndentLevel(1);
                 let indent = IndentLevel::from_node(it.syntax());
+
                 let fn_def = ast::make::add_leading_newlines(1, fn_def);
-                let fn_def = fn_def.indent(indent_once);
+                let fn_def = indent_once.increase_indent(fn_def);
                 let fn_def = ast::make::add_trailing_newlines(1, fn_def);
-                let fn_def = fn_def.indent(indent);
+                let fn_def = indent.increase_indent(fn_def);
                 (fn_def, it.syntax().text_range().start() + TextSize::of('{'))
             }
         };
@@ -147,15 +144,6 @@ enum GeneratedFunctionTarget {
     InEmptyItemList(ast::ItemList),
 }
 
-impl GeneratedFunctionTarget {
-    fn syntax(&self) -> &SyntaxNode {
-        match self {
-            GeneratedFunctionTarget::BehindItem(it) => it,
-            GeneratedFunctionTarget::InEmptyItemList(it) => it.syntax(),
-        }
-    }
-}
-
 fn fn_name(call: &ast::Path) -> Option<ast::Name> {
     let name = call.segment()?.syntax().to_string();
     Some(ast::make::name(&name))
@@ -164,17 +152,17 @@ fn fn_name(call: &ast::Path) -> Option<ast::Name> {
 /// Computes the type variables and arguments required for the generated function
 fn fn_args(
     ctx: &AssistContext,
-    target_module: hir::Module,
     call: &ast::CallExpr,
 ) -> Option<(Option<ast::TypeParamList>, ast::ParamList)> {
     let mut arg_names = Vec::new();
     let mut arg_types = Vec::new();
     for arg in call.arg_list()?.args() {
-        arg_names.push(match fn_arg_name(&arg) {
+        let arg_name = match fn_arg_name(&arg) {
             Some(name) => name,
             None => String::from("arg"),
-        });
-        arg_types.push(match fn_arg_type(ctx, target_module, &arg) {
+        };
+        arg_names.push(arg_name);
+        arg_types.push(match fn_arg_type(ctx, &arg) {
             Some(ty) => ty,
             None => String::from("()"),
         });
@@ -230,21 +218,12 @@ fn fn_arg_name(fn_arg: &ast::Expr) -> Option<String> {
     }
 }
 
-fn fn_arg_type(
-    ctx: &AssistContext,
-    target_module: hir::Module,
-    fn_arg: &ast::Expr,
-) -> Option<String> {
+fn fn_arg_type(ctx: &AssistContext, fn_arg: &ast::Expr) -> Option<String> {
     let ty = ctx.sema.type_of_expr(fn_arg)?;
     if ty.is_unknown() {
         return None;
     }
-
-    if let Ok(rendered) = ty.display_source_code(ctx.db, target_module.into()) {
-        Some(rendered)
-    } else {
-        None
-    }
+    Some(ty.display(ctx.sema.db).to_string())
 }
 
 /// Returns the position inside the current mod or file
@@ -273,10 +252,10 @@ fn next_space_for_fn_after_call_site(expr: &ast::CallExpr) -> Option<GeneratedFu
 
 fn next_space_for_fn_in_module(
     db: &dyn hir::db::AstDatabase,
-    module_source: &hir::InFile<hir::ModuleSource>,
+    module: hir::InFile<hir::ModuleSource>,
 ) -> Option<(FileId, GeneratedFunctionTarget)> {
-    let file = module_source.file_id.original_file(db);
-    let assist_item = match &module_source.value {
+    let file = module.file_id.original_file(db);
+    let assist_item = match module.value {
         hir::ModuleSource::SourceFile(it) => {
             if let Some(last_item) = it.items().last() {
                 GeneratedFunctionTarget::BehindItem(last_item.syntax().clone())
@@ -620,33 +599,8 @@ fn bar(foo: impl Foo) {
     }
 
     #[test]
-    fn borrowed_arg() {
-        check_assist(
-            add_function,
-            r"
-struct Baz;
-fn baz() -> Baz { todo!() }
-
-fn foo() {
-    bar<|>(&baz())
-}
-",
-            r"
-struct Baz;
-fn baz() -> Baz { todo!() }
-
-fn foo() {
-    bar(&baz())
-}
-
-fn bar(baz: &Baz) {
-    <|>todo!()
-}
-",
-        )
-    }
-
-    #[test]
+    #[ignore]
+    // FIXME print paths properly to make this test pass
     fn add_function_with_qualified_path_arg() {
         check_assist(
             add_function,
@@ -655,8 +609,10 @@ mod Baz {
     pub struct Bof;
     pub fn baz() -> Bof { Bof }
 }
-fn foo() {
-    <|>bar(Baz::baz())
+mod Foo {
+    fn foo() {
+        <|>bar(super::Baz::baz())
+    }
 }
 ",
             r"
@@ -664,12 +620,14 @@ mod Baz {
     pub struct Bof;
     pub fn baz() -> Bof { Bof }
 }
-fn foo() {
-    bar(Baz::baz())
-}
+mod Foo {
+    fn foo() {
+        bar(super::Baz::baz())
+    }
 
-fn bar(baz: Baz::Bof) {
-    <|>todo!()
+    fn bar(baz: super::Baz::Bof) {
+        <|>todo!()
+    }
 }
 ",
         )
@@ -850,40 +808,6 @@ fn foo() {
         )
     }
 
-    #[test]
-    #[ignore]
-    // Ignored until local imports are supported.
-    // See https://github.com/rust-analyzer/rust-analyzer/issues/1165
-    fn qualified_path_uses_correct_scope() {
-        check_assist(
-            add_function,
-            "
-mod foo {
-    pub struct Foo;
-}
-fn bar() {
-    use foo::Foo;
-    let foo = Foo;
-    baz<|>(foo)
-}
-",
-            "
-mod foo {
-    pub struct Foo;
-}
-fn bar() {
-    use foo::Foo;
-    let foo = Foo;
-    baz(foo)
-}
-
-fn baz(foo: foo::Foo) {
-    <|>todo!()
-}
-",
-        )
-    }
-
     #[test]
     fn add_function_in_module_containing_other_items() {
         check_assist(
@@ -995,6 +919,21 @@ fn bar(baz: ()) {}
         )
     }
 
+    #[test]
+    fn add_function_not_applicable_if_function_path_not_singleton() {
+        // In the future this assist could be extended to generate functions
+        // if the path is in the same crate (or even the same workspace).
+        // For the beginning, I think this is fine.
+        check_assist_not_applicable(
+            add_function,
+            r"
+fn foo() {
+    other_crate::bar<|>();
+}
+        ",
+        )
+    }
+
     #[test]
     #[ignore]
     fn create_method_with_no_args() {
diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
index c1ce87914a..3482a75bfc 100644
--- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs
@@ -2,7 +2,7 @@ use hir::HasSource;
 use ra_syntax::{
     ast::{
         self,
-        edit::{self, AstNodeEdit, IndentLevel},
+        edit::{self, IndentLevel},
         make, AstNode, NameOwner,
     },
     SmolStr,
@@ -176,7 +176,8 @@ fn add_body(fn_def: ast::FnDef) -> ast::FnDef {
     if fn_def.body().is_some() {
         return fn_def;
     }
-    let body = make::block_expr(None, Some(make::expr_todo())).indent(IndentLevel(1));
+    let body = make::block_expr(None, Some(make::expr_todo()));
+    let body = IndentLevel(1).increase_indent(body);
     fn_def.with_body(body)
 }
 
diff --git a/crates/ra_assists/src/handlers/early_return.rs b/crates/ra_assists/src/handlers/early_return.rs
index 66b296081d..810784ad57 100644
--- a/crates/ra_assists/src/handlers/early_return.rs
+++ b/crates/ra_assists/src/handlers/early_return.rs
@@ -2,11 +2,7 @@ use std::{iter::once, ops::RangeInclusive};
 
 use ra_syntax::{
     algo::replace_children,
-    ast::{
-        self,
-        edit::{AstNodeEdit, IndentLevel},
-        make,
-    },
+    ast::{self, edit::IndentLevel, make},
     AstNode,
     SyntaxKind::{FN_DEF, LOOP_EXPR, L_CURLY, R_CURLY, WHILE_EXPR, WHITESPACE},
     SyntaxNode,
@@ -109,7 +105,8 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
                     let then_branch =
                         make::block_expr(once(make::expr_stmt(early_expression).into()), None);
                     let cond = invert_boolean_expression(cond_expr);
-                    make::expr_if(make::condition(cond, None), then_branch).indent(if_indent_level)
+                    let e = make::expr_if(make::condition(cond, None), then_branch);
+                    if_indent_level.increase_indent(e)
                 };
                 replace(new_expr.syntax(), &then_block, &parent_block, &if_expr)
             }
@@ -143,7 +140,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
                     make::bind_pat(make::name(&bound_ident.syntax().to_string())).into(),
                     Some(match_expr),
                 );
-                let let_stmt = let_stmt.indent(if_indent_level);
+                let let_stmt = if_indent_level.increase_indent(let_stmt);
                 replace(let_stmt.syntax(), &then_block, &parent_block, &if_expr)
             }
         };
@@ -156,7 +153,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext)
             parent_block: &ast::BlockExpr,
             if_expr: &ast::IfExpr,
         ) -> SyntaxNode {
-            let then_block_items = then_block.dedent(IndentLevel::from(1));
+            let then_block_items = IndentLevel::from(1).decrease_indent(then_block.clone());
             let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
             let end_of_then =
                 if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
diff --git a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
index 65f5fc6abe..a59a06efa5 100644
--- a/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_if_let_with_match.rs
@@ -1,10 +1,6 @@
 use ra_fmt::unwrap_trivial_block;
 use ra_syntax::{
-    ast::{
-        self,
-        edit::{AstNodeEdit, IndentLevel},
-        make,
-    },
+    ast::{self, edit::IndentLevel, make},
     AstNode,
 };
 
@@ -65,9 +61,10 @@ pub(crate) fn replace_if_let_with_match(acc: &mut Assists, ctx: &AssistContext)
                 make::match_arm(vec![pattern], else_expr)
             };
             make::expr_match(expr, make::match_arm_list(vec![then_arm, else_arm]))
-                .indent(IndentLevel::from_node(if_expr.syntax()))
         };
 
+        let match_expr = IndentLevel::from_node(if_expr.syntax()).increase_indent(match_expr);
+
         edit.set_cursor(if_expr.syntax().text_range().start());
         edit.replace_ast::<ast::Expr>(if_expr.into(), match_expr);
     })
diff --git a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
index 482957dc60..d3f214591a 100644
--- a/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
+++ b/crates/ra_assists/src/handlers/replace_let_with_if_let.rs
@@ -53,7 +53,8 @@ pub(crate) fn replace_let_with_if_let(acc: &mut Assists, ctx: &AssistContext) ->
             )
             .into(),
         };
-        let block = make::block_expr(None, None).indent(IndentLevel::from_node(let_stmt.syntax()));
+        let block =
+            IndentLevel::from_node(let_stmt.syntax()).increase_indent(make::block_expr(None, None));
         let if_ = make::expr_if(make::condition(init, Some(with_placeholder)), block);
         let stmt = make::expr_stmt(if_);
 
diff --git a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
index c4b56f6e90..a46998b8eb 100644
--- a/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
+++ b/crates/ra_assists/src/handlers/replace_unwrap_with_match.rs
@@ -1,11 +1,7 @@
 use std::iter;
 
 use ra_syntax::{
-    ast::{
-        self,
-        edit::{AstNodeEdit, IndentLevel},
-        make,
-    },
+    ast::{self, edit::IndentLevel, make},
     AstNode,
 };
 
@@ -55,8 +51,8 @@ pub(crate) fn replace_unwrap_with_match(acc: &mut Assists, ctx: &AssistContext)
         let err_arm = make::match_arm(iter::once(make::placeholder_pat().into()), unreachable_call);
 
         let match_arm_list = make::match_arm_list(vec![ok_arm, err_arm]);
-        let match_expr = make::expr_match(caller.clone(), match_arm_list)
-            .indent(IndentLevel::from_node(method_call.syntax()));
+        let match_expr = make::expr_match(caller.clone(), match_arm_list);
+        let match_expr = IndentLevel::from_node(method_call.syntax()).increase_indent(match_expr);
 
         edit.set_cursor(caller.syntax().text_range().start());
         edit.replace_ast::<ast::Expr>(method_call.into(), match_expr);
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index be18c845c6..5f480c3040 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -22,11 +22,8 @@ use hir_expand::{
     MacroDefId, MacroDefKind,
 };
 use hir_ty::{
-    autoderef,
-    display::{HirDisplayError, HirFormatter},
-    expr::ExprValidator,
-    method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, Ty,
-    TyDefId, TypeCtor,
+    autoderef, display::HirFormatter, expr::ExprValidator, method_resolution, ApplicationTy,
+    Canonical, InEnvironment, Substs, TraitEnvironment, Ty, TyDefId, TypeCtor,
 };
 use ra_db::{CrateId, CrateName, Edition, FileId};
 use ra_prof::profile;
@@ -1322,7 +1319,7 @@ impl Type {
 }
 
 impl HirDisplay for Type {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> std::fmt::Result {
         self.ty.value.hir_fmt(f)
     }
 }
diff --git a/crates/ra_hir_ty/src/display.rs b/crates/ra_hir_ty/src/display.rs
index f5edaea8c8..d03bbd5a7b 100644
--- a/crates/ra_hir_ty/src/display.rs
+++ b/crates/ra_hir_ty/src/display.rs
@@ -6,42 +6,28 @@ use crate::{
     db::HirDatabase, utils::generics, ApplicationTy, CallableDef, FnSig, GenericPredicate,
     Obligation, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
 };
-use hir_def::{
-    find_path, generics::TypeParamProvenance, item_scope::ItemInNs, AdtId, AssocContainerId,
-    Lookup, ModuleId,
-};
+use hir_def::{generics::TypeParamProvenance, AdtId, AssocContainerId, Lookup};
 use hir_expand::name::Name;
 
-pub struct HirFormatter<'a> {
+pub struct HirFormatter<'a, 'b> {
     pub db: &'a dyn HirDatabase,
-    fmt: &'a mut dyn fmt::Write,
+    fmt: &'a mut fmt::Formatter<'b>,
     buf: String,
     curr_size: usize,
     pub(crate) max_size: Option<usize>,
     omit_verbose_types: bool,
-    display_target: DisplayTarget,
 }
 
 pub trait HirDisplay {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError>;
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result;
 
-    /// Returns a `Display`able type that is human-readable.
-    /// Use this for showing types to the user (e.g. diagnostics)
     fn display<'a>(&'a self, db: &'a dyn HirDatabase) -> HirDisplayWrapper<'a, Self>
     where
         Self: Sized,
     {
-        HirDisplayWrapper {
-            db,
-            t: self,
-            max_size: None,
-            omit_verbose_types: false,
-            display_target: DisplayTarget::Diagnostics,
-        }
+        HirDisplayWrapper(db, self, None, false)
     }
 
-    /// Returns a `Display`able type that is human-readable and tries to be succinct.
-    /// Use this for showing types to the user where space is constrained (e.g. doc popups)
     fn display_truncated<'a>(
         &'a self,
         db: &'a dyn HirDatabase,
@@ -50,46 +36,16 @@ pub trait HirDisplay {
     where
         Self: Sized,
     {
-        HirDisplayWrapper {
-            db,
-            t: self,
-            max_size,
-            omit_verbose_types: true,
-            display_target: DisplayTarget::Diagnostics,
-        }
-    }
-
-    /// Returns a String representation of `self` that can be inserted into the given module.
-    /// Use this when generating code (e.g. assists)
-    fn display_source_code<'a>(
-        &'a self,
-        db: &'a dyn HirDatabase,
-        module_id: ModuleId,
-    ) -> Result<String, DisplaySourceCodeError> {
-        let mut result = String::new();
-        match self.hir_fmt(&mut HirFormatter {
-            db,
-            fmt: &mut result,
-            buf: String::with_capacity(20),
-            curr_size: 0,
-            max_size: None,
-            omit_verbose_types: false,
-            display_target: DisplayTarget::SourceCode { module_id },
-        }) {
-            Ok(()) => {}
-            Err(HirDisplayError::FmtError) => panic!("Writing to String can't fail!"),
-            Err(HirDisplayError::DisplaySourceCodeError(e)) => return Err(e),
-        };
-        Ok(result)
+        HirDisplayWrapper(db, self, max_size, true)
     }
 }
 
-impl<'a> HirFormatter<'a> {
+impl<'a, 'b> HirFormatter<'a, 'b> {
     pub fn write_joined<T: HirDisplay>(
         &mut self,
         iter: impl IntoIterator<Item = T>,
         sep: &str,
-    ) -> Result<(), HirDisplayError> {
+    ) -> fmt::Result {
         let mut first = true;
         for e in iter {
             if !first {
@@ -102,14 +58,14 @@ impl<'a> HirFormatter<'a> {
     }
 
     /// This allows using the `write!` macro directly with a `HirFormatter`.
-    pub fn write_fmt(&mut self, args: fmt::Arguments) -> Result<(), HirDisplayError> {
+    pub fn write_fmt(&mut self, args: fmt::Arguments) -> fmt::Result {
         // We write to a buffer first to track output size
         self.buf.clear();
         fmt::write(&mut self.buf, args)?;
         self.curr_size += self.buf.len();
 
         // Then we write to the internal formatter from the buffer
-        self.fmt.write_str(&self.buf).map_err(HirDisplayError::from)
+        self.fmt.write_str(&self.buf)
     }
 
     pub fn should_truncate(&self) -> bool {
@@ -125,76 +81,34 @@ impl<'a> HirFormatter<'a> {
     }
 }
 
-#[derive(Clone, Copy)]
-enum DisplayTarget {
-    /// Display types for inlays, doc popups, autocompletion, etc...
-    /// Showing `{unknown}` or not qualifying paths is fine here.
-    /// There's no reason for this to fail.
-    Diagnostics,
-    /// Display types for inserting them in source files.
-    /// The generated code should compile, so paths need to be qualified.
-    SourceCode { module_id: ModuleId },
-}
-
-#[derive(Debug)]
-pub enum DisplaySourceCodeError {
-    PathNotFound,
-}
-
-pub enum HirDisplayError {
-    /// Errors that can occur when generating source code
-    DisplaySourceCodeError(DisplaySourceCodeError),
-    /// `FmtError` is required to be compatible with std::fmt::Display
-    FmtError,
-}
-impl From<fmt::Error> for HirDisplayError {
-    fn from(_: fmt::Error) -> Self {
-        Self::FmtError
-    }
-}
-
-pub struct HirDisplayWrapper<'a, T> {
-    db: &'a dyn HirDatabase,
-    t: &'a T,
-    max_size: Option<usize>,
-    omit_verbose_types: bool,
-    display_target: DisplayTarget,
-}
+pub struct HirDisplayWrapper<'a, T>(&'a dyn HirDatabase, &'a T, Option<usize>, bool);
 
 impl<'a, T> fmt::Display for HirDisplayWrapper<'a, T>
 where
     T: HirDisplay,
 {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        match self.t.hir_fmt(&mut HirFormatter {
-            db: self.db,
+        self.1.hir_fmt(&mut HirFormatter {
+            db: self.0,
             fmt: f,
             buf: String::with_capacity(20),
             curr_size: 0,
-            max_size: self.max_size,
-            omit_verbose_types: self.omit_verbose_types,
-            display_target: self.display_target,
-        }) {
-            Ok(()) => Ok(()),
-            Err(HirDisplayError::FmtError) => Err(fmt::Error),
-            Err(HirDisplayError::DisplaySourceCodeError(_)) => {
-                // This should never happen
-                panic!("HirDisplay failed when calling Display::fmt!")
-            }
-        }
+            max_size: self.2,
+            omit_verbose_types: self.3,
+        })
     }
 }
 
 const TYPE_HINT_TRUNCATION: &str = "…";
 
 impl HirDisplay for &Ty {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         HirDisplay::hir_fmt(*self, f)
     }
 }
 
 impl HirDisplay for ApplicationTy {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
@@ -277,30 +191,12 @@ impl HirDisplay for ApplicationTy {
                 }
             }
             TypeCtor::Adt(def_id) => {
-                match f.display_target {
-                    DisplayTarget::Diagnostics => {
-                        let name = match def_id {
-                            AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
-                            AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
-                            AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
-                        };
-                        write!(f, "{}", name)?;
-                    }
-                    DisplayTarget::SourceCode { module_id } => {
-                        if let Some(path) = find_path::find_path(
-                            f.db.upcast(),
-                            ItemInNs::Types(def_id.into()),
-                            module_id,
-                        ) {
-                            write!(f, "{}", path)?;
-                        } else {
-                            return Err(HirDisplayError::DisplaySourceCodeError(
-                                DisplaySourceCodeError::PathNotFound,
-                            ));
-                        }
-                    }
-                }
-
+                let name = match def_id {
+                    AdtId::StructId(it) => f.db.struct_data(it).name.clone(),
+                    AdtId::UnionId(it) => f.db.union_data(it).name.clone(),
+                    AdtId::EnumId(it) => f.db.enum_data(it).name.clone(),
+                };
+                write!(f, "{}", name)?;
                 if self.parameters.len() > 0 {
                     let mut non_default_parameters = Vec::with_capacity(self.parameters.len());
                     let parameters_to_write = if f.omit_verbose_types() {
@@ -373,7 +269,7 @@ impl HirDisplay for ApplicationTy {
 }
 
 impl HirDisplay for ProjectionTy {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
@@ -391,7 +287,7 @@ impl HirDisplay for ProjectionTy {
 }
 
 impl HirDisplay for Ty {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
@@ -436,7 +332,7 @@ impl HirDisplay for Ty {
 fn write_bounds_like_dyn_trait(
     predicates: &[GenericPredicate],
     f: &mut HirFormatter,
-) -> Result<(), HirDisplayError> {
+) -> fmt::Result {
     // Note: This code is written to produce nice results (i.e.
     // corresponding to surface Rust) for types that can occur in
     // actual Rust. It will have weird results if the predicates
@@ -498,7 +394,7 @@ fn write_bounds_like_dyn_trait(
 }
 
 impl TraitRef {
-    fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
+    fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> fmt::Result {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
@@ -520,19 +416,19 @@ impl TraitRef {
 }
 
 impl HirDisplay for TraitRef {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         self.hir_fmt_ext(f, false)
     }
 }
 
 impl HirDisplay for &GenericPredicate {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         HirDisplay::hir_fmt(*self, f)
     }
 }
 
 impl HirDisplay for GenericPredicate {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
         if f.should_truncate() {
             return write!(f, "{}", TYPE_HINT_TRUNCATION);
         }
@@ -556,15 +452,15 @@ impl HirDisplay for GenericPredicate {
 }
 
 impl HirDisplay for Obligation {
-    fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
-        Ok(match self {
-            Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db))?,
+    fn hir_fmt(&self, f: &mut HirFormatter) -> fmt::Result {
+        match self {
+            Obligation::Trait(tr) => write!(f, "Implements({})", tr.display(f.db)),
             Obligation::Projection(proj) => write!(
                 f,
                 "Normalize({} => {})",
                 proj.projection_ty.display(f.db),
                 proj.ty.display(f.db)
-            )?,
-        })
+            ),
+        }
     }
 }
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs
index 24a1e1d918..3e6dd6061c 100644
--- a/crates/ra_syntax/src/ast/edit.rs
+++ b/crates/ra_syntax/src/ast/edit.rs
@@ -453,7 +453,11 @@ impl IndentLevel {
         IndentLevel(0)
     }
 
-    fn increase_indent(self, node: SyntaxNode) -> SyntaxNode {
+    pub fn increase_indent<N: AstNode>(self, node: N) -> N {
+        N::cast(self._increase_indent(node.syntax().clone())).unwrap()
+    }
+
+    fn _increase_indent(self, node: SyntaxNode) -> SyntaxNode {
         let mut rewriter = SyntaxRewriter::default();
         node.descendants_with_tokens()
             .filter_map(|el| el.into_token())
@@ -474,7 +478,11 @@ impl IndentLevel {
         rewriter.rewrite(&node)
     }
 
-    fn decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
+    pub fn decrease_indent<N: AstNode>(self, node: N) -> N {
+        N::cast(self._decrease_indent(node.syntax().clone())).unwrap()
+    }
+
+    fn _decrease_indent(self, node: SyntaxNode) -> SyntaxNode {
         let mut rewriter = SyntaxRewriter::default();
         node.descendants_with_tokens()
             .filter_map(|el| el.into_token())
@@ -513,7 +521,7 @@ fn prev_tokens(token: SyntaxToken) -> impl Iterator<Item = SyntaxToken> {
     iter::successors(Some(token), |token| token.prev_token())
 }
 
-pub trait AstNodeEdit: AstNode + Clone + Sized {
+pub trait AstNodeEdit: AstNode + Sized {
     #[must_use]
     fn insert_children(
         &self,
@@ -550,17 +558,9 @@ pub trait AstNodeEdit: AstNode + Clone + Sized {
         }
         rewriter.rewrite_ast(self)
     }
-    #[must_use]
-    fn indent(&self, indent: IndentLevel) -> Self {
-        Self::cast(indent.increase_indent(self.syntax().clone())).unwrap()
-    }
-    #[must_use]
-    fn dedent(&self, indent: IndentLevel) -> Self {
-        Self::cast(indent.decrease_indent(self.syntax().clone())).unwrap()
-    }
 }
 
-impl<N: AstNode + Clone> AstNodeEdit for N {}
+impl<N: AstNode> AstNodeEdit for N {}
 
 fn single_node(element: impl Into<SyntaxElement>) -> RangeInclusive<SyntaxElement> {
     let element = element.into();
@@ -580,7 +580,7 @@ fn test_increase_indent() {
     _ => (),
 }"
     );
-    let indented = arm_list.indent(IndentLevel(2));
+    let indented = IndentLevel(2).increase_indent(arm_list);
     assert_eq!(
         indented.syntax().to_string(),
         "{
diff --git a/crates/ra_toolchain/src/lib.rs b/crates/ra_toolchain/src/lib.rs
index 3c307a0eac..3d2865e09c 100644
--- a/crates/ra_toolchain/src/lib.rs
+++ b/crates/ra_toolchain/src/lib.rs
@@ -53,10 +53,9 @@ fn lookup_in_path(exec: &str) -> bool {
     let paths = env::var_os("PATH").unwrap_or_default();
     let mut candidates = env::split_paths(&paths).flat_map(|path| {
         let candidate = path.join(&exec);
-        let with_exe = if env::consts::EXE_EXTENSION == "" {
-            None
-        } else {
-            Some(candidate.with_extension(env::consts::EXE_EXTENSION))
+        let with_exe = match env::consts::EXE_EXTENSION {
+            "" => None,
+            it => Some(candidate.with_extension(it)),
         };
         iter::once(candidate).chain(with_exe)
     });
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index 17b0b95b9d..a8fa2af08b 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -173,7 +173,6 @@ pub fn main_loop(ws_roots: Vec<PathBuf>, config: Config, connection: Connection)
     };
 
     loop_state.roots_total = world_state.vfs.read().n_roots();
-    loop_state.roots_scanned = 0;
 
     let pool = ThreadPool::default();
     let (task_sender, task_receiver) = unbounded::<Task>();
@@ -400,10 +399,12 @@ fn loop_turn(
     }
 
     let max_in_flight_libs = pool.max_count().saturating_sub(2).max(1);
-    while loop_state.in_flight_libraries < max_in_flight_libs
-        && !loop_state.pending_libraries.is_empty()
-    {
-        let (root, files) = loop_state.pending_libraries.pop().unwrap();
+    while loop_state.in_flight_libraries < max_in_flight_libs {
+        let (root, files) = match loop_state.pending_libraries.pop() {
+            Some(it) => it,
+            None => break,
+        };
+
         loop_state.in_flight_libraries += 1;
         let sender = libdata_sender.clone();
         pool.execute(move || {
diff --git a/crates/rust-analyzer/src/world.rs b/crates/rust-analyzer/src/world.rs
index 16020648df..6333c15b2b 100644
--- a/crates/rust-analyzer/src/world.rs
+++ b/crates/rust-analyzer/src/world.rs
@@ -137,15 +137,6 @@ impl WorldState {
             opts
         };
 
-        // Create crate graph from all the workspaces
-        let mut crate_graph = CrateGraph::default();
-        let mut load = |path: &std::path::Path| {
-            // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs
-            let path = path.canonicalize().ok()?;
-            let vfs_file = vfs.load(&path);
-            vfs_file.map(|f| FileId(f.0))
-        };
-
         let proc_macro_client = match &config.proc_macro_srv {
             None => ProcMacroClient::dummy(),
             Some((path, args)) => match ProcMacroClient::extern_process(path.into(), args) {
@@ -161,19 +152,22 @@ impl WorldState {
             },
         };
 
-        workspaces
-            .iter()
-            .map(|ws| {
-                ws.to_crate_graph(
-                    &default_cfg_options,
-                    &extern_source_roots,
-                    &proc_macro_client,
-                    &mut load,
-                )
-            })
-            .for_each(|graph| {
-                crate_graph.extend(graph);
-            });
+        // Create crate graph from all the workspaces
+        let mut crate_graph = CrateGraph::default();
+        let mut load = |path: &Path| {
+            // Some path from metadata will be non canonicalized, e.g. /foo/../bar/lib.rs
+            let path = path.canonicalize().ok()?;
+            let vfs_file = vfs.load(&path);
+            vfs_file.map(|f| FileId(f.0))
+        };
+        for ws in workspaces.iter() {
+            crate_graph.extend(ws.to_crate_graph(
+                &default_cfg_options,
+                &extern_source_roots,
+                &proc_macro_client,
+                &mut load,
+            ));
+        }
         change.set_crate_graph(crate_graph);
 
         let flycheck = config.check.as_ref().and_then(|c| create_flycheck(&workspaces, c));


Test patch:
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs
index 1fe05c70c9..5af88b3684 100644
--- a/crates/ra_hir_ty/src/tests.rs
+++ b/crates/ra_hir_ty/src/tests.rs
@@ -6,7 +6,6 @@ mod patterns;
 mod traits;
 mod method_resolution;
 mod macros;
-mod display_source_code;
 
 use std::sync::Arc;
 
@@ -17,7 +16,7 @@ use hir_def::{
     item_scope::ItemScope,
     keys,
     nameres::CrateDefMap,
-    AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId, ModuleId,
+    AssocItemId, DefWithBodyId, LocalModuleId, Lookup, ModuleDefId,
 };
 use hir_expand::{db::AstDatabase, InFile};
 use insta::assert_snapshot;
@@ -38,18 +37,6 @@ use crate::{
 // update the snapshots.
 
 fn type_at_pos(db: &TestDB, pos: FilePosition) -> String {
-    type_at_pos_displayed(db, pos, |ty, _| ty.display(db).to_string())
-}
-
-fn displayed_source_at_pos(db: &TestDB, pos: FilePosition) -> String {
-    type_at_pos_displayed(db, pos, |ty, module_id| ty.display_source_code(db, module_id).unwrap())
-}
-
-fn type_at_pos_displayed(
-    db: &TestDB,
-    pos: FilePosition,
-    display_fn: impl FnOnce(&Ty, ModuleId) -> String,
-) -> String {
     let file = db.parse(pos.file_id).ok().unwrap();
     let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
     let fn_def = expr.syntax().ancestors().find_map(ast::FnDef::cast).unwrap();
@@ -62,7 +49,7 @@ fn type_at_pos_displayed(
     if let Some(expr_id) = source_map.node_expr(InFile::new(pos.file_id.into(), &expr)) {
         let infer = db.infer(func.into());
         let ty = &infer[expr_id];
-        return display_fn(ty, module);
+        return ty.display(db).to_string();
     }
     panic!("Can't find expression")
 }
diff --git a/crates/ra_hir_ty/src/tests/display_source_code.rs b/crates/ra_hir_ty/src/tests/display_source_code.rs
deleted file mode 100644
index ca17486152..0000000000
--- a/crates/ra_hir_ty/src/tests/display_source_code.rs
+++ /dev/null
@@ -1,23 +0,0 @@
-use super::displayed_source_at_pos;
-use crate::test_db::TestDB;
-use ra_db::fixture::WithFixture;
-
-#[test]
-fn qualify_path_to_submodule() {
-    let (db, pos) = TestDB::with_position(
-        r#"
-//- /main.rs
-
-mod foo {
-    pub struct Foo;
-}
-
-fn bar() {
-    let foo: foo::Foo = foo::Foo;
-    foo<|>
-}
-
-"#,
-    );
-    assert_eq!("foo::Foo", displayed_source_at_pos(&db, pos));
-}
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index b1e3c328f3..b13e13af2a 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -270,7 +270,7 @@ fn parse_fixture_checks_further_indented_metadata() {
 }
 
 #[test]
-fn parse_fixture_can_handle_dedented_first_line() {
+fn parse_fixture_can_handle_unindented_first_line() {
     let fixture = "//- /lib.rs
                    mod foo;
                    //- /foo.rs