Repository: rust-analyzer/rust-analyzer
Pull request #1374 (2019-06-04 07:32:07)

Implement `cargo lint` and fix some clippy errors
This creates a `cargo lint` command that runs clippy with certain lints disabled. I've also gone ahead and fixed some of the lint errors, although there are many more still to go.

cc #848 


Patch:
diff --git a/.cargo/config b/.cargo/config
index b12f407e6f..51ae33910b 100644
--- a/.cargo/config
+++ b/.cargo/config
@@ -12,6 +12,9 @@ install-code = "run --package tools --bin tools -- install-code"
 # Formats the full repository or installs the git hook to do it automatically.
 format       = "run --package tools --bin tools -- format"
 format-hook  = "run --package tools --bin tools -- format-hook"
+# Run clippy
+lint         = "run --package tools --bin tools -- lint"
+
 # Runs the fuzzing test suite (currently only parser)
 fuzz-tests   = "run --package tools --bin tools -- fuzz-tests"
 
diff --git a/Cargo.lock b/Cargo.lock
index 39d7c630a2..4dbe5679d8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1058,7 +1058,7 @@ dependencies = [
  "ra_syntax 0.1.0",
  "relative-path 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "salsa 0.12.1 (git+https://github.com/matklad/salsa?branch=strong-panic-safety)",
+ "salsa 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "test_utils 0.1.0",
 ]
 
@@ -1469,7 +1469,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 [[package]]
 name = "salsa"
 version = "0.12.1"
-source = "git+https://github.com/matklad/salsa?branch=strong-panic-safety#fcc7058e9cbdec838a3d9e6721a0da2892fe4ce1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "derive-new 0.5.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -1477,14 +1477,14 @@ dependencies = [
  "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "salsa-macros 0.12.1 (git+https://github.com/matklad/salsa?branch=strong-panic-safety)",
+ "salsa-macros 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
 name = "salsa-macros"
 version = "0.12.1"
-source = "git+https://github.com/matklad/salsa?branch=strong-panic-safety#fcc7058e9cbdec838a3d9e6721a0da2892fe4ce1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
  "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
  "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -2126,8 +2126,8 @@ dependencies = [
 "checksum rustc-hash 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7540fc8b0c49f096ee9c961cda096467dce8084bec6bdca2fc83895fd9b28cb8"
 "checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
 "checksum ryu 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "b96a9549dc8d48f2c283938303c4b5a77aa29bfbc5b54b084fb1630408899a8f"
-"checksum salsa 0.12.1 (git+https://github.com/matklad/salsa?branch=strong-panic-safety)" = "<none>"
-"checksum salsa-macros 0.12.1 (git+https://github.com/matklad/salsa?branch=strong-panic-safety)" = "<none>"
+"checksum salsa 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "6ccd6297ee190727cea6f8c81771b73a79bbfc6e320496775083c44dbff67263"
+"checksum salsa-macros 0.12.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b7f1e25ca2b995bdf032946174929d62156ffd57abd7ff88dc6f9bdeb5ac0c59"
 "checksum same-file 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "8f20c4be53a8a1ff4c1f1b2bd14570d2f634628709752f0702ecdd2b3f9a5267"
 "checksum scopeguard 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "94258f53601af11e6a49f722422f6e3425c52b06245a5cf9bc09908b174f5e27"
 "checksum scopeguard 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b42e15e59b18a828bbf5c58ea01debb36b9b096346de35d941dcb89009f24a0d"
diff --git a/Cargo.toml b/Cargo.toml
index 5106ea91d5..c5155e8996 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -6,4 +6,3 @@ incremental = true
 debug = true
 
 [patch.'crates-io']
-salsa = { git = "https://github.com/matklad/salsa", branch = "strong-panic-safety" }
\ No newline at end of file
diff --git a/crates/ra_assists/src/ast_editor.rs b/crates/ra_assists/src/ast_editor.rs
index cabb3d862f..de0529b328 100644
--- a/crates/ra_assists/src/ast_editor.rs
+++ b/crates/ra_assists/src/ast_editor.rs
@@ -212,21 +212,17 @@ impl AstEditor<ast::FnDef> {
     }
 
     pub fn strip_attrs_and_docs(&mut self) {
-        loop {
-            if let Some(start) = self
-                .ast()
-                .syntax()
-                .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,
-                };
-                self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty());
-            } else {
-                break;
-            }
+        while let Some(start) = self
+            .ast()
+            .syntax()
+            .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,
+            };
+            self.ast = self.replace_children(RangeInclusive::new(start, end), iter::empty());
         }
     }
 }
diff --git a/crates/ra_assists/src/auto_import.rs b/crates/ra_assists/src/auto_import.rs
index 1566cf1791..9617beb5c5 100644
--- a/crates/ra_assists/src/auto_import.rs
+++ b/crates/ra_assists/src/auto_import.rs
@@ -334,7 +334,7 @@ fn best_action_for_target<'b, 'a: 'b>(
         .filter_map(ast::UseItem::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(Some(a))
+            best.and_then(|best| Some(*ImportAction::better(&best, &a))).or_else(|| Some(a))
         });
 
     match best_action {
@@ -347,7 +347,7 @@ fn best_action_for_target<'b, 'a: 'b>(
             let anchor = container
                 .children()
                 .find(|n| n.range().start() < anchor.range().start())
-                .or(Some(anchor));
+                .or_else(|| Some(anchor));
 
             return ImportAction::add_new_use(anchor, false);
         }
diff --git a/crates/ra_assists/src/change_visibility.rs b/crates/ra_assists/src/change_visibility.rs
index 620f534b5d..4eb24d27f7 100644
--- a/crates/ra_assists/src/change_visibility.rs
+++ b/crates/ra_assists/src/change_visibility.rs
@@ -59,7 +59,7 @@ fn vis_offset(node: &SyntaxNode) -> TextUnit {
         })
         .next()
         .map(|it| it.range().start())
-        .unwrap_or(node.range().start())
+        .unwrap_or_else(|| node.range().start())
 }
 
 fn change_vis(mut ctx: AssistCtx<impl HirDatabase>, vis: &ast::Visibility) -> Option<Assist> {
diff --git a/crates/ra_assists/src/introduce_variable.rs b/crates/ra_assists/src/introduce_variable.rs
index fb7333c8c5..28467d3413 100644
--- a/crates/ra_assists/src/introduce_variable.rs
+++ b/crates/ra_assists/src/introduce_variable.rs
@@ -57,9 +57,9 @@ pub(crate) fn introduce_variable(mut ctx: AssistCtx<impl HirDatabase>) -> Option
             if text.starts_with("\r\n") {
                 buf.push_str("\r\n");
                 buf.push_str(text.trim_start_matches("\r\n"));
-            } else if text.starts_with("\n") {
+            } else if text.starts_with('\n') {
                 buf.push_str("\n");
-                buf.push_str(text.trim_start_matches("\n"));
+                buf.push_str(text.trim_start_matches('\n'));
             } else {
                 buf.push_str(text);
             }
diff --git a/crates/ra_batch/src/lib.rs b/crates/ra_batch/src/lib.rs
index a4a8462de3..a445dcb4d4 100644
--- a/crates/ra_batch/src/lib.rs
+++ b/crates/ra_batch/src/lib.rs
@@ -34,10 +34,10 @@ impl salsa::Database for BatchDatabase {
 }
 
 fn vfs_file_to_id(f: ra_vfs::VfsFile) -> FileId {
-    FileId(f.0.into())
+    FileId(f.0)
 }
 fn vfs_root_to_id(r: ra_vfs::VfsRoot) -> SourceRootId {
-    SourceRootId(r.0.into())
+    SourceRootId(r.0)
 }
 
 impl BatchDatabase {
diff --git a/crates/ra_cli/src/analysis_stats.rs b/crates/ra_cli/src/analysis_stats.rs
index b481ace9e8..8bb524ce30 100644
--- a/crates/ra_cli/src/analysis_stats.rs
+++ b/crates/ra_cli/src/analysis_stats.rs
@@ -31,18 +31,16 @@ pub fn run(verbose: bool, path: &str, only: Option<&str>) -> Result<()> {
 
             for decl in module.declarations(&db) {
                 num_decls += 1;
-                match decl {
-                    ModuleDef::Function(f) => funcs.push(f),
-                    _ => {}
+                if let ModuleDef::Function(f) = decl {
+                    funcs.push(f);
                 }
             }
 
             for impl_block in module.impl_blocks(&db) {
                 for item in impl_block.items(&db) {
                     num_decls += 1;
-                    match item {
-                        ImplItem::Method(f) => funcs.push(f),
-                        _ => {}
+                    if let ImplItem::Method(f) = item {
+                        funcs.push(f);
                     }
                 }
             }
diff --git a/crates/ra_hir/src/adt.rs b/crates/ra_hir/src/adt.rs
index 45a12dd4df..38ff1d6f63 100644
--- a/crates/ra_hir/src/adt.rs
+++ b/crates/ra_hir/src/adt.rs
@@ -36,7 +36,7 @@ impl AdtDef {
 
 impl Struct {
     pub(crate) fn variant_data(&self, db: &impl DefDatabase) -> Arc<VariantData> {
-        db.struct_data((*self).into()).variant_data.clone()
+        db.struct_data(*self).variant_data.clone()
     }
 }
 
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 9c02b3995d..6ee6bd627d 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -281,9 +281,8 @@ impl Module {
 
         for impl_block in self.impl_blocks(db) {
             for item in impl_block.items(db) {
-                match item {
-                    crate::ImplItem::Method(f) => f.diagnostics(db, sink),
-                    _ => (),
+                if let crate::ImplItem::Method(f) = item {
+                    f.diagnostics(db, sink);
                 }
             }
         }
diff --git a/crates/ra_hir/src/expr/validation.rs b/crates/ra_hir/src/expr/validation.rs
index 2816144a74..a1b2641da1 100644
--- a/crates/ra_hir/src/expr/validation.rs
+++ b/crates/ra_hir/src/expr/validation.rs
@@ -31,11 +31,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
     pub(crate) fn validate_body(&mut self, db: &impl HirDatabase) {
         let body = self.func.body(db);
         for e in body.exprs() {
-            match e {
-                (id, Expr::StructLit { path, fields, spread }) => {
-                    self.validate_struct_literal(id, path, fields, spread, db)
-                }
-                _ => (),
+            if let (id, Expr::StructLit { path, fields, spread }) = e {
+                self.validate_struct_literal(id, path, fields, spread, db);
             }
         }
     }
@@ -44,7 +41,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
         &mut self,
         id: ExprId,
         _path: &Option<Path>,
-        fields: &Vec<StructLitField>,
+        fields: &[StructLitField],
         spread: &Option<ExprId>,
         db: &impl HirDatabase,
     ) {
@@ -57,7 +54,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
             _ => return,
         };
 
-        let lit_fields: FxHashSet<_> = fields.into_iter().map(|f| &f.name).collect();
+        let lit_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
         let missed_fields: Vec<Name> = struct_def
             .fields(db)
             .iter()
diff --git a/crates/ra_hir/src/impl_block.rs b/crates/ra_hir/src/impl_block.rs
index ba90e67e9a..a0d3b33fe6 100644
--- a/crates/ra_hir/src/impl_block.rs
+++ b/crates/ra_hir/src/impl_block.rs
@@ -202,7 +202,6 @@ impl ModuleImplBlocks {
         };
 
         let (file_id, module_source) = m.module.definition_source(db);
-        let file_id: HirFileId = file_id.into();
         let node = match &module_source {
             ModuleSource::SourceFile(node) => node.syntax(),
             ModuleSource::Module(node) => {
diff --git a/crates/ra_hir/src/lang_item.rs b/crates/ra_hir/src/lang_item.rs
index 4cacaeba43..684fbc0685 100644
--- a/crates/ra_hir/src/lang_item.rs
+++ b/crates/ra_hir/src/lang_item.rs
@@ -95,7 +95,7 @@ impl LangItems {
                 .nth(0);
             if let Some(lang_item_name) = lang_item_name {
                 let imp = ImplBlock::from_id(*module, impl_id);
-                self.items.entry(lang_item_name).or_insert(LangItemTarget::ImplBlock(imp));
+                self.items.entry(lang_item_name).or_insert_with(|| LangItemTarget::ImplBlock(imp));
             }
         }
 
diff --git a/crates/ra_hir/src/nameres.rs b/crates/ra_hir/src/nameres.rs
index d649aa8209..8b798d6c9a 100644
--- a/crates/ra_hir/src/nameres.rs
+++ b/crates/ra_hir/src/nameres.rs
@@ -332,7 +332,8 @@ impl CrateDefMap {
         let name = path.expand_macro_expr()?;
         // search local first
         // FIXME: Remove public_macros check when we have a correct local_macors implementation
-        let local = self.public_macros.get(&name).or(self.local_macros.get(&name)).map(|it| *it);
+        let local =
+            self.public_macros.get(&name).or_else(|| self.local_macros.get(&name)).map(|it| *it);
         if local.is_some() {
             return local;
         }
@@ -405,7 +406,7 @@ impl CrateDefMap {
         };
 
         for (i, segment) in segments {
-            let curr = match curr_per_ns.as_ref().left().map_or(None, |m| m.as_ref().take_types()) {
+            let curr = match curr_per_ns.as_ref().left().and_then(|m| m.as_ref().take_types()) {
                 Some(r) => r,
                 None => {
                     // we still have path segments left, but the path so far
@@ -421,10 +422,8 @@ impl CrateDefMap {
             curr_per_ns = match curr {
                 ModuleDef::Module(module) => {
                     if module.krate != self.krate {
-                        let path = Path {
-                            segments: path.segments[i..].iter().cloned().collect(),
-                            kind: PathKind::Self_,
-                        };
+                        let path =
+                            Path { segments: path.segments[i..].to_vec(), kind: PathKind::Self_ };
                         log::debug!("resolving {:?} in other crate", path);
                         let defp_map = db.crate_def_map(module.krate);
                         let (def, s) =
@@ -468,7 +467,7 @@ impl CrateDefMap {
                     );
 
                     return ResolvePathResult::with(
-                        Either::Left(PerNs::types((*s).into())),
+                        Either::Left(PerNs::types(*s)),
                         ReachedFixedPoint::Yes,
                         Some(i),
                     );
@@ -479,8 +478,10 @@ impl CrateDefMap {
     }
 
     fn resolve_name_in_crate_root_or_extern_prelude(&self, name: &Name) -> ItemOrMacro {
-        let from_crate_root =
-            self[self.root].scope.get_item_or_macro(name).unwrap_or(Either::Left(PerNs::none()));
+        let from_crate_root = self[self.root]
+            .scope
+            .get_item_or_macro(name)
+            .unwrap_or_else(|| Either::Left(PerNs::none()));
         let from_extern_prelude = self.resolve_name_in_extern_prelude(name);
 
         or(from_crate_root, Either::Left(from_extern_prelude))
@@ -505,8 +506,10 @@ impl CrateDefMap {
         //  - current module / scope
         //  - extern prelude
         //  - std prelude
-        let from_scope =
-            self[module].scope.get_item_or_macro(name).unwrap_or(Either::Left(PerNs::none()));;
+        let from_scope = self[module]
+            .scope
+            .get_item_or_macro(name)
+            .unwrap_or_else(|| Either::Left(PerNs::none()));;
         let from_extern_prelude =
             self.extern_prelude.get(name).map_or(PerNs::none(), |&it| PerNs::types(it));
         let from_prelude = self.resolve_in_prelude(db, name);
@@ -525,7 +528,7 @@ impl CrateDefMap {
             } else {
                 db.crate_def_map(prelude.krate)[prelude.module_id].scope.get_item_or_macro(name)
             };
-            resolution.unwrap_or(Either::Left(PerNs::none()))
+            resolution.unwrap_or_else(|| Either::Left(PerNs::none()))
         } else {
             Either::Left(PerNs::none())
         }
diff --git a/crates/ra_hir/src/nameres/collector.rs b/crates/ra_hir/src/nameres/collector.rs
index 693c3fe8e8..3bfef799da 100644
--- a/crates/ra_hir/src/nameres/collector.rs
+++ b/crates/ra_hir/src/nameres/collector.rs
@@ -556,7 +556,7 @@ where
 
     fn define_def(&mut self, def: &raw::DefData) {
         let module = Module { krate: self.def_collector.def_map.krate, module_id: self.module_id };
-        let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id.into());
+        let ctx = LocationCtx::new(self.def_collector.db, module, self.file_id);
 
         macro_rules! def {
             ($kind:ident, $ast_id:ident) => {
diff --git a/crates/ra_hir/src/nameres/raw.rs b/crates/ra_hir/src/nameres/raw.rs
index 21935dbb9d..a0afe282c1 100644
--- a/crates/ra_hir/src/nameres/raw.rs
+++ b/crates/ra_hir/src/nameres/raw.rs
@@ -69,7 +69,7 @@ impl RawItems {
     ) -> (Arc<RawItems>, Arc<ImportSourceMap>) {
         let mut collector = RawItemsCollector {
             raw_items: RawItems::default(),
-            source_ast_id_map: db.ast_id_map(file_id.into()),
+            source_ast_id_map: db.ast_id_map(file_id),
             source_map: ImportSourceMap::default(),
         };
         if let Some(node) = db.parse_or_expand(file_id) {
diff --git a/crates/ra_hir/src/path.rs b/crates/ra_hir/src/path.rs
index 1b129c752b..67afd5027a 100644
--- a/crates/ra_hir/src/path.rs
+++ b/crates/ra_hir/src/path.rs
@@ -116,7 +116,7 @@ impl Path {
 
     /// `true` if this path is just a standalone `self`
     pub fn is_self(&self) -> bool {
-        self.kind == PathKind::Self_ && self.segments.len() == 0
+        self.kind == PathKind::Self_ && self.segments.is_empty()
     }
 
     /// If this path is a single identifier, like `foo`, return its name.
@@ -140,7 +140,7 @@ impl GenericArgs {
             args.push(GenericArg::Type(type_ref));
         }
         // lifetimes and assoc type args ignored for now
-        if args.len() > 0 {
+        if !args.is_empty() {
             Some(GenericArgs { args })
         } else {
             None
diff --git a/crates/ra_hir/src/source_binder.rs b/crates/ra_hir/src/source_binder.rs
index 75ed2de6cd..6a57996229 100644
--- a/crates/ra_hir/src/source_binder.rs
+++ b/crates/ra_hir/src/source_binder.rs
@@ -48,8 +48,8 @@ pub fn module_from_declaration(
 pub fn module_from_position(db: &impl HirDatabase, position: FilePosition) -> Option<Module> {
     let file = db.parse(position.file_id).tree;
     match find_node_at_offset::<ast::Module>(file.syntax(), position.offset) {
-        Some(m) if !m.has_semi() => module_from_inline(db, position.file_id.into(), m),
-        _ => module_from_file_id(db, position.file_id.into()),
+        Some(m) if !m.has_semi() => module_from_inline(db, position.file_id, m),
+        _ => module_from_file_id(db, position.file_id),
     }
 }
 
@@ -72,9 +72,9 @@ pub fn module_from_child_node(
     child: &SyntaxNode,
 ) -> Option<Module> {
     if let Some(m) = child.ancestors().filter_map(ast::Module::cast).find(|it| !it.has_semi()) {
-        module_from_inline(db, file_id.into(), m)
+        module_from_inline(db, file_id, m)
     } else {
-        module_from_file_id(db, file_id.into())
+        module_from_file_id(db, file_id)
     }
 }
 
@@ -99,14 +99,12 @@ pub fn struct_from_module(
     struct_def: &ast::StructDef,
 ) -> Struct {
     let (file_id, _) = module.definition_source(db);
-    let file_id = file_id.into();
     let ctx = LocationCtx::new(db, module, file_id);
     Struct { id: ctx.to_def(struct_def) }
 }
 
 pub fn enum_from_module(db: &impl HirDatabase, module: Module, enum_def: &ast::EnumDef) -> Enum {
     let (file_id, _) = module.definition_source(db);
-    let file_id = file_id.into();
     let ctx = LocationCtx::new(db, module, file_id);
     Enum { id: ctx.to_def(enum_def) }
 }
@@ -117,7 +115,6 @@ pub fn trait_from_module(
     trait_def: &ast::TraitDef,
 ) -> Trait {
     let (file_id, _) = module.definition_source(db);
-    let file_id = file_id.into();
     let ctx = LocationCtx::new(db, module, file_id);
     Trait { id: ctx.to_def(trait_def) }
 }
diff --git a/crates/ra_hir/src/traits.rs b/crates/ra_hir/src/traits.rs
index 2a7c2b791f..967654e97e 100644
--- a/crates/ra_hir/src/traits.rs
+++ b/crates/ra_hir/src/traits.rs
@@ -77,13 +77,10 @@ impl TraitItemsIndex {
     pub(crate) fn trait_items_index(db: &impl DefDatabase, module: Module) -> TraitItemsIndex {
         let mut index = TraitItemsIndex { traits_by_def: FxHashMap::default() };
         for decl in module.declarations(db) {
-            match decl {
-                crate::ModuleDef::Trait(tr) => {
-                    for item in tr.trait_data(db).items() {
-                        index.traits_by_def.insert(*item, tr);
-                    }
+            if let crate::ModuleDef::Trait(tr) = decl {
+                for item in tr.trait_data(db).items() {
+                    index.traits_by_def.insert(*item, tr);
                 }
-                _ => {}
             }
         }
         index
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 76d34c12b6..4a37e02684 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -451,7 +451,7 @@ impl Ty {
     /// Substitutes `Ty::Bound` vars (as opposed to type parameters).
     pub fn subst_bound_vars(self, substs: &Substs) -> Ty {
         self.fold(&mut |ty| match ty {
-            Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or(Ty::Bound(idx)),
+            Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)),
             ty => ty,
         })
     }
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index e8ae33eadc..905fe9f0e3 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -462,7 +462,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
         let mut resolved =
             if remaining_index.is_none() { def.take_values()? } else { def.take_types()? };
 
-        let remaining_index = remaining_index.unwrap_or(path.segments.len());
+        let remaining_index = remaining_index.unwrap_or_else(|| path.segments.len());
         let mut actual_def_ty: Option<Ty> = None;
 
         let krate = resolver.krate()?;
@@ -539,7 +539,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                 }
             })?;
 
-            resolved = Resolution::Def(item.into());
+            resolved = Resolution::Def(item);
         }
 
         match resolved {
@@ -762,7 +762,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
                     _ => &Ty::Unknown,
                 };
                 let subty = self.infer_pat(*pat, expectation, default_bm);
-                Ty::apply_one(TypeCtor::Ref(*mutability), subty.into())
+                Ty::apply_one(TypeCtor::Ref(*mutability), subty)
             }
             Pat::TupleStruct { path: ref p, args: ref subpats } => {
                 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
@@ -790,7 +790,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
 
                 let bound_ty = match mode {
                     BindingMode::Ref(mutability) => {
-                        Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone().into())
+                        Ty::apply_one(TypeCtor::Ref(mutability), inner_ty.clone())
                     }
                     BindingMode::Move => inner_ty.clone(),
                 };
@@ -848,28 +848,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
     }
 
     fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
-        match callable_ty {
-            Ty::Apply(a_ty) => match a_ty.ctor {
-                TypeCtor::FnDef(def) => {
-                    // add obligation for trait implementation, if this is a trait method
-                    // FIXME also register obligations from where clauses from the trait or impl and method
-                    match def {
-                        CallableDef::Function(f) => {
-                            if let Some(trait_) = f.parent_trait(self.db) {
-                                // construct a TraitDef
-                                let substs = a_ty.parameters.prefix(
-                                    trait_.generic_params(self.db).count_params_including_parent(),
-                                );
-                                self.obligations
-                                    .push(Obligation::Trait(TraitRef { trait_, substs }));
-                            }
+        if let Ty::Apply(a_ty) = callable_ty {
+            if let TypeCtor::FnDef(def) = a_ty.ctor {
+                // add obligation for trait implementation, if this is a trait method
+                // FIXME also register obligations from where clauses from the trait or impl and method
+                match def {
+                    CallableDef::Function(f) => {
+                        if let Some(trait_) = f.parent_trait(self.db) {
+                            // construct a TraitDef
+                            let substs = a_ty.parameters.prefix(
+                                trait_.generic_params(self.db).count_params_including_parent(),
+                            );
+                            self.obligations.push(Obligation::Trait(TraitRef { trait_, substs }));
                         }
-                        CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {}
                     }
+                    CallableDef::Struct(_) | CallableDef::EnumVariant(_) => {}
                 }
-                _ => {}
-            },
-            _ => {}
+            }
         }
     }
 
@@ -1049,7 +1044,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
             Expr::StructLit { path, fields, spread } => {
                 let (ty, def_id) = self.resolve_variant(path.as_ref());
                 let substs = ty.substs().unwrap_or_else(Substs::empty);
-                for (field_idx, field) in fields.into_iter().enumerate() {
+                for (field_idx, field) in fields.iter().enumerate() {
                     let field_ty = def_id
                         .and_then(|it| match it.field(self.db, &field.name) {
                             Some(field) => Some(field),
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs
index 34817a5ecd..646e58aa91 100644
--- a/crates/ra_hir/src/ty/method_resolution.rs
+++ b/crates/ra_hir/src/ty/method_resolution.rs
@@ -192,23 +192,20 @@ fn iterate_trait_method_candidates<T>(
         // iteration
         let mut known_implemented = false;
         for item in data.items() {
-            match item {
-                &TraitItem::Function(m) => {
-                    let sig = m.signature(db);
-                    if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() {
-                        if !known_implemented {
-                            let trait_ref = canonical_trait_ref(db, t, ty.clone());
-                            if db.implements(krate, trait_ref).is_none() {
-                                continue 'traits;
-                            }
-                        }
-                        known_implemented = true;
-                        if let Some(result) = callback(&ty.value, m) {
-                            return Some(result);
+            if let TraitItem::Function(m) = *item {
+                let sig = m.signature(db);
+                if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() {
+                    if !known_implemented {
+                        let trait_ref = canonical_trait_ref(db, t, ty.clone());
+                        if db.implements(krate, trait_ref).is_none() {
+                            continue 'traits;
                         }
                     }
+                    known_implemented = true;
+                    if let Some(result) = callback(&ty.value, m) {
+                        return Some(result);
+                    }
                 }
-                _ => {}
             }
         }
     }
@@ -230,16 +227,13 @@ fn iterate_inherent_methods<T>(
 
     for impl_block in impls.lookup_impl_blocks(&ty.value) {
         for item in impl_block.items(db) {
-            match item {
-                ImplItem::Method(f) => {
-                    let sig = f.signature(db);
-                    if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() {
-                        if let Some(result) = callback(&ty.value, f) {
-                            return Some(result);
-                        }
+            if let ImplItem::Method(f) = item {
+                let sig = f.signature(db);
+                if name.map_or(true, |name| sig.name() == name) && sig.has_self_param() {
+                    if let Some(result) = callback(&ty.value, f) {
+                        return Some(result);
                     }
                 }
-                _ => {}
             }
         }
     }
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 78440b258b..1e4806db0e 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -211,13 +211,10 @@ fn convert_where_clauses(
             // anyway), otherwise Chalk can easily get into slow situations
             return vec![pred.clone().subst(substs).to_chalk(db)];
         }
-        match pred {
-            GenericPredicate::Implemented(trait_ref) => {
-                if blacklisted_trait(db, trait_ref.trait_) {
-                    continue;
-                }
+        if let GenericPredicate::Implemented(trait_ref) = pred {
+            if blacklisted_trait(db, trait_ref.trait_) {
+                continue;
             }
-            _ => {}
         }
         result.push(pred.clone().subst(substs).to_chalk(db));
     }
diff --git a/crates/ra_ide_api/src/call_info.rs b/crates/ra_ide_api/src/call_info.rs
index 5d43282fd4..bd08e183db 100644
--- a/crates/ra_ide_api/src/call_info.rs
+++ b/crates/ra_ide_api/src/call_info.rs
@@ -21,8 +21,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
     let function = match calling_node {
         FnCallNode::CallExpr(expr) => {
             //FIXME: apply subst
-            let (callable_def, _subst) =
-                analyzer.type_of(db, expr.expr()?.into())?.as_callable()?;
+            let (callable_def, _subst) = analyzer.type_of(db, expr.expr()?)?.as_callable()?;
             match callable_def {
                 hir::CallableDef::Function(it) => it,
                 //FIXME: handle other callables
@@ -64,7 +63,7 @@ pub(crate) fn call_info(db: &RootDatabase, position: FilePosition) -> Option<Cal
 
             // If we are in a method account for `self`
             if has_self {
-                param = param + 1;
+                param += 1;
             }
 
             call_info.active_parameter = Some(param);
diff --git a/crates/ra_ide_api/src/completion/complete_dot.rs b/crates/ra_ide_api/src/completion/complete_dot.rs
index 5bf289c630..0822a0e7ec 100644
--- a/crates/ra_ide_api/src/completion/complete_dot.rs
+++ b/crates/ra_ide_api/src/completion/complete_dot.rs
@@ -16,8 +16,8 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) {
 
 fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty) {
     for receiver in receiver.autoderef(ctx.db) {
-        match receiver {
-            Ty::Apply(a_ty) => match a_ty.ctor {
+        if let Ty::Apply(a_ty) = receiver {
+            match a_ty.ctor {
                 TypeCtor::Adt(AdtDef::Struct(s)) => {
                     for field in s.fields(ctx.db) {
                         acc.add_field(ctx, field, &a_ty.parameters);
@@ -30,8 +30,7 @@ fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: Ty)
                     }
                 }
                 _ => {}
-            },
-            _ => {}
+            }
         };
     }
 }
diff --git a/crates/ra_ide_api/src/completion/complete_pattern.rs b/crates/ra_ide_api/src/completion/complete_pattern.rs
index 74833a7565..6655a05a7c 100644
--- a/crates/ra_ide_api/src/completion/complete_pattern.rs
+++ b/crates/ra_ide_api/src/completion/complete_pattern.rs
@@ -10,7 +10,7 @@ pub(super) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) {
     let names = ctx.analyzer.all_names(ctx.db);
     for (name, res) in names.into_iter() {
         let r = res.as_ref();
-        let def = match r.take_types().or(r.take_values()) {
+        let def = match r.take_types().or_else(|| r.take_values()) {
             Some(hir::Resolution::Def(def)) => def,
             _ => continue,
         };
diff --git a/crates/ra_ide_api/src/completion/complete_scope.rs b/crates/ra_ide_api/src/completion/complete_scope.rs
index 2473e58b40..0f8cfaae80 100644
--- a/crates/ra_ide_api/src/completion/complete_scope.rs
+++ b/crates/ra_ide_api/src/completion/complete_scope.rs
@@ -49,7 +49,7 @@ pub(super) fn complete_scope(acc: &mut Completions, ctx: &CompletionContext) {
     }
 }
 
-fn build_import_label(name: &str, path: &Vec<SmolStr>) -> String {
+fn build_import_label(name: &str, path: &[SmolStr]) -> String {
     let mut buf = String::with_capacity(64);
     buf.push_str(name);
     buf.push_str(" (");
@@ -58,7 +58,7 @@ fn build_import_label(name: &str, path: &Vec<SmolStr>) -> String {
     buf
 }
 
-fn fmt_import_path(path: &Vec<SmolStr>, buf: &mut String) {
+fn fmt_import_path(path: &[SmolStr], buf: &mut String) {
     let mut segments = path.iter();
     if let Some(s) = segments.next() {
         buf.push_str(&s);
diff --git a/crates/ra_ide_api/src/diagnostics.rs b/crates/ra_ide_api/src/diagnostics.rs
index a2a8c1e4f7..35b3d77df3 100644
--- a/crates/ra_ide_api/src/diagnostics.rs
+++ b/crates/ra_ide_api/src/diagnostics.rs
@@ -109,7 +109,7 @@ fn check_unnecessary_braces_in_use_statement(
 
         acc.push(Diagnostic {
             range,
-            message: format!("Unnecessary braces in use statement"),
+            message: "Unnecessary braces in use statement".to_string(),
             severity: Severity::WeakWarning,
             fix: Some(SourceChange::source_file_edit(
                 "Remove unnecessary braces",
@@ -155,7 +155,7 @@ fn check_struct_shorthand_initialization(
 
                 acc.push(Diagnostic {
                     range: named_field.syntax().range(),
-                    message: format!("Shorthand struct initialization"),
+                    message: "Shorthand struct initialization".to_string(),
                     severity: Severity::WeakWarning,
                     fix: Some(SourceChange::source_file_edit(
                         "use struct shorthand initialization",
diff --git a/crates/ra_ide_api/src/extend_selection.rs b/crates/ra_ide_api/src/extend_selection.rs
index 00c445310e..a713b762cf 100644
--- a/crates/ra_ide_api/src/extend_selection.rs
+++ b/crates/ra_ide_api/src/extend_selection.rs
@@ -95,7 +95,7 @@ fn extend_single_word_in_comment_or_string(
     }
 
     let start_idx = before.rfind(non_word_char)? as u32;
-    let end_idx = after.find(non_word_char).unwrap_or(after.len()) as u32;
+    let end_idx = after.find(non_word_char).unwrap_or_else(|| after.len()) as u32;
 
     let from: TextUnit = (start_idx + 1).into();
     let to: TextUnit = (cursor_position + end_idx).into();
diff --git a/crates/ra_ide_api/src/folding_ranges.rs b/crates/ra_ide_api/src/folding_ranges.rs
index b50bbee38b..4400ff2323 100644
--- a/crates/ra_ide_api/src/folding_ranges.rs
+++ b/crates/ra_ide_api/src/folding_ranges.rs
@@ -205,7 +205,7 @@ mod tests {
             "The amount of fold kinds is different than the expected amount"
         );
         for ((fold, range), fold_kind) in
-            folds.into_iter().zip(ranges.into_iter()).zip(fold_kinds.into_iter())
+            folds.iter().zip(ranges.into_iter()).zip(fold_kinds.iter())
         {
             assert_eq!(fold.range.start(), range.start());
             assert_eq!(fold.range.end(), range.end());
diff --git a/crates/ra_ide_api/src/hover.rs b/crates/ra_ide_api/src/hover.rs
index 9c35db2a4b..f56965ef5a 100644
--- a/crates/ra_ide_api/src/hover.rs
+++ b/crates/ra_ide_api/src/hover.rs
@@ -18,6 +18,12 @@ pub struct HoverResult {
     exact: bool,
 }
 
+impl Default for HoverResult {
+    fn default() -> Self {
+        HoverResult::new()
+    }
+}
+
 impl HoverResult {
     pub fn new() -> HoverResult {
         HoverResult {
diff --git a/crates/ra_ide_api/src/line_index.rs b/crates/ra_ide_api/src/line_index.rs
index fd33d67678..087dfafed8 100644
--- a/crates/ra_ide_api/src/line_index.rs
+++ b/crates/ra_ide_api/src/line_index.rs
@@ -41,7 +41,7 @@ impl LineIndex {
                 newlines.push(curr_row);
 
                 // Save any utf-16 characters seen in the previous line
-                if utf16_chars.len() > 0 {
+                if !utf16_chars.is_empty() {
                     utf16_lines.insert(line, utf16_chars);
                     utf16_chars = Vec::new();
                 }
@@ -61,7 +61,7 @@ impl LineIndex {
         }
 
         // Save any utf-16 characters seen in the last line
-        if utf16_chars.len() > 0 {
+        if !utf16_chars.is_empty() {
             utf16_lines.insert(line, utf16_chars);
         }
 
diff --git a/crates/ra_ide_api/src/line_index_utils.rs b/crates/ra_ide_api/src/line_index_utils.rs
index 799a920ad7..a03467011d 100644
--- a/crates/ra_ide_api/src/line_index_utils.rs
+++ b/crates/ra_ide_api/src/line_index_utils.rs
@@ -133,9 +133,9 @@ impl<'a> Edits<'a> {
     }
 
     fn next_steps(&mut self, step: &Step) -> NextSteps {
-        let step_pos = match step {
-            &Step::Newline(n) => n,
-            &Step::Utf16Char(r) => r.end(),
+        let step_pos = match *step {
+            Step::Newline(n) => n,
+            Step::Utf16Char(r) => r.end(),
         };
         let res = match &mut self.current {
             Some(edit) => {
@@ -181,9 +181,9 @@ impl<'a> Edits<'a> {
         if self.acc_diff == 0 {
             x.clone()
         } else {
-            match x {
-                &Step::Newline(n) => Step::Newline(self.translate(n)),
-                &Step::Utf16Char(r) => Step::Utf16Char(self.translate_range(r)),
+            match *x {
+                Step::Newline(n) => Step::Newline(self.translate(n)),
+                Step::Utf16Char(r) => Step::Utf16Char(self.translate_range(r)),
             }
         }
     }
diff --git a/crates/ra_ide_api/src/typing.rs b/crates/ra_ide_api/src/typing.rs
index 63bc0cf88c..3e35d83523 100644
--- a/crates/ra_ide_api/src/typing.rs
+++ b/crates/ra_ide_api/src/typing.rs
@@ -110,7 +110,7 @@ pub(crate) fn on_dot_typed(db: &RootDatabase, position: FilePosition) -> Option<
     let mut edit = TextEditBuilder::default();
     edit.replace(
         TextRange::from_to(position.offset - current_indent_len, position.offset),
-        target_indent.into(),
+        target_indent,
     );
 
     let res = SourceChange::source_file_edit_from("reindent dot", position.file_id, edit.finish())
diff --git a/crates/ra_lsp_server/src/cargo_target_spec.rs b/crates/ra_lsp_server/src/cargo_target_spec.rs
index 7423611555..082ac8609c 100644
--- a/crates/ra_lsp_server/src/cargo_target_spec.rs
+++ b/crates/ra_lsp_server/src/cargo_target_spec.rs
@@ -64,7 +64,7 @@ impl CargoTargetSpec {
             None => return Ok(None),
         };
         let file_id = world.analysis().crate_root(crate_id)?;
-        let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0.into()));
+        let path = world.vfs.read().file2path(ra_vfs::VfsFile(file_id.0));
         let res = world.workspaces.iter().find_map(|ws| match ws {
             project_model::ProjectWorkspace::Cargo { cargo, .. } => {
                 let tgt = cargo.target_by_root(&path)?;
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index b0b70df5c8..a0df32dde6 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -49,7 +49,7 @@ fn main_inner() -> Result<()> {
         let opts = params
             .initialization_options
             .and_then(|v| InitializationOptions::deserialize(v).ok())
-            .unwrap_or(InitializationOptions::default());
+            .unwrap_or_default();
 
         ra_lsp_server::main_loop(workspace_roots, opts, r, s)
     })?;
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 6080a3a4e6..090fb9b1b0 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -384,7 +384,7 @@ fn on_notification(
             if let Some(file_id) =
                 state.vfs.write().add_file_overlay(&path, params.text_document.text)
             {
-                subs.add_sub(FileId(file_id.0.into()));
+                subs.add_sub(FileId(file_id.0));
             }
             return Ok(());
         }
@@ -406,7 +406,7 @@ fn on_notification(
             let uri = params.text_document.uri;
             let path = uri.to_file_path().map_err(|()| format_err!("invalid uri: {}", uri))?;
             if let Some(file_id) = state.vfs.write().remove_file_overlay(path.as_path()) {
-                subs.remove_sub(FileId(file_id.0.into()));
+                subs.remove_sub(FileId(file_id.0));
             }
             let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() };
             let not = RawNotification::new::<req::PublishDiagnostics>(&params);
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index e0d2f63061..cd8df4fdba 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -60,14 +60,14 @@ impl WorldState {
         for r in vfs_roots {
             let vfs_root_path = vfs.root2path(r);
             let is_local = folder_roots.iter().any(|it| vfs_root_path.starts_with(it));
-            change.add_root(SourceRootId(r.0.into()), is_local);
+            change.add_root(SourceRootId(r.0), is_local);
         }
 
         // Create crate graph from all the workspaces
         let mut crate_graph = CrateGraph::default();
         let mut load = |path: &std::path::Path| {
             let vfs_file = vfs.load(path);
-            vfs_file.map(|f| FileId(f.0.into()))
+            vfs_file.map(|f| FileId(f.0))
         };
         for ws in workspaces.iter() {
             crate_graph.extend(ws.to_crate_graph(&mut load));
@@ -105,29 +105,24 @@ impl WorldState {
                     if is_local {
                         self.roots_to_scan -= 1;
                         for (file, path, text) in files {
-                            change.add_file(
-                                SourceRootId(root.0.into()),
-                                FileId(file.0.into()),
-                                path,
-                                text,
-                            );
+                            change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
                         }
                     } else {
                         let files = files
                             .into_iter()
-                            .map(|(vfsfile, path, text)| (FileId(vfsfile.0.into()), path, text))
+                            .map(|(vfsfile, path, text)| (FileId(vfsfile.0), path, text))
                             .collect();
-                        libs.push((SourceRootId(root.0.into()), files));
+                        libs.push((SourceRootId(root.0), files));
                     }
                 }
                 VfsChange::AddFile { root, file, path, text } => {
-                    change.add_file(SourceRootId(root.0.into()), FileId(file.0.into()), path, text);
+                    change.add_file(SourceRootId(root.0), FileId(file.0), path, text);
                 }
                 VfsChange::RemoveFile { root, file, path } => {
-                    change.remove_file(SourceRootId(root.0.into()), FileId(file.0.into()), path)
+                    change.remove_file(SourceRootId(root.0), FileId(file.0), path)
                 }
                 VfsChange::ChangeFile { file, text } => {
-                    change.change_file(FileId(file.0.into()), text);
+                    change.change_file(FileId(file.0), text);
                 }
             }
         }
@@ -178,18 +173,18 @@ impl WorldSnapshot {
                 message: "Rust file outside current workspace is not supported yet.".to_string(),
             })
         })?;
-        Ok(FileId(file.0.into()))
+        Ok(FileId(file.0))
     }
 
     pub fn file_id_to_uri(&self, id: FileId) -> Result<Url> {
-        let path = self.vfs.read().file2path(VfsFile(id.0.into()));
+        let path = self.vfs.read().file2path(VfsFile(id.0));
         let url = Url::from_file_path(&path)
             .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
         Ok(url)
     }
 
     pub fn path_to_uri(&self, root: SourceRootId, path: &RelativePathBuf) -> Result<Url> {
-        let base = self.vfs.read().root2path(VfsRoot(root.0.into()));
+        let base = self.vfs.read().root2path(VfsRoot(root.0));
         let path = path.to_path(base);
         let url = Url::from_file_path(&path)
             .map_err(|_| format_err!("can't convert path to url: {}", path.display()))?;
@@ -212,7 +207,7 @@ impl WorldSnapshot {
     }
 
     pub fn workspace_root_for(&self, file_id: FileId) -> Option<&Path> {
-        let path = self.vfs.read().file2path(VfsFile(file_id.0.into()));
+        let path = self.vfs.read().file2path(VfsFile(file_id.0));
         self.workspaces.iter().find_map(|ws| ws.workspace_root_for(&path))
     }
 }
diff --git a/crates/ra_mbe/src/mbe_expander.rs b/crates/ra_mbe/src/mbe_expander.rs
index a0bd0c5f88..55a6ecf587 100644
--- a/crates/ra_mbe/src/mbe_expander.rs
+++ b/crates/ra_mbe/src/mbe_expander.rs
@@ -105,17 +105,15 @@ impl Bindings {
     }
 
     fn get(&self, name: &SmolStr, nesting: &[usize]) -> Result<&tt::TokenTree, ExpandError> {
-        let mut b = self
-            .inner
-            .get(name)
-            .ok_or(ExpandError::BindingError(format!("could not find binding `{}`", name)))?;
+        let mut b = self.inner.get(name).ok_or_else(|| {
+            ExpandError::BindingError(format!("could not find binding `{}`", name))
+        })?;
         for &idx in nesting.iter() {
             b = match b {
                 Binding::Simple(_) => break,
-                Binding::Nested(bs) => bs.get(idx).ok_or(ExpandError::BindingError(format!(
-                    "could not find nested binding `{}`",
-                    name
-                )))?,
+                Binding::Nested(bs) => bs.get(idx).ok_or_else(|| {
+                    ExpandError::BindingError(format!("could not find nested binding `{}`", name))
+                })?,
                 Binding::Empty => {
                     return Err(ExpandError::BindingError(format!(
                         "could not find empty binding `{}`",
@@ -206,48 +204,48 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
                         "path" => {
                             let path =
                                 input.eat_path().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(path.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(path));
                         }
                         "expr" => {
                             let expr =
                                 input.eat_expr().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(expr.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(expr));
                         }
                         "ty" => {
                             let ty = input.eat_ty().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(ty.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(ty));
                         }
                         "pat" => {
                             let pat = input.eat_pat().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(pat.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(pat));
                         }
                         "stmt" => {
                             let pat = input.eat_stmt().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(pat.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(pat));
                         }
                         "block" => {
                             let block =
                                 input.eat_block().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(block.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(block));
                         }
                         "meta" => {
                             let meta =
                                 input.eat_meta().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(meta.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(meta));
                         }
                         "tt" => {
                             let token = input.eat().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(token.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(token));
                         }
                         "item" => {
                             let item =
                                 input.eat_item().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(item.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(item));
                         }
                         "lifetime" => {
                             let lifetime =
                                 input.eat_lifetime().ok_or(ExpandError::UnexpectedToken)?.clone();
-                            res.inner.insert(text.clone(), Binding::Simple(lifetime.into()));
+                            res.inner.insert(text.clone(), Binding::Simple(lifetime));
                         }
                         "literal" => {
                             let literal =
@@ -262,7 +260,7 @@ fn match_lhs(pattern: &crate::Subtree, input: &mut TtCursor) -> Result<Bindings,
                             // `vis` is optional
                             if let Some(vis) = input.try_eat_vis() {
                                 let vis = vis.clone();
-                                res.inner.insert(text.clone(), Binding::Simple(vis.into()));
+                                res.inner.insert(text.clone(), Binding::Simple(vis));
                             } else {
                                 res.push_optional(&text);
                             }
@@ -452,7 +450,7 @@ fn expand_tt(
 
                 let idx = ctx.nesting.pop().unwrap();
                 ctx.nesting.push(idx + 1);
-                token_trees.push(reduce_single_token(t).into());
+                token_trees.push(reduce_single_token(t));
 
                 if let Some(ref sep) = repeat.separator {
                     match sep {
diff --git a/crates/ra_mbe/src/mbe_parser.rs b/crates/ra_mbe/src/mbe_parser.rs
index d8fe293c74..dca16b5376 100644
--- a/crates/ra_mbe/src/mbe_parser.rs
+++ b/crates/ra_mbe/src/mbe_parser.rs
@@ -125,8 +125,8 @@ fn parse_repeat(p: &mut TtCursor, transcriber: bool) -> Result<crate::Repeat, Pa
         }
     }
 
-    let sep = p.eat_seperator().ok_or(ParseError::Expected(String::from("separator")))?;
-    let rep = p.eat_punct().ok_or(ParseError::Expected(String::from("repeat")))?;
+    let sep = p.eat_seperator().ok_or_else(|| ParseError::Expected(String::from("separator")))?;
+    let rep = p.eat_punct().ok_or_else(|| ParseError::Expected(String::from("repeat")))?;
 
     mk_repeat(rep.char, subtree, Some(sep))
 }
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 0edb6f9a29..9d3d2ad5bc 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -155,9 +155,10 @@ fn convert_doc_comment<'a>(token: &ra_syntax::SyntaxToken<'a>) -> Option<Vec<tt:
     if let ast::CommentPlacement::Inner = doc {
         token_trees.push(mk_punct('!'));
     }
-    token_trees.push(tt::TokenTree::from(tt::Subtree::from(
-        tt::Subtree { delimiter: tt::Delimiter::Bracket, token_trees: meta_tkns }.into(),
-    )));
+    token_trees.push(tt::TokenTree::from(tt::Subtree {
+        delimiter: tt::Delimiter::Bracket,
+        token_trees: meta_tkns,
+    }));
 
     return Some(token_trees);
 
@@ -292,7 +293,7 @@ fn delim_to_str(d: tt::Delimiter, closing: bool) -> SmolStr {
     };
 
     let idx = closing as usize;
-    let text = if texts.len() > 0 { &texts[idx..texts.len() - (1 - idx)] } else { "" };
+    let text = if !texts.is_empty() { &texts[idx..texts.len() - (1 - idx)] } else { "" };
     text.into()
 }
 
diff --git a/crates/ra_parser/src/grammar.rs b/crates/ra_parser/src/grammar.rs
index cf603eba1d..5997636d62 100644
--- a/crates/ra_parser/src/grammar.rs
+++ b/crates/ra_parser/src/grammar.rs
@@ -87,10 +87,8 @@ pub(crate) fn pattern(p: &mut Parser) {
 }
 
 pub(crate) fn stmt(p: &mut Parser, with_semi: bool) {
-    let with_semi = match with_semi {
-        true => expressions::StmtWithSemi::Yes,
-        false => expressions::StmtWithSemi::No,
-    };
+    let with_semi =
+        if with_semi { expressions::StmtWithSemi::Yes } else { expressions::StmtWithSemi::No };
 
     expressions::stmt(p, with_semi)
 }
diff --git a/crates/ra_parser/src/grammar/expressions.rs b/crates/ra_parser/src/grammar/expressions.rs
index bb6c78b5fb..99e32c4e82 100644
--- a/crates/ra_parser/src/grammar/expressions.rs
+++ b/crates/ra_parser/src/grammar/expressions.rs
@@ -454,6 +454,7 @@ fn method_call_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
 //     x.1i32;
 //     x.0x01;
 // }
+#[allow(clippy::if_same_then_else)]
 fn field_expr(p: &mut Parser, lhs: CompletedMarker) -> CompletedMarker {
     assert!(p.at(T![.]));
     let m = lhs.precede(p);
diff --git a/crates/ra_prof/src/lib.rs b/crates/ra_prof/src/lib.rs
index de67b4031d..6ec24d86d5 100644
--- a/crates/ra_prof/src/lib.rs
+++ b/crates/ra_prof/src/lib.rs
@@ -236,13 +236,13 @@ thread_local!(static IN_SCOPE: RefCell<bool> = RefCell::new(false));
 /// Allows to check if the current code is withing some dynamic scope, can be
 /// useful during debugging to figure out why a function is called.
 pub struct Scope {
-    prev: bool,
+    _hidden: (),
 }
 
 impl Scope {
     pub fn enter() -> Scope {
-        let prev = IN_SCOPE.with(|slot| std::mem::replace(&mut *slot.borrow_mut(), true));
-        Scope { prev }
+        IN_SCOPE.with(|slot| *slot.borrow_mut() = true);
+        Scope { _hidden: () }
     }
     pub fn is_active() -> bool {
         IN_SCOPE.with(|slot| *slot.borrow())
@@ -251,7 +251,7 @@ impl Scope {
 
 impl Drop for Scope {
     fn drop(&mut self) {
-        IN_SCOPE.with(|slot| *slot.borrow_mut() = self.prev);
+        IN_SCOPE.with(|slot| *slot.borrow_mut() = false);
     }
 }
 
diff --git a/crates/ra_project_model/src/cargo_workspace.rs b/crates/ra_project_model/src/cargo_workspace.rs
index 71976071fe..5a16577888 100644
--- a/crates/ra_project_model/src/cargo_workspace.rs
+++ b/crates/ra_project_model/src/cargo_workspace.rs
@@ -137,7 +137,7 @@ impl CargoWorkspace {
         for meta_pkg in meta.packages {
             let is_member = ws_members.contains(&meta_pkg.id);
             let pkg = packages.alloc(PackageData {
-                name: meta_pkg.name.into(),
+                name: meta_pkg.name,
                 manifest: meta_pkg.manifest_path.clone(),
                 targets: Vec::new(),
                 is_member,
@@ -149,7 +149,7 @@ impl CargoWorkspace {
             for meta_tgt in meta_pkg.targets {
                 let tgt = targets.alloc(TargetData {
                     pkg,
-                    name: meta_tgt.name.into(),
+                    name: meta_tgt.name,
                     root: meta_tgt.src_path.clone(),
                     kind: TargetKind::new(meta_tgt.kind.as_slice()),
                 });
@@ -160,8 +160,7 @@ impl CargoWorkspace {
         for node in resolve.nodes {
             let source = pkg_by_id[&node.id];
             for dep_node in node.deps {
-                let dep =
-                    PackageDependency { name: dep_node.name.into(), pkg: pkg_by_id[&dep_node.pkg] };
+                let dep = PackageDependency { name: dep_node.name, pkg: pkg_by_id[&dep_node.pkg] };
                 packages[source].dependencies.push(dep);
             }
         }
diff --git a/crates/ra_project_model/src/lib.rs b/crates/ra_project_model/src/lib.rs
index 63eb7041e1..4ae7f685c7 100644
--- a/crates/ra_project_model/src/lib.rs
+++ b/crates/ra_project_model/src/lib.rs
@@ -70,7 +70,7 @@ impl ProjectRoot {
             })
         };
 
-        let hidden = dir_path.components().any(|c| c.as_str().starts_with("."));
+        let hidden = dir_path.components().any(|c| c.as_str().starts_with('.'));
 
         !is_ignored && !hidden
     }
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs
index e4c99784c3..930b2d9fad 100644
--- a/crates/ra_syntax/src/ast/extensions.rs
+++ b/crates/ra_syntax/src/ast/extensions.rs
@@ -78,7 +78,7 @@ impl ast::Attr {
         if attr.kind() == IDENT {
             let key = attr.as_token()?.text().clone();
             let val_node = tt_node.children_with_tokens().find(|t| t.kind() == STRING)?;
-            let val = val_node.as_token()?.text().trim_start_matches("\"").trim_end_matches("\"");
+            let val = val_node.as_token()?.text().trim_start_matches('"').trim_end_matches('"');
             Some((key, SmolStr::new(val)))
         } else {
             None
diff --git a/crates/ra_syntax/src/validation/unescape.rs b/crates/ra_syntax/src/validation/unescape.rs
index 2086046b67..91dbcfae87 100644
--- a/crates/ra_syntax/src/validation/unescape.rs
+++ b/crates/ra_syntax/src/validation/unescape.rs
@@ -255,7 +255,7 @@ where
         let first_non_space = str
             .bytes()
             .position(|b| b != b' ' && b != b'\t' && b != b'\n' && b != b'\r')
-            .unwrap_or(str.len());
+            .unwrap_or_else(|| str.len());
         *chars = str[first_non_space..].chars()
     }
 }
diff --git a/crates/ra_tt/src/buffer.rs b/crates/ra_tt/src/buffer.rs
index 995c9f90be..5659aeae8b 100644
--- a/crates/ra_tt/src/buffer.rs
+++ b/crates/ra_tt/src/buffer.rs
@@ -179,6 +179,6 @@ impl<'a> Cursor<'a> {
     /// Check whether it is a top level
     pub fn is_root(&self) -> bool {
         let entry_id = self.ptr.0;
-        return entry_id.0 == 0;
+        entry_id.0 == 0
     }
 }
diff --git a/crates/thread_worker/src/lib.rs b/crates/thread_worker/src/lib.rs
index d67e44e380..d8d0d9bf23 100644
--- a/crates/thread_worker/src/lib.rs
+++ b/crates/thread_worker/src/lib.rs
@@ -19,13 +19,10 @@ impl Drop for ScopedThread {
         log::info!(".. {} terminated with {}", name, if res.is_ok() { "ok" } else { "err" });
 
         // escalate panic, but avoid aborting the process
-        match res {
-            Err(e) => {
-                if !thread::panicking() {
-                    panic!(e)
-                }
+        if let Err(e) = res {
+            if !thread::panicking() {
+                panic!(e)
             }
-            _ => (),
         }
     }
 }
diff --git a/crates/tools/src/lib.rs b/crates/tools/src/lib.rs
index 11b52ccb7f..2446fdf287 100644
--- a/crates/tools/src/lib.rs
+++ b/crates/tools/src/lib.rs
@@ -133,6 +133,40 @@ pub fn install_format_hook() -> Result<()> {
     Ok(())
 }
 
+pub fn run_clippy() -> Result<()> {
+    match Command::new("rustup")
+        .args(&["run", TOOLCHAIN, "--", "cargo", "clippy", "--version"])
+        .stderr(Stdio::null())
+        .stdout(Stdio::null())
+        .status()
+    {
+        Ok(status) if status.success() => (),
+        _ => install_clippy()?,
+    };
+
+    let allowed_lints = [
+        "clippy::collapsible_if",
+        "clippy::map_clone", // FIXME: remove when Iterator::copied stabilizes (1.36.0)
+        "clippy::needless_pass_by_value",
+        "clippy::nonminimal_bool",
+        "clippy::redundant_pattern_matching",
+    ];
+    run(
+        &format!(
+            "rustup run {} -- cargo clippy --all-features --all-targets -- -A {}",
+            TOOLCHAIN,
+            allowed_lints.join(" -A ")
+        ),
+        ".",
+    )?;
+    Ok(())
+}
+
+pub fn install_clippy() -> Result<()> {
+    run(&format!("rustup install {}", TOOLCHAIN), ".")?;
+    run(&format!("rustup component add clippy --toolchain {}", TOOLCHAIN), ".")
+}
+
 pub fn run_fuzzer() -> Result<()> {
     match Command::new("cargo")
         .args(&["fuzz", "--help"])
diff --git a/crates/tools/src/main.rs b/crates/tools/src/main.rs
index 0c33396857..8027ff833e 100644
--- a/crates/tools/src/main.rs
+++ b/crates/tools/src/main.rs
@@ -3,7 +3,7 @@ use core::str;
 use failure::bail;
 use tools::{
     generate, gen_tests, install_format_hook, run, run_with_output, run_rustfmt,
-    Overwrite, Result, run_fuzzer,
+    Overwrite, Result, run_fuzzer, run_clippy,
 };
 use std::{path::{PathBuf}, env};
 
@@ -16,6 +16,7 @@ fn main() -> Result<()> {
         .subcommand(SubCommand::with_name("format"))
         .subcommand(SubCommand::with_name("format-hook"))
         .subcommand(SubCommand::with_name("fuzz-tests"))
+        .subcommand(SubCommand::with_name("lint"))
         .get_matches();
     match matches.subcommand_name().expect("Subcommand must be specified") {
         "install-code" => {
@@ -28,6 +29,7 @@ fn main() -> Result<()> {
         "gen-syntax" => generate(Overwrite)?,
         "format" => run_rustfmt(Overwrite)?,
         "format-hook" => install_format_hook()?,
+        "lint" => run_clippy()?,
         "fuzz-tests" => run_fuzzer()?,
         _ => unreachable!(),
     }
@@ -82,7 +84,7 @@ fn fix_path_for_mac() -> Result<()> {
 
         [ROOT_DIR, &home_dir]
             .iter()
-            .map(|dir| String::from(dir.clone()) + COMMON_APP_PATH)
+            .map(|dir| String::from(*dir) + COMMON_APP_PATH)
             .map(PathBuf::from)
             .filter(|path| path.exists())
             .collect()


Test patch:
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs
index f952a03a39..75912afdd4 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/support.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs
@@ -94,14 +94,9 @@ impl Server {
         let worker = Worker::<RawMessage, RawMessage>::spawn(
             "test server",
             128,
-            move |mut msg_receiver, mut msg_sender| {
-                main_loop(
-                    roots,
-                    InitializationOptions::default(),
-                    &mut msg_receiver,
-                    &mut msg_sender,
-                )
-                .unwrap()
+            move |msg_receiver, msg_sender| {
+                main_loop(roots, InitializationOptions::default(), &msg_receiver, &msg_sender)
+                    .unwrap()
             },
         );
         let res = Server { req_id: Cell::new(1), dir, messages: Default::default(), worker };
@@ -141,15 +136,14 @@ impl Server {
         R::Params: Serialize,
     {
         let actual = self.send_request::<R>(params);
-        match find_mismatch(&expected_resp, &actual) {
-            Some((expected_part, actual_part)) => panic!(
+        if let Some((expected_part, actual_part)) = find_mismatch(&expected_resp, &actual) {
+            panic!(
                 "JSON mismatch\nExpected:\n{}\nWas:\n{}\nExpected part:\n{}\nActual part:\n{}\n",
                 to_string_pretty(&expected_resp).unwrap(),
                 to_string_pretty(&actual).unwrap(),
                 to_string_pretty(expected_part).unwrap(),
                 to_string_pretty(actual_part).unwrap(),
-            ),
-            None => {}
+            );
         }
     }
 
diff --git a/crates/ra_text_edit/src/test_utils.rs b/crates/ra_text_edit/src/test_utils.rs
index 9e21b24f67..2dc0e71af2 100644
--- a/crates/ra_text_edit/src/test_utils.rs
+++ b/crates/ra_text_edit/src/test_utils.rs
@@ -42,8 +42,8 @@ pub fn arb_text_edit(text: &str) -> BoxedStrategy<TextEdit> {
         .prop_flat_map(|cuts| {
             let strategies: Vec<_> = cuts
                 .chunks(2)
-                .map(|chunk| match chunk {
-                    &[from, to] => {
+                .map(|chunk| match *chunk {
+                    [from, to] => {
                         let range = TextRange::from_to(from, to);
                         Just(AtomTextEdit::delete(range))
                             .boxed()
@@ -54,7 +54,7 @@ pub fn arb_text_edit(text: &str) -> BoxedStrategy<TextEdit> {
                             )
                             .boxed()
                     }
-                    &[x] => arb_text().prop_map(move |text| AtomTextEdit::insert(x, text)).boxed(),
+                    [x] => arb_text().prop_map(move |text| AtomTextEdit::insert(x, text)).boxed(),
                     _ => unreachable!(),
                 })
                 .collect();
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index 7f55779cf0..8bb3b3937f 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -318,7 +318,7 @@ pub fn project_dir() -> PathBuf {
 /// so this should always be correct.
 pub fn read_text(path: &Path) -> String {
     fs::read_to_string(path)
-        .expect(&format!("File at {:?} should be valid", path))
+        .unwrap_or_else(|_| panic!("File at {:?} should be valid", path))
         .replace("\r\n", "\n")
 }