Repository: rust-analyzer/rust-analyzer
Pull request #8144 (2021-03-22 07:17:24)

bail out early for source code closures
close https://github.com/rust-analyzer/rust-analyzer/issues/8084


Patch:
diff --git a/crates/base_db/src/input.rs b/crates/base_db/src/input.rs
index e9e8dfc2e9..d0def21815 100644
--- a/crates/base_db/src/input.rs
+++ b/crates/base_db/src/input.rs
@@ -410,7 +410,7 @@ impl CrateId {
 
 impl CrateData {
     fn add_dep(&mut self, name: CrateName, crate_id: CrateId) {
-        self.dependencies.push(Dependency { crate_id, name })
+        self.dependencies.push(Dependency { name, crate_id })
     }
 }
 
diff --git a/crates/cfg/src/dnf.rs b/crates/cfg/src/dnf.rs
index 75ded9aa1f..30f4bcdf79 100644
--- a/crates/cfg/src/dnf.rs
+++ b/crates/cfg/src/dnf.rs
@@ -255,9 +255,9 @@ impl Builder {
 fn make_dnf(expr: CfgExpr) -> CfgExpr {
     match expr {
         CfgExpr::Invalid | CfgExpr::Atom(_) | CfgExpr::Not(_) => expr,
-        CfgExpr::Any(e) => CfgExpr::Any(e.into_iter().map(make_dnf).collect()),
+        CfgExpr::Any(e) => CfgExpr::Any(e.into_iter().map(|expr| make_dnf(expr)).collect()),
         CfgExpr::All(e) => {
-            let e = e.into_iter().map(make_nnf).collect::<Vec<_>>();
+            let e = e.into_iter().map(|expr| make_nnf(expr)).collect::<Vec<_>>();
 
             CfgExpr::Any(distribute_conj(&e))
         }
@@ -300,8 +300,8 @@ fn distribute_conj(conj: &[CfgExpr]) -> Vec<CfgExpr> {
 fn make_nnf(expr: CfgExpr) -> CfgExpr {
     match expr {
         CfgExpr::Invalid | CfgExpr::Atom(_) => expr,
-        CfgExpr::Any(expr) => CfgExpr::Any(expr.into_iter().map(make_nnf).collect()),
-        CfgExpr::All(expr) => CfgExpr::All(expr.into_iter().map(make_nnf).collect()),
+        CfgExpr::Any(expr) => CfgExpr::Any(expr.into_iter().map(|expr| make_nnf(expr)).collect()),
+        CfgExpr::All(expr) => CfgExpr::All(expr.into_iter().map(|expr| make_nnf(expr)).collect()),
         CfgExpr::Not(operand) => match *operand {
             CfgExpr::Invalid | CfgExpr::Atom(_) => CfgExpr::Not(operand.clone()), // Original negated expr
             CfgExpr::Not(expr) => {
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index e3ac37e4c8..e34be7e42f 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -213,7 +213,7 @@ impl Crate {
                 Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text),
                 _ => None
             }
-        }).flatten().next();
+        }).flat_map(|t| t).next();
 
         doc_url.map(|s| s.trim_matches('"').trim_end_matches('/').to_owned() + "/")
     }
@@ -2068,10 +2068,7 @@ impl Type {
                 match pred {
                     WhereClause::Implemented(trait_ref) => {
                         cb(type_.clone());
-                        // skip the self type. it's likely the type we just got the bounds from
-                        for ty in trait_ref.substitution.iter().skip(1) {
-                            walk_type(db, &type_.derived(ty.clone()), cb);
-                        }
+                        walk_substs(db, type_, &trait_ref.substitution, cb);
                     }
                     _ => (),
                 }
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 52a2bce9b1..2c10f46d8a 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -638,7 +638,7 @@ fn collect_attrs(
     owner: &dyn ast::AttrsOwner,
 ) -> impl Iterator<Item = Either<ast::Attr, ast::Comment>> {
     let (inner_attrs, inner_docs) = inner_attributes(owner.syntax())
-        .map_or((None, None), |(attrs, docs)| (Some(attrs), Some(docs)));
+        .map_or((None, None), |(attrs, docs)| ((Some(attrs), Some(docs))));
 
     let outer_attrs = owner.attrs().filter(|attr| attr.excl_token().is_none());
     let attrs = outer_attrs
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 28b73c3a18..46a3c60cdd 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1467,13 +1467,12 @@ impl ModCollector<'_, '_> {
             },
         ) {
             Ok(Ok(macro_call_id)) => {
-                // Legacy macros need to be expanded immediately, so that any macros they produce
-                // are in scope.
-                self.def_collector.collect_macro_expansion(
-                    self.module_id,
-                    macro_call_id,
-                    self.macro_depth + 1,
-                );
+                self.def_collector.unexpanded_macros.push(MacroDirective {
+                    module_id: self.module_id,
+                    ast_id,
+                    legacy: Some(macro_call_id),
+                    depth: self.macro_depth + 1,
+                });
 
                 return;
             }
diff --git a/crates/hir_def/src/nameres/mod_resolution.rs b/crates/hir_def/src/nameres/mod_resolution.rs
index d9cec0e27a..d5de9899cf 100644
--- a/crates/hir_def/src/nameres/mod_resolution.rs
+++ b/crates/hir_def/src/nameres/mod_resolution.rs
@@ -62,7 +62,7 @@ impl ModDir {
         name: &Name,
         attr_path: Option<&SmolStr>,
     ) -> Result<(FileId, bool, ModDir), String> {
-        let orig_file_id = file_id.original_file(db.upcast());
+        let file_id = file_id.original_file(db.upcast());
 
         let mut candidate_files = Vec::new();
         match attr_path {
@@ -70,18 +70,13 @@ impl ModDir {
                 candidate_files.push(self.dir_path.join_attr(attr_path, self.root_non_dir_owner))
             }
             None => {
-                if file_id.is_include_macro(db.upcast()) {
-                    candidate_files.push(format!("{}.rs", name));
-                    candidate_files.push(format!("{}/mod.rs", name));
-                } else {
-                    candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
-                    candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
-                }
+                candidate_files.push(format!("{}{}.rs", self.dir_path.0, name));
+                candidate_files.push(format!("{}{}/mod.rs", self.dir_path.0, name));
             }
         };
 
         for candidate in candidate_files.iter() {
-            let path = AnchoredPath { anchor: orig_file_id, path: candidate.as_str() };
+            let path = AnchoredPath { anchor: file_id, path: candidate.as_str() };
             if let Some(file_id) = db.resolve_path(path) {
                 let is_mod_rs = candidate.ends_with("/mod.rs");
 
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index 04ea9c5d7f..4a2d1c0875 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -472,7 +472,7 @@ impl Scope {
             }
             Scope::ExprScope(scope) => {
                 if let Some((label, name)) = scope.expr_scopes.label(scope.scope_id) {
-                    f(name, ScopeDef::Label(label))
+                    f(name.clone(), ScopeDef::Label(label))
                 }
                 scope.expr_scopes.entries(scope.scope_id).iter().for_each(|e| {
                     f(e.name().clone(), ScopeDef::Local(e.pat()));
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 4d52904b94..8529b43b6d 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -43,7 +43,7 @@ macro_rules! register_builtin {
                 db: &dyn AstDatabase,
                 arg_id: EagerMacroId,
                 tt: &tt::Subtree,
-            ) -> ExpandResult<Option<ExpandedEager>> {
+            ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
                 let expander = match *self {
                     $( EagerExpander::$e_kind => $e_expand, )*
                 };
@@ -61,20 +61,6 @@ macro_rules! register_builtin {
     };
 }
 
-#[derive(Debug)]
-pub struct ExpandedEager {
-    pub(crate) subtree: tt::Subtree,
-    pub(crate) fragment: FragmentKind,
-    /// The included file ID of the include macro.
-    pub(crate) included_file: Option<FileId>,
-}
-
-impl ExpandedEager {
-    fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
-        ExpandedEager { subtree, fragment, included_file: None }
-    }
-}
-
 pub fn find_builtin_macro(
     ident: &name::Name,
     krate: CrateId,
@@ -294,7 +280,7 @@ fn compile_error_expand(
     _db: &dyn AstDatabase,
     _id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let err = match &*tt.token_trees {
         [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => {
             let text = it.text.as_str();
@@ -308,14 +294,14 @@ fn compile_error_expand(
         _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()),
     };
 
-    ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) }
+    ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) }
 }
 
 fn concat_expand(
     _db: &dyn AstDatabase,
     _arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let mut err = None;
     let mut text = String::new();
     for (i, t) in tt.token_trees.iter().enumerate() {
@@ -339,7 +325,7 @@ fn concat_expand(
             }
         }
     }
-    ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err }
+    ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err }
 }
 
 fn relative_file(
@@ -375,27 +361,21 @@ fn include_expand(
     db: &dyn AstDatabase,
     arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let res = (|| {
         let path = parse_string(tt)?;
         let file_id = relative_file(db, arg_id.into(), &path, false)?;
 
-        let subtree = parse_to_token_tree(&db.file_text(file_id))
+        Ok(parse_to_token_tree(&db.file_text(file_id))
             .ok_or_else(|| mbe::ExpandError::ConversionError)?
-            .0;
-        Ok((subtree, file_id))
+            .0)
     })();
 
     match res {
-        Ok((subtree, file_id)) => {
+        Ok(res) => {
             // FIXME:
             // Handle include as expression
-
-            ExpandResult::ok(Some(ExpandedEager {
-                subtree,
-                fragment: FragmentKind::Items,
-                included_file: Some(file_id),
-            }))
+            ExpandResult::ok(Some((res, FragmentKind::Items)))
         }
         Err(e) => ExpandResult::only_err(e),
     }
@@ -405,7 +385,7 @@ fn include_bytes_expand(
     _db: &dyn AstDatabase,
     _arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     if let Err(e) = parse_string(tt) {
         return ExpandResult::only_err(e);
     }
@@ -418,14 +398,14 @@ fn include_bytes_expand(
             id: tt::TokenId::unspecified(),
         }))],
     };
-    ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr)))
+    ExpandResult::ok(Some((res, FragmentKind::Expr)))
 }
 
 fn include_str_expand(
     db: &dyn AstDatabase,
     arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let path = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => return ExpandResult::only_err(e),
@@ -438,14 +418,14 @@ fn include_str_expand(
     let file_id = match relative_file(db, arg_id.into(), &path, true) {
         Ok(file_id) => file_id,
         Err(_) => {
-            return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr)));
+            return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr)));
         }
     };
 
     let text = db.file_text(file_id);
     let text = &*text;
 
-    ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)))
+    ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr)))
 }
 
 fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> {
@@ -457,7 +437,7 @@ fn env_expand(
     db: &dyn AstDatabase,
     arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let key = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => return ExpandResult::only_err(e),
@@ -481,14 +461,14 @@ fn env_expand(
     });
     let expanded = quote! { #s };
 
-    ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err }
+    ExpandResult { value: Some((expanded, FragmentKind::Expr)), err }
 }
 
 fn option_env_expand(
     db: &dyn AstDatabase,
     arg_id: EagerMacroId,
     tt: &tt::Subtree,
-) -> ExpandResult<Option<ExpandedEager>> {
+) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> {
     let key = match parse_string(tt) {
         Ok(it) => it,
         Err(e) => return ExpandResult::only_err(e),
@@ -499,7 +479,7 @@ fn option_env_expand(
         Some(s) => quote! { std::option::Some(#s) },
     };
 
-    ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr)))
+    ExpandResult::ok(Some((expanded, FragmentKind::Expr)))
 }
 
 #[cfg(test)]
@@ -573,18 +553,16 @@ mod tests {
                         subtree: Arc::new(parsed_args.clone()),
                         krate,
                         call: call_id,
-                        included_file: None,
                     }
                 });
 
-                let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
+                let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap();
                 let eager = EagerCallLoc {
                     def,
-                    fragment: expanded.fragment,
-                    subtree: Arc::new(expanded.subtree),
+                    fragment,
+                    subtree: Arc::new(subtree),
                     krate,
                     call: call_id,
-                    included_file: expanded.included_file,
                 };
 
                 let id: MacroCallId = db.intern_eager_expansion(eager).into();
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index fc73e435bf..2748e25cf3 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -173,7 +173,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> {
     };
     let loc = db.lookup_intern_macro(id);
     let arg = loc.kind.arg(db)?;
-    Some(arg.green())
+    Some(arg.green().to_owned())
 }
 
 fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> {
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 9eedc84614..04f374a29f 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -124,7 +124,6 @@ pub fn expand_eager_macro(
             subtree: Arc::new(parsed_args.clone()),
             krate,
             call: call_id,
-            included_file: None,
         }
     });
     let arg_file_id: MacroCallId = arg_id.into();
@@ -144,15 +143,9 @@ pub fn expand_eager_macro(
     if let MacroDefKind::BuiltInEager(eager, _) = def.kind {
         let res = eager.expand(db, arg_id, &subtree);
 
-        let expanded = diagnostic_sink.expand_result_option(res)?;
-        let eager = EagerCallLoc {
-            def,
-            fragment: expanded.fragment,
-            subtree: Arc::new(expanded.subtree),
-            krate,
-            call: call_id,
-            included_file: expanded.included_file,
-        };
+        let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?;
+        let eager =
+            EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id };
 
         Ok(db.intern_eager_expansion(eager))
     } else {
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index b8045fda95..f49fd4fda1 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -84,11 +84,7 @@ impl HirFileId {
                     }
                     MacroCallId::EagerMacro(id) => {
                         let loc = db.lookup_intern_eager_expansion(id);
-                        if let Some(included_file) = loc.included_file {
-                            return included_file;
-                        } else {
-                            loc.call.file_id
-                        }
+                        loc.call.file_id
                     }
                 };
                 file_id.original_file(db)
@@ -192,21 +188,6 @@ impl HirFileId {
             }
         }
     }
-
-    /// Return whether this file is an include macro
-    pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool {
-        match self.0 {
-            HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id {
-                MacroCallId::EagerMacro(id) => {
-                    let loc = db.lookup_intern_eager_expansion(id);
-                    return loc.included_file.is_some();
-                }
-                _ => {}
-            },
-            _ => {}
-        }
-        false
-    }
 }
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -334,8 +315,6 @@ pub struct EagerCallLoc {
     pub(crate) subtree: Arc<tt::Subtree>,
     pub(crate) krate: CrateId,
     pub(crate) call: AstId<ast::MacroCall>,
-    // The included file ID of the include macro.
-    pub(crate) included_file: Option<FileId>,
 }
 
 /// ExpansionInfo mainly describes how to map text range between src and expanded macro
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 0aeea48d50..43de9edd65 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -48,8 +48,9 @@ impl Name {
 
     /// Resolve a name from the text of token.
     fn resolve(raw_text: &str) -> Name {
-        if let Some(text) = raw_text.strip_prefix("r#") {
-            Name::new_text(SmolStr::new(text))
+        let raw_start = "r#";
+        if raw_text.starts_with(raw_start) {
+            Name::new_text(SmolStr::new(&raw_text[raw_start.len()..]))
         } else {
             Name::new_text(raw_text.into())
         }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 9d3b79be39..981ba564d3 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -190,6 +190,7 @@ impl DisplayTarget {
 pub enum DisplaySourceCodeError {
     PathNotFound,
     UnknownType,
+    Closure,
 }
 
 pub enum HirDisplayError {
@@ -539,6 +540,11 @@ impl HirDisplay for Ty {
                 }
             }
             TyKind::Closure(.., substs) => {
+                if f.display_target.is_source_code() {
+                    return Err(HirDisplayError::DisplaySourceCodeError(
+                        DisplaySourceCodeError::Closure,
+                    ));
+                }
                 let sig = substs[0].callable_sig(f.db);
                 if let Some(sig) = sig {
                     if sig.params().is_empty() {
@@ -571,22 +577,13 @@ impl HirDisplay for Ty {
                         write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
                     }
                     TypeParamProvenance::ArgumentImplTrait => {
+                        let bounds = f.db.generic_predicates_for_param(id);
                         let substs = Substitution::type_params_for_generics(f.db, &generics);
-                        let bounds = f
-                            .db
-                            .generic_predicates(id.parent)
-                            .into_iter()
-                            .map(|pred| pred.clone().subst(&substs))
-                            .filter(|wc| match &wc {
-                                WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
-                                WhereClause::AliasEq(AliasEq {
-                                    alias: AliasTy::Projection(proj),
-                                    ty: _,
-                                }) => proj.self_type_parameter() == self,
-                                _ => false,
-                            })
-                            .collect::<Vec<_>>();
-                        write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
+                        write_bounds_like_dyn_trait_with_prefix(
+                            "impl",
+                            &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(),
+                            f,
+                        )?;
                     }
                 }
             }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 24deff7073..79bbc5daba 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -513,10 +513,10 @@ impl<'a> InferenceContext<'a> {
                 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
                 if let Some(box_) = self.resolve_boxed_box() {
                     let mut sb =
-                        Substitution::build_for_generics(&generics(self.db.upcast(), box_.into()));
+                        Substitution::builder(generics(self.db.upcast(), box_.into()).len());
                     sb = sb.push(inner_ty);
-                    match self.db.generic_defaults(box_.into()).get(1) {
-                        Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
+                    match self.db.generic_defaults(box_.into()).as_ref() {
+                        [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => {
                             sb = sb.push(alloc_ty.value.clone());
                         }
                         _ => (),
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 474363709b..befa0d69b0 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -13,9 +13,7 @@ use hir_expand::name::Name;
 
 use super::{BindingMode, Expectation, InferenceContext};
 use crate::{
-    lower::lower_to_chalk_mutability,
-    utils::{generics, variant_data},
-    Interner, Substitution, Ty, TyKind,
+    lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind,
 };
 
 impl<'a> InferenceContext<'a> {
@@ -40,7 +38,7 @@ impl<'a> InferenceContext<'a> {
         let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
         let (pre, post) = match ellipsis {
             Some(idx) => subpats.split_at(idx),
-            None => (subpats, &[][..]),
+            None => (&subpats[..], &[][..]),
         };
         let post_idx_offset = field_tys.iter().count() - post.len();
 
@@ -235,31 +233,13 @@ impl<'a> InferenceContext<'a> {
             Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())),
             Pat::Box { inner } => match self.resolve_boxed_box() {
                 Some(box_adt) => {
-                    let (inner_ty, alloc_ty) = match expected.as_adt() {
-                        Some((adt, subst)) if adt == box_adt => {
-                            (subst[0].clone(), subst.get(1).cloned())
-                        }
-                        _ => (self.result.standard_types.unknown.clone(), None),
+                    let inner_expected = match expected.as_adt() {
+                        Some((adt, substs)) if adt == box_adt => substs.as_single().clone(),
+                        _ => self.result.standard_types.unknown.clone(),
                     };
 
-                    let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
-                    let mut sb = Substitution::build_for_generics(&generics(
-                        self.db.upcast(),
-                        box_adt.into(),
-                    ));
-                    sb = sb.push(inner_ty);
-                    if sb.remaining() == 1 {
-                        sb = sb.push(match alloc_ty {
-                            Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
-                            _ => match self.db.generic_defaults(box_adt.into()).get(1) {
-                                Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
-                                    alloc_ty.value.clone()
-                                }
-                                _ => self.table.new_type_var(),
-                            },
-                        });
-                    }
-                    Ty::adt_ty(box_adt, sb.build())
+                    let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm);
+                    Ty::adt_ty(box_adt, Substitution::single(inner_ty))
                 }
                 None => self.err_ty(),
             },
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index ad908f957b..c46529879d 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -106,10 +106,6 @@ impl ProjectionTy {
         }
     }
 
-    pub fn self_type_parameter(&self) -> &Ty {
-        &self.substitution[0]
-    }
-
     fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
         match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
             AssocContainerId::TraitId(it) => it,
@@ -940,19 +936,10 @@ impl Ty {
                 let param_data = &generic_params.types[id.local_id];
                 match param_data.provenance {
                     hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
-                        let substs = Substitution::type_params(db, id.parent);
                         let predicates = db
-                            .generic_predicates(id.parent)
+                            .generic_predicates_for_param(id)
                             .into_iter()
-                            .map(|pred| pred.clone().subst(&substs))
-                            .filter(|wc| match &wc {
-                                WhereClause::Implemented(tr) => tr.self_type_parameter() == self,
-                                WhereClause::AliasEq(AliasEq {
-                                    alias: AliasTy::Projection(proj),
-                                    ty: _,
-                                }) => proj.self_type_parameter() == self,
-                                _ => false,
-                            })
+                            .map(|pred| pred.value.clone())
                             .collect_vec();
 
                         Some(predicates)
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index fd451a823e..cbbb535e55 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -189,10 +189,7 @@ impl<'a> TyLoweringContext<'a> {
                 let self_ty =
                     TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
                 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-                    bounds
-                        .iter()
-                        .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false))
-                        .collect()
+                    bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect()
                 });
                 TyKind::Dyn(predicates).intern(&Interner)
             }
@@ -669,7 +666,6 @@ impl<'a> TyLoweringContext<'a> {
     pub(crate) fn lower_where_predicate(
         &'a self,
         where_predicate: &'a WherePredicate,
-        ignore_bindings: bool,
     ) -> impl Iterator<Item = WhereClause> + 'a {
         match where_predicate {
             WherePredicate::ForLifetime { target, bound, .. }
@@ -692,9 +688,7 @@ impl<'a> TyLoweringContext<'a> {
                         .intern(&Interner)
                     }
                 };
-                self.lower_type_bound(bound, self_ty, ignore_bindings)
-                    .collect::<Vec<_>>()
-                    .into_iter()
+                self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter()
             }
             WherePredicate::Lifetime { .. } => vec![].into_iter(),
         }
@@ -704,7 +698,6 @@ impl<'a> TyLoweringContext<'a> {
         &'a self,
         bound: &'a TypeBound,
         self_ty: Ty,
-        ignore_bindings: bool,
     ) -> impl Iterator<Item = WhereClause> + 'a {
         let mut bindings = None;
         let trait_ref = match bound {
@@ -718,7 +711,6 @@ impl<'a> TyLoweringContext<'a> {
         trait_ref.into_iter().chain(
             bindings
                 .into_iter()
-                .filter(move |_| !ignore_bindings)
                 .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)),
         )
     }
@@ -763,7 +755,6 @@ impl<'a> TyLoweringContext<'a> {
                     preds.extend(self.lower_type_bound(
                         bound,
                         TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner),
-                        false,
                     ));
                 }
                 preds
@@ -775,7 +766,7 @@ impl<'a> TyLoweringContext<'a> {
         let self_ty =
             TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
         let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-            bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect()
+            bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect()
         });
         ReturnTypeImplTrait { bounds: Binders::new(1, predicates) }
     }
@@ -905,9 +896,7 @@ pub(crate) fn generic_predicates_for_param_query(
             },
             WherePredicate::Lifetime { .. } => false,
         })
-        .flat_map(|pred| {
-            ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p))
-        })
+        .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p)))
         .collect()
 }
 
@@ -929,7 +918,7 @@ pub(crate) fn trait_environment_query(
     let mut traits_in_scope = Vec::new();
     let mut clauses = Vec::new();
     for pred in resolver.where_predicates_in_scope() {
-        for pred in ctx.lower_where_predicate(pred, false) {
+        for pred in ctx.lower_where_predicate(pred) {
             if let WhereClause::Implemented(tr) = &pred {
                 traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id()));
             }
@@ -957,7 +946,8 @@ pub(crate) fn trait_environment_query(
         let substs = Substitution::type_params(db, trait_id);
         let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
         let pred = WhereClause::Implemented(trait_ref);
-        let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner);
+        let program_clause: chalk_ir::ProgramClause<Interner> =
+            pred.clone().to_chalk(db).cast(&Interner);
         clauses.push(program_clause.into_from_env_clause(&Interner));
     }
 
@@ -977,9 +967,7 @@ pub(crate) fn generic_predicates_query(
     let generics = generics(db.upcast(), def);
     resolver
         .where_predicates_in_scope()
-        .flat_map(|pred| {
-            ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p))
-        })
+        .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p)))
         .collect()
 }
 
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 9441456038..734679414b 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -395,7 +395,7 @@ pub(crate) fn associated_ty_data_query(
     let bounds = type_alias_data
         .bounds
         .iter()
-        .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
+        .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone()))
         .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
         .map(|bound| make_binders(bound.shifted_in(&Interner), 0))
         .collect();
diff --git a/crates/ide/src/extend_selection.rs b/crates/ide/src/extend_selection.rs
index 5201ce587a..e187243cbf 100644
--- a/crates/ide/src/extend_selection.rs
+++ b/crates/ide/src/extend_selection.rs
@@ -263,10 +263,11 @@ fn extend_list_item(node: &SyntaxNode) -> Option<TextRange> {
     ) -> Option<SyntaxToken> {
         node.siblings_with_tokens(dir)
             .skip(1)
-            .find(|node| match node {
-                NodeOrToken::Node(_) => true,
-                NodeOrToken::Token(it) => !is_single_line_ws(it),
+            .skip_while(|node| match node {
+                NodeOrToken::Node(_) => false,
+                NodeOrToken::Token(it) => is_single_line_ws(it),
             })
+            .next()
             .and_then(|it| it.into_token())
             .filter(|node| node.kind() == delimiter_kind)
     }
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs
index 9dc3ee28fd..cdc45fc42c 100644
--- a/crates/ide_assists/src/handlers/convert_comment_block.rs
+++ b/crates/ide_assists/src/handlers/convert_comment_block.rs
@@ -1,4 +1,5 @@
 use itertools::Itertools;
+use std::convert::identity;
 use syntax::{
     ast::{
         self,
@@ -139,7 +140,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
         .filter(|s| !skippable(s))
         .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
         .take_while(|opt_com| opt_com.is_some())
-        .flatten()
+        .filter_map(identity)
         .skip(1); // skip the first element so we don't duplicate it in next_comments
 
     let next_comments = comment
@@ -148,7 +149,7 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
         .filter(|s| !skippable(s))
         .map(|not| not.into_token().and_then(Comment::cast).filter(same_prefix))
         .take_while(|opt_com| opt_com.is_some())
-        .flatten();
+        .filter_map(identity);
 
     let mut comments: Vec<_> = prev_comments.collect();
     comments.reverse();
diff --git a/crates/ide_assists/src/handlers/expand_glob_import.rs b/crates/ide_assists/src/handlers/expand_glob_import.rs
index 98389e4f7b..83aa11d52c 100644
--- a/crates/ide_assists/src/handlers/expand_glob_import.rs
+++ b/crates/ide_assists/src/handlers/expand_glob_import.rs
@@ -136,13 +136,18 @@ impl Refs {
                 .into_iter()
                 .filter(|r| {
                     if let Def::ModuleDef(ModuleDef::Trait(tr)) = r.def {
-                        if tr.items(ctx.db()).into_iter().any(|ai| {
-                            if let AssocItem::Function(f) = ai {
-                                Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx)
-                            } else {
-                                false
-                            }
-                        }) {
+                        if tr
+                            .items(ctx.db())
+                            .into_iter()
+                            .find(|ai| {
+                                if let AssocItem::Function(f) = *ai {
+                                    Def::ModuleDef(ModuleDef::Function(f)).is_referenced_in(ctx)
+                                } else {
+                                    false
+                                }
+                            })
+                            .is_some()
+                        {
                             return true;
                         }
                     }
diff --git a/crates/ide_assists/src/handlers/reorder_impl.rs b/crates/ide_assists/src/handlers/reorder_impl.rs
index f976e73adc..edf4b0bfeb 100644
--- a/crates/ide_assists/src/handlers/reorder_impl.rs
+++ b/crates/ide_assists/src/handlers/reorder_impl.rs
@@ -95,7 +95,7 @@ fn compute_method_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashM
                 _ => None,
             })
             .enumerate()
-            .map(|(idx, func)| (func.name(ctx.db()).to_string(), idx))
+            .map(|(idx, func)| ((func.name(ctx.db()).to_string(), idx)))
             .collect(),
     )
 }
diff --git a/crates/ide_completion/src/completions/lifetime.rs b/crates/ide_completion/src/completions/lifetime.rs
index 5eeddf7a40..628c1fb9b6 100644
--- a/crates/ide_completion/src/completions/lifetime.rs
+++ b/crates/ide_completion/src/completions/lifetime.rs
@@ -68,16 +68,6 @@ fn func<'lifetime>(foo: &'li$0) {}
 "#,
             r#"
 fn func<'lifetime>(foo: &'lifetime) {}
-"#,
-        );
-        cov_mark::check!(completes_if_lifetime_without_idents);
-        check_edit(
-            "'lifetime",
-            r#"
-fn func<'lifetime>(foo: &'$0) {}
-"#,
-            r#"
-fn func<'lifetime>(foo: &'lifetime) {}
 "#,
         );
     }
@@ -201,27 +191,6 @@ fn foo<'footime, 'lifetime: 'a$0>() {}
         );
     }
 
-    #[test]
-    fn check_label_edit() {
-        check_edit(
-            "'label",
-            r#"
-fn foo() {
-    'label: loop {
-        break '$0
-    }
-}
-"#,
-            r#"
-fn foo() {
-    'label: loop {
-        break 'label
-    }
-}
-"#,
-        );
-    }
-
     #[test]
     fn complete_label_in_loop() {
         check(
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index 32f81aec14..67e2d6f6c2 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -255,10 +255,6 @@ impl<'a> CompletionContext<'a> {
         if kind == IDENT || kind == LIFETIME_IDENT || kind == UNDERSCORE || kind.is_keyword() {
             cov_mark::hit!(completes_if_prefix_is_keyword);
             self.original_token.text_range()
-        } else if kind == CHAR {
-            // assume we are completing a lifetime but the user has only typed the '
-            cov_mark::hit!(completes_if_lifetime_without_idents);
-            TextRange::at(self.original_token.text_range().start(), TextSize::from(1))
         } else {
             TextRange::empty(self.position.offset)
         }
@@ -475,7 +471,7 @@ impl<'a> CompletionContext<'a> {
         self.lifetime_syntax =
             find_node_at_offset(original_file, lifetime.syntax().text_range().start());
         if let Some(parent) = lifetime.syntax().parent() {
-            if parent.kind() == ERROR {
+            if parent.kind() == syntax::SyntaxKind::ERROR {
                 return;
             }
 
diff --git a/crates/ide_completion/src/patterns.rs b/crates/ide_completion/src/patterns.rs
index d82564381d..cf5ef07b72 100644
--- a/crates/ide_completion/src/patterns.rs
+++ b/crates/ide_completion/src/patterns.rs
@@ -71,7 +71,7 @@ fn test_has_block_expr_parent() {
 }
 
 pub(crate) fn has_bind_pat_parent(element: SyntaxElement) -> bool {
-    element.ancestors().any(|it| it.kind() == IDENT_PAT)
+    element.ancestors().find(|it| it.kind() == IDENT_PAT).is_some()
 }
 #[test]
 fn test_has_bind_pat_parent() {
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 37acf95f0f..9e0cb91c3f 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -14,12 +14,10 @@ use syntax::{
     AstToken, InsertPosition, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxToken,
 };
 
-pub use hir::PrefixKind;
-
 #[derive(Clone, Copy, Debug, PartialEq, Eq)]
 pub struct InsertUseConfig {
     pub merge: Option<MergeBehavior>,
-    pub prefix_kind: PrefixKind,
+    pub prefix_kind: hir::PrefixKind,
     pub group: bool,
 }
 
diff --git a/crates/ide_ssr/src/parsing.rs b/crates/ide_ssr/src/parsing.rs
index 5e757e7019..5ff25cb6d7 100644
--- a/crates/ide_ssr/src/parsing.rs
+++ b/crates/ide_ssr/src/parsing.rs
@@ -67,7 +67,7 @@ impl ParsedRule {
     ) -> Result<Vec<ParsedRule>, SsrError> {
         let raw_pattern = pattern.as_rust_code();
         let raw_template = template.map(|t| t.as_rust_code());
-        let raw_template = raw_template.as_deref();
+        let raw_template = raw_template.as_ref().map(|s| s.as_str());
         let mut builder = RuleBuilder {
             placeholders_by_stand_in: pattern.placeholders_by_stand_in(),
             rules: Vec::new(),
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 75d2f2eedf..1682b21b08 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -304,7 +304,7 @@ impl BindingsBuilder {
         link_nodes: &'a Vec<LinkNode<Rc<BindingKind>>>,
         nodes: &mut Vec<&'a Rc<BindingKind>>,
     ) {
-        link_nodes.iter().for_each(|it| match it {
+        link_nodes.into_iter().for_each(|it| match it {
             LinkNode::Node(it) => nodes.push(it),
             LinkNode::Parent { idx, len } => self.collect_nodes_ref(*idx, *len, nodes),
         });
@@ -713,9 +713,10 @@ fn match_meta_var(kind: &str, input: &mut TtIter) -> ExpandResult<Option<Fragmen
                     .map(|ident| Some(tt::Leaf::from(ident.clone()).into()))
                     .map_err(|()| err!("expected ident")),
                 "tt" => input.expect_tt().map(Some).map_err(|()| err!()),
-                "lifetime" => {
-                    input.expect_lifetime().map(Some).map_err(|()| err!("expected lifetime"))
-                }
+                "lifetime" => input
+                    .expect_lifetime()
+                    .map(|tt| Some(tt))
+                    .map_err(|()| err!("expected lifetime")),
                 "literal" => {
                     let neg = input.eat_char('-');
                     input
diff --git a/crates/mbe/src/lib.rs b/crates/mbe/src/lib.rs
index e74f8cf3f4..33b85e23db 100644
--- a/crates/mbe/src/lib.rs
+++ b/crates/mbe/src/lib.rs
@@ -356,6 +356,6 @@ impl<T> ExpandResult<T> {
 
 impl<T: Default> From<Result<T, ExpandError>> for ExpandResult<T> {
     fn from(result: Result<T, ExpandError>) -> Self {
-        result.map_or_else(Self::only_err, Self::ok)
+        result.map_or_else(|e| Self::only_err(e), |it| Self::ok(it))
     }
 }
diff --git a/crates/mbe/src/parser.rs b/crates/mbe/src/parser.rs
index 61b2a49551..c88387653d 100644
--- a/crates/mbe/src/parser.rs
+++ b/crates/mbe/src/parser.rs
@@ -57,7 +57,7 @@ impl<'a> Iterator for OpDelimitedIter<'a> {
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         let len = self.inner.len() + if self.delimited.is_some() { 2 } else { 0 };
-        let remain = len.saturating_sub(self.idx);
+        let remain = len.checked_sub(self.idx).unwrap_or(0);
         (remain, Some(remain))
     }
 }
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs
index 9d433b3b0b..8bba3d3d52 100644
--- a/crates/mbe/src/syntax_bridge.rs
+++ b/crates/mbe/src/syntax_bridge.rs
@@ -362,7 +362,7 @@ trait TokenConvertor {
             if let Some((kind, closed)) = delim {
                 let mut subtree = tt::Subtree::default();
                 let (id, idx) = self.id_alloc().open_delim(range);
-                subtree.delimiter = Some(tt::Delimiter { id, kind });
+                subtree.delimiter = Some(tt::Delimiter { kind, id });
 
                 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) {
                     self.collect_leaf(&mut subtree.token_trees);
diff --git a/crates/project_model/src/build_data.rs b/crates/project_model/src/build_data.rs
index f7050be4e7..728a258eae 100644
--- a/crates/project_model/src/build_data.rs
+++ b/crates/project_model/src/build_data.rs
@@ -137,53 +137,60 @@ fn collect_from_workspace(
     let stdout = BufReader::new(child_stdout);
 
     let mut res = BuildDataMap::default();
-    for message in cargo_metadata::Message::parse_stream(stdout).flatten() {
-        match message {
-            Message::BuildScriptExecuted(BuildScript {
-                package_id, out_dir, cfgs, env, ..
-            }) => {
-                let cfgs = {
-                    let mut acc = Vec::new();
-                    for cfg in cfgs {
-                        match cfg.parse::<CfgFlag>() {
-                            Ok(it) => acc.push(it),
-                            Err(err) => {
-                                anyhow::bail!("invalid cfg from cargo-metadata: {}", err)
-                            }
-                        };
+    for message in cargo_metadata::Message::parse_stream(stdout) {
+        if let Ok(message) = message {
+            match message {
+                Message::BuildScriptExecuted(BuildScript {
+                    package_id,
+                    out_dir,
+                    cfgs,
+                    env,
+                    ..
+                }) => {
+                    let cfgs = {
+                        let mut acc = Vec::new();
+                        for cfg in cfgs {
+                            match cfg.parse::<CfgFlag>() {
+                                Ok(it) => acc.push(it),
+                                Err(err) => {
+                                    anyhow::bail!("invalid cfg from cargo-metadata: {}", err)
+                                }
+                            };
+                        }
+                        acc
+                    };
+                    let res = res.entry(package_id.repr.clone()).or_default();
+                    // cargo_metadata crate returns default (empty) path for
+                    // older cargos, which is not absolute, so work around that.
+                    if !out_dir.as_str().is_empty() {
+                        let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
+                        res.out_dir = Some(out_dir);
+                        res.cfgs = cfgs;
                     }
-                    acc
-                };
-                let res = res.entry(package_id.repr.clone()).or_default();
-                // cargo_metadata crate returns default (empty) path for
-                // older cargos, which is not absolute, so work around that.
-                if !out_dir.as_str().is_empty() {
-                    let out_dir = AbsPathBuf::assert(PathBuf::from(out_dir.into_os_string()));
-                    res.out_dir = Some(out_dir);
-                    res.cfgs = cfgs;
-                }
 
-                res.envs = env;
-            }
-            Message::CompilerArtifact(message) => {
-                progress(format!("metadata {}", message.target.name));
-
-                if message.target.kind.contains(&"proc-macro".to_string()) {
-                    let package_id = message.package_id;
-                    // Skip rmeta file
-                    if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name)) {
-                        let filename = AbsPathBuf::assert(PathBuf::from(&filename));
-                        let res = res.entry(package_id.repr.clone()).or_default();
-                        res.proc_macro_dylib_path = Some(filename);
+                    res.envs = env;
+                }
+                Message::CompilerArtifact(message) => {
+                    progress(format!("metadata {}", message.target.name));
+
+                    if message.target.kind.contains(&"proc-macro".to_string()) {
+                        let package_id = message.package_id;
+                        // Skip rmeta file
+                        if let Some(filename) = message.filenames.iter().find(|name| is_dylib(name))
+                        {
+                            let filename = AbsPathBuf::assert(PathBuf::from(&filename));
+                            let res = res.entry(package_id.repr.clone()).or_default();
+                            res.proc_macro_dylib_path = Some(filename);
+                        }
                     }
                 }
+                Message::CompilerMessage(message) => {
+                    progress(message.target.name.clone());
+                }
+                Message::BuildFinished(_) => {}
+                Message::TextLine(_) => {}
+                _ => {}
             }
-            Message::CompilerMessage(message) => {
-                progress(message.target.name.clone());
-            }
-            Message::BuildFinished(_) => {}
-            Message::TextLine(_) => {}
-            _ => {}
         }
     }
 
diff --git a/crates/rust-analyzer/src/caps.rs b/crates/rust-analyzer/src/caps.rs
index 7a5bcb8c7f..aa48c455cb 100644
--- a/crates/rust-analyzer/src/caps.rs
+++ b/crates/rust-analyzer/src/caps.rs
@@ -33,7 +33,7 @@ pub fn server_capabilities(client_caps: &ClientCapabilities) -> ServerCapabiliti
         hover_provider: Some(HoverProviderCapability::Simple(true)),
         completion_provider: Some(CompletionOptions {
             resolve_provider: completions_resolve_provider(client_caps),
-            trigger_characters: Some(vec![":".to_string(), ".".to_string(), "'".to_string()]),
+            trigger_characters: Some(vec![":".to_string(), ".".to_string()]),
             all_commit_characters: None,
             completion_item: None,
             work_done_progress_options: WorkDoneProgressOptions { work_done_progress: None },
diff --git a/crates/rust-analyzer/src/config.rs b/crates/rust-analyzer/src/config.rs
index 5c88c3a9b8..8f541976ec 100644
--- a/crates/rust-analyzer/src/config.rs
+++ b/crates/rust-analyzer/src/config.rs
@@ -10,9 +10,10 @@
 use std::{ffi::OsString, iter, path::PathBuf};
 
 use flycheck::FlycheckConfig;
+use hir::PrefixKind;
 use ide::{AssistConfig, CompletionConfig, DiagnosticsConfig, HoverConfig, InlayHintsConfig};
 use ide_db::helpers::{
-    insert_use::{InsertUseConfig, MergeBehavior, PrefixKind},
+    insert_use::{InsertUseConfig, MergeBehavior},
     SnippetCap,
 };
 use lsp_types::{ClientCapabilities, MarkupKind};
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index c63a0eaeaf..984790d354 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -242,8 +242,11 @@ impl GlobalState {
                                 }
                                 BuildDataProgress::End(collector) => {
                                     self.fetch_build_data_completed();
-                                    let workspaces =
-                                        (*self.workspaces).clone().into_iter().map(Ok).collect();
+                                    let workspaces = (*self.workspaces)
+                                        .clone()
+                                        .into_iter()
+                                        .map(|it| Ok(it))
+                                        .collect();
                                     self.switch_workspaces(workspaces, Some(collector));
                                     (Some(Progress::End), None)
                                 }
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 76fdbcdddb..aa8504c3d5 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -237,7 +237,7 @@ impl GlobalState {
             None => None,
         };
 
-        if *self.workspaces == workspaces && self.workspace_build_data == workspace_build_data {
+        if &*self.workspaces == &workspaces && self.workspace_build_data == workspace_build_data {
             return;
         }
 
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs
index c1ca7ff9b6..1ddea92788 100644
--- a/crates/rust-analyzer/src/to_proto.rs
+++ b/crates/rust-analyzer/src/to_proto.rs
@@ -1073,11 +1073,9 @@ pub(crate) fn rename_error(err: RenameError) -> crate::LspError {
 mod tests {
     use std::sync::Arc;
 
+    use hir::PrefixKind;
     use ide::Analysis;
-    use ide_db::helpers::{
-        insert_use::{InsertUseConfig, PrefixKind},
-        SnippetCap,
-    };
+    use ide_db::helpers::{insert_use::InsertUseConfig, SnippetCap};
 
     use super::*;
 
diff --git a/crates/syntax/src/algo.rs b/crates/syntax/src/algo.rs
index a153a9e1c3..82ebf9037c 100644
--- a/crates/syntax/src/algo.rs
+++ b/crates/syntax/src/algo.rs
@@ -567,7 +567,7 @@ impl<'a> SyntaxRewriter<'a> {
 
 fn element_to_green(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
     match element {
-        NodeOrToken::Node(it) => NodeOrToken::Node(it.green()),
+        NodeOrToken::Node(it) => NodeOrToken::Node(it.green().to_owned()),
         NodeOrToken::Token(it) => NodeOrToken::Token(it.green().to_owned()),
     }
 }
@@ -625,7 +625,7 @@ fn position_of_child(parent: &SyntaxNode, child: SyntaxElement) -> usize {
 
 fn to_green_element(element: SyntaxElement) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> {
     match element {
-        NodeOrToken::Node(it) => it.green().into(),
+        NodeOrToken::Node(it) => it.green().to_owned().into(),
         NodeOrToken::Token(it) => it.green().to_owned().into(),
     }
 }
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
index 347862b8a4..64fac13a73 100644
--- a/crates/syntax/src/ast/edit.rs
+++ b/crates/syntax/src/ast/edit.rs
@@ -333,7 +333,8 @@ impl ast::Use {
             .and_then(ast::Whitespace::cast);
         if let Some(next_ws) = next_ws {
             let ws_text = next_ws.syntax().text();
-            if let Some(rest) = ws_text.strip_prefix('\n') {
+            if ws_text.starts_with('\n') {
+                let rest = &ws_text[1..];
                 if rest.is_empty() {
                     res.delete(next_ws.syntax())
                 } else {
@@ -461,7 +462,8 @@ impl ast::MatchArmList {
         let end = if let Some(comma) = start
             .siblings_with_tokens(Direction::Next)
             .skip(1)
-            .find(|it| !it.kind().is_trivia())
+            .skip_while(|it| it.kind().is_trivia())
+            .next()
             .filter(|it| it.kind() == T![,])
         {
             comma
@@ -595,7 +597,7 @@ impl IndentLevel {
     pub fn from_node(node: &SyntaxNode) -> IndentLevel {
         match node.first_token() {
             Some(it) => Self::from_token(&it),
-            None => IndentLevel(0),
+            None => return IndentLevel(0),
         }
     }
 
diff --git a/crates/syntax/src/ast/expr_ext.rs b/crates/syntax/src/ast/expr_ext.rs
index 6317d84ba3..636ce166d7 100644
--- a/crates/syntax/src/ast/expr_ext.rs
+++ b/crates/syntax/src/ast/expr_ext.rs
@@ -11,16 +11,16 @@ impl ast::AttrsOwner for ast::Expr {}
 
 impl ast::Expr {
     pub fn is_block_like(&self) -> bool {
-        matches!(
-            self,
+        match self {
             ast::Expr::IfExpr(_)
-                | ast::Expr::LoopExpr(_)
-                | ast::Expr::ForExpr(_)
-                | ast::Expr::WhileExpr(_)
-                | ast::Expr::BlockExpr(_)
-                | ast::Expr::MatchExpr(_)
-                | ast::Expr::EffectExpr(_)
-        )
+            | ast::Expr::LoopExpr(_)
+            | ast::Expr::ForExpr(_)
+            | ast::Expr::WhileExpr(_)
+            | ast::Expr::BlockExpr(_)
+            | ast::Expr::MatchExpr(_)
+            | ast::Expr::EffectExpr(_) => true,
+            _ => false,
+        }
     }
 
     pub fn name_ref(&self) -> Option<ast::NameRef> {
@@ -151,20 +151,20 @@ pub enum BinOp {
 
 impl BinOp {
     pub fn is_assignment(self) -> bool {
-        matches!(
-            self,
+        match self {
             BinOp::Assignment
-                | BinOp::AddAssign
-                | BinOp::DivAssign
-                | BinOp::MulAssign
-                | BinOp::RemAssign
-                | BinOp::ShrAssign
-                | BinOp::ShlAssign
-                | BinOp::SubAssign
-                | BinOp::BitOrAssign
-                | BinOp::BitAndAssign
-                | BinOp::BitXorAssign
-        )
+            | BinOp::AddAssign
+            | BinOp::DivAssign
+            | BinOp::MulAssign
+            | BinOp::RemAssign
+            | BinOp::ShrAssign
+            | BinOp::ShlAssign
+            | BinOp::SubAssign
+            | BinOp::BitOrAssign
+            | BinOp::BitAndAssign
+            | BinOp::BitXorAssign => true,
+            _ => false,
+        }
     }
 }
 
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index 7049affd95..810c8d4c86 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -532,7 +532,7 @@ fn ast_from_text<N: AstNode>(text: &str) -> N {
 }
 
 fn unroot(n: SyntaxNode) -> SyntaxNode {
-    SyntaxNode::new_root(n.green())
+    SyntaxNode::new_root(n.green().to_owned())
 }
 
 pub mod tokens {
diff --git a/crates/syntax/src/ast/node_ext.rs b/crates/syntax/src/ast/node_ext.rs
index bdf907a21a..42a7b9c2a6 100644
--- a/crates/syntax/src/ast/node_ext.rs
+++ b/crates/syntax/src/ast/node_ext.rs
@@ -58,7 +58,10 @@ impl From<ast::MacroDef> for Macro {
 
 impl AstNode for Macro {
     fn can_cast(kind: SyntaxKind) -> bool {
-        matches!(kind, SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF)
+        match kind {
+            SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF => true,
+            _ => false,
+        }
     }
     fn cast(syntax: SyntaxNode) -> Option<Self> {
         let res = match syntax.kind() {
@@ -459,8 +462,10 @@ impl ast::FieldExpr {
     pub fn field_access(&self) -> Option<FieldKind> {
         if let Some(nr) = self.name_ref() {
             Some(FieldKind::Name(nr))
+        } else if let Some(tok) = self.index_token() {
+            Some(FieldKind::Index(tok))
         } else {
-            self.index_token().map(FieldKind::Index)
+            None
         }
     }
 }
@@ -477,10 +482,16 @@ impl ast::SlicePat {
         let prefix = args
             .peeking_take_while(|p| match p {
                 ast::Pat::RestPat(_) => false,
-                ast::Pat::IdentPat(bp) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
+                ast::Pat::IdentPat(bp) => match bp.pat() {
+                    Some(ast::Pat::RestPat(_)) => false,
+                    _ => true,
+                },
                 ast::Pat::RefPat(rp) => match rp.pat() {
                     Some(ast::Pat::RestPat(_)) => false,
-                    Some(ast::Pat::IdentPat(bp)) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
+                    Some(ast::Pat::IdentPat(bp)) => match bp.pat() {
+                        Some(ast::Pat::RestPat(_)) => false,
+                        _ => true,
+                    },
                     _ => true,
                 },
                 _ => true,
diff --git a/crates/syntax/src/ast/token_ext.rs b/crates/syntax/src/ast/token_ext.rs
index 090282d280..6c242d1265 100644
--- a/crates/syntax/src/ast/token_ext.rs
+++ b/crates/syntax/src/ast/token_ext.rs
@@ -494,8 +494,9 @@ pub trait HasFormatSpecifier: AstToken {
                 }
                 _ => {
                     while let Some((_, Ok(next_char))) = chars.peek() {
-                        if next_char == &'{' {
-                            break;
+                        match next_char {
+                            '{' => break,
+                            _ => {}
                         }
                         chars.next();
                     }
diff --git a/crates/syntax/src/fuzz.rs b/crates/syntax/src/fuzz.rs
index aa84239d2f..fbb97aa273 100644
--- a/crates/syntax/src/fuzz.rs
+++ b/crates/syntax/src/fuzz.rs
@@ -43,7 +43,7 @@ impl CheckReparse {
             TextRange::at(delete_start.try_into().unwrap(), delete_len.try_into().unwrap());
         let edited_text =
             format!("{}{}{}", &text[..delete_start], &insert, &text[delete_start + delete_len..]);
-        let edit = Indel { insert, delete };
+        let edit = Indel { delete, insert };
         Some(CheckReparse { text, edit, edited_text })
     }
 
diff --git a/crates/syntax/src/validation.rs b/crates/syntax/src/validation.rs
index bbe802174a..3e216fb70b 100644
--- a/crates/syntax/src/validation.rs
+++ b/crates/syntax/src/validation.rs
@@ -297,7 +297,7 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
                 }
             };
         }
-        None
+        return None;
     }
 
     fn all_supers(path: &ast::Path) -> bool {
@@ -314,7 +314,7 @@ fn validate_path_keywords(segment: ast::PathSegment, errors: &mut Vec<SyntaxErro
             return all_supers(subpath);
         }
 
-        true
+        return true;
     }
 }
 
diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs
index bed44d6005..9d9a01e30a 100644
--- a/crates/tt/src/lib.rs
+++ b/crates/tt/src/lib.rs
@@ -239,8 +239,9 @@ impl Subtree {
 
         let mut res = String::new();
         res.push_str(delim.0);
+        let mut iter = self.token_trees.iter();
         let mut last = None;
-        for child in &self.token_trees {
+        while let Some(child) = iter.next() {
             let s = match child {
                 TokenTree::Leaf(it) => {
                     let s = match it {
diff --git a/docs/user/manual.adoc b/docs/user/manual.adoc
index 8656dd1dab..dba2197de9 100644
--- a/docs/user/manual.adoc
+++ b/docs/user/manual.adoc
@@ -516,20 +516,6 @@ See https://github.com/rust-analyzer/rust-project.json-example for a small examp
 
 You can set `RA_LOG` environmental variable to `rust_analyzer=info` to inspect how rust-analyzer handles config and project loading.
 
-== Security
-
-At the moment, rust-analyzer assumes that all code is trusted.
-Here is a **non-exhaustive** list of ways to make rust-analyzer execute arbitrary code:
-
-* proc macros and build scripts are executed by default
-* `.cargo/config` can override `rustc` with an arbitrary executable
-* VS Code plugin reads configuration from project directory, and that can be used to override paths to various executables, like `rustfmt` or `rust-analyzer` itself.
-* rust-analyzer's syntax trees library uses a lot of `unsafe` and hasn't been properly audited for memory safety.
-
-rust-analyzer itself doesn't access the network.
-The VS Code plugin doesn't access the network unless the nightly channel is selected in the settings.
-In that case, the plugin uses the GitHub API to check for and download updates.
-
 == Features
 
 include::./generated_features.adoc[]
diff --git a/xtask/src/codegen/gen_assists_docs.rs b/xtask/src/codegen/gen_assists_docs.rs
index c91716409e..158680993f 100644
--- a/xtask/src/codegen/gen_assists_docs.rs
+++ b/xtask/src/codegen/gen_assists_docs.rs
@@ -154,8 +154,8 @@ fn hide_hash_comments(text: &str) -> String {
 fn reveal_hash_comments(text: &str) -> String {
     text.split('\n') // want final newline
         .map(|it| {
-            if let Some(stripped) = it.strip_prefix("# ") {
-                stripped
+            if it.starts_with("# ") {
+                &it[2..]
             } else if it == "#" {
                 ""
             } else {
diff --git a/xtask/src/codegen/gen_syntax.rs b/xtask/src/codegen/gen_syntax.rs
index ba4b248489..80f26e8f59 100644
--- a/xtask/src/codegen/gen_syntax.rs
+++ b/xtask/src/codegen/gen_syntax.rs
@@ -707,7 +707,7 @@ fn extract_struct_trait(node: &mut AstNodeSrc, trait_name: &str, methods: &[&str
     let mut to_remove = Vec::new();
     for (i, field) in node.fields.iter().enumerate() {
         let method_name = field.method_name().to_string();
-        if methods.iter().any(|&it| it == method_name) {
+        if methods.iter().any(|&it| it == &method_name) {
             to_remove.push(i);
         }
     }
diff --git a/xtask/src/main.rs b/xtask/src/main.rs
index 960927fc00..915aae71a3 100644
--- a/xtask/src/main.rs
+++ b/xtask/src/main.rs
@@ -37,7 +37,7 @@ fn main() -> Result<()> {
     match flags.subcommand {
         flags::XtaskCmd::Help(_) => {
             println!("{}", flags::Xtask::HELP);
-            Ok(())
+            return Ok(());
         }
         flags::XtaskCmd::Install(cmd) => cmd.run(),
         flags::XtaskCmd::FuzzTests(_) => run_fuzzer(),
diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs
index b0b76b8aac..97395738b0 100644
--- a/xtask/src/metrics.rs
+++ b/xtask/src/metrics.rs
@@ -167,7 +167,7 @@ impl Host {
 
         return Ok(Host { os, cpu, mem });
 
-        fn read_field(path: &str, field: &str) -> Result<String> {
+        fn read_field<'a>(path: &str, field: &str) -> Result<String> {
             let text = read_file(path)?;
 
             let line = text
diff --git a/xtask/src/tidy.rs b/xtask/src/tidy.rs
index 50d9efccd2..1352d12189 100644
--- a/xtask/src/tidy.rs
+++ b/xtask/src/tidy.rs
@@ -193,7 +193,7 @@ https://github.blog/2015-06-08-how-to-undo-almost-anything-with-git/#redo-after-
     }
 }
 
-fn deny_clippy(path: &Path, text: &str) {
+fn deny_clippy(path: &PathBuf, text: &String) {
     let ignore = &[
         // The documentation in string literals may contain anything for its own purposes
         "ide_completion/src/generated_lint_completions.rs",


Test patch:
diff --git a/crates/hir_def/src/nameres/tests/macros.rs b/crates/hir_def/src/nameres/tests/macros.rs
index 6d3cb8d7af..d59d3c0db1 100644
--- a/crates/hir_def/src/nameres/tests/macros.rs
+++ b/crates/hir_def/src/nameres/tests/macros.rs
@@ -712,27 +712,6 @@ b! { static = #[] ();}
     );
 }
 
-#[test]
-fn macros_defining_macros() {
-    check(
-        r#"
-macro_rules! item {
-    ($item:item) => { $item }
-}
-
-item! {
-    macro_rules! indirect_macro { () => { struct S {} } }
-}
-
-indirect_macro!();
-    "#,
-        expect![[r#"
-            crate
-            S: t
-        "#]],
-    );
-}
-
 #[test]
 fn resolves_proc_macros() {
     check(
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index ad283c1e04..0a4141e698 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -369,72 +369,3 @@ fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) {
     actual.push('\n');
     expect.assert_eq(&actual);
 }
-
-#[test]
-fn salsa_bug() {
-    let (mut db, pos) = TestDB::with_position(
-        "
-        //- /lib.rs
-        trait Index {
-            type Output;
-        }
-
-        type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
-
-        pub trait UnificationStoreBase: Index<Output = Key<Self>> {
-            type Key;
-
-            fn len(&self) -> usize;
-        }
-
-        pub trait UnificationStoreMut: UnificationStoreBase {
-            fn push(&mut self, value: Self::Key);
-        }
-
-        fn main() {
-            let x = 1;
-            x.push(1);$0
-        }
-    ",
-    );
-
-    let module = db.module_for_file(pos.file_id);
-    let crate_def_map = module.def_map(&db);
-    visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-        db.infer(def);
-    });
-
-    let new_text = "
-        //- /lib.rs
-        trait Index {
-            type Output;
-        }
-
-        type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
-
-        pub trait UnificationStoreBase: Index<Output = Key<Self>> {
-            type Key;
-
-            fn len(&self) -> usize;
-        }
-
-        pub trait UnificationStoreMut: UnificationStoreBase {
-            fn push(&mut self, value: Self::Key);
-        }
-
-        fn main() {
-
-            let x = 1;
-            x.push(1);
-        }
-    "
-    .to_string();
-
-    db.set_file_text(pos.file_id, Arc::new(new_text));
-
-    let module = db.module_for_file(pos.file_id);
-    let crate_def_map = module.def_map(&db);
-    visit_module(&db, &crate_def_map, module.local_id, &mut |def| {
-        db.infer(def);
-    });
-}
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs
index 12951fb16c..c1e605740a 100644
--- a/crates/hir_ty/src/tests/macros.rs
+++ b/crates/hir_ty/src/tests/macros.rs
@@ -606,29 +606,6 @@ fn bar() -> u32 {0}
     );
 }
 
-#[test]
-fn infer_builtin_macros_include_child_mod() {
-    check_types(
-        r#"
-//- /main.rs
-#[rustc_builtin_macro]
-macro_rules! include {() => {}}
-
-include!("f/foo.rs");
-
-fn main() {
-    bar::bar();
-}          //^ u32
-
-//- /f/foo.rs
-pub mod bar;
-
-//- /f/bar.rs
-pub fn bar() -> u32 {0}
-"#,
-    );
-}
-
 #[test]
 fn infer_builtin_macros_include_str() {
     check_types(
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs
index 85a28e76b2..5da19ba5f0 100644
--- a/crates/hir_ty/src/tests/patterns.rs
+++ b/crates/hir_ty/src/tests/patterns.rs
@@ -656,28 +656,6 @@ fn slice_tail_pattern() {
 
 #[test]
 fn box_pattern() {
-    check_infer(
-        r#"
-        pub struct Global;
-        #[lang = "owned_box"]
-        pub struct Box<T, A = Global>(T);
-
-        fn foo(params: Box<i32>) {
-            match params {
-                box integer => {}
-            }
-        }
-        "#,
-        expect![[r#"
-            83..89 'params': Box<i32, Global>
-            101..155 '{     ...   } }': ()
-            107..153 'match ...     }': ()
-            113..119 'params': Box<i32, Global>
-            130..141 'box integer': Box<i32, Global>
-            134..141 'integer': i32
-            145..147 '{}': ()
-        "#]],
-    );
     check_infer(
         r#"
         #[lang = "owned_box"]
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 37cd04c6f7..8f2bdffc03 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -2271,56 +2271,6 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> {
     );
 }
 
-#[test]
-fn unselected_projection_in_trait_env_cycle_3() {
-    // this is a cycle for rustc; we currently accept it
-    check_types(
-        r#"
-//- /main.rs
-trait Trait {
-    type Item;
-    type OtherItem;
-}
-
-fn test<T>() where T: Trait<OtherItem = T::Item> {
-    let x: T::Item = no_matter;
-}                   //^ Trait::Item<T>
-"#,
-    );
-}
-
-#[test]
-fn unselected_projection_in_trait_env_no_cycle() {
-    // this is not a cycle
-    check_types(
-        r#"
-//- /main.rs
-trait Index {
-    type Output;
-}
-
-type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
-
-pub trait UnificationStoreBase: Index<Output = Key<Self>> {
-    type Key;
-
-    fn len(&self) -> usize;
-}
-
-pub trait UnificationStoreMut: UnificationStoreBase {
-    fn push(&mut self, value: Self::Key);
-}
-
-fn test<T>(t: T) where T: UnificationStoreMut {
-    let x;
-    t.push(x);
-    let y: Key<T>;
-    (x, y);
-}      //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>)
-"#,
-    );
-}
-
 #[test]
 fn inline_assoc_type_bounds_1() {
     check_types(
diff --git a/crates/mbe/src/tests/expand.rs b/crates/mbe/src/tests/expand.rs
index 8951f38137..2cce62781a 100644
--- a/crates/mbe/src/tests/expand.rs
+++ b/crates/mbe/src/tests/expand.rs
@@ -1225,7 +1225,8 @@ macro_rules! m {
     )
     .expand_statements(r#"m!(C("0"))"#)
     .descendants()
-    .any(|token| token.kind() == ERROR));
+    .find(|token| token.kind() == ERROR)
+    .is_some());
 }
 
 #[test]
diff --git a/crates/rust-analyzer/tests/rust-analyzer/support.rs b/crates/rust-analyzer/tests/rust-analyzer/support.rs
index 95bf26f016..cd0c914817 100644
--- a/crates/rust-analyzer/tests/rust-analyzer/support.rs
+++ b/crates/rust-analyzer/tests/rust-analyzer/support.rs
@@ -54,7 +54,7 @@ impl<'a> Project<'a> {
     }
 
     pub(crate) fn server(self) -> Server {
-        let tmp_dir = self.tmp_dir.unwrap_or_else(TestDir::new);
+        let tmp_dir = self.tmp_dir.unwrap_or_else(|| TestDir::new());
         static INIT: Once = Once::new();
         INIT.call_once(|| {
             env_logger::builder().is_test(true).parse_env("RA_LOG").try_init().unwrap();
diff --git a/xtask/src/codegen/gen_parser_tests.rs b/xtask/src/codegen/gen_parser_tests.rs
index 2fecb9b5bd..096590653f 100644
--- a/xtask/src/codegen/gen_parser_tests.rs
+++ b/xtask/src/codegen/gen_parser_tests.rs
@@ -60,10 +60,12 @@ fn collect_tests(s: &str) -> Vec<Test> {
     let mut res = Vec::new();
     for comment_block in extract_comment_blocks(s) {
         let first_line = &comment_block[0];
-        let (name, ok) = if let Some(name) = first_line.strip_prefix("test ") {
-            (name.to_string(), true)
-        } else if let Some(name) = first_line.strip_prefix("test_err ") {
-            (name.to_string(), false)
+        let (name, ok) = if first_line.starts_with("test ") {
+            let name = first_line["test ".len()..].to_string();
+            (name, true)
+        } else if first_line.starts_with("test_err ") {
+            let name = first_line["test_err ".len()..].to_string();
+            (name, false)
         } else {
             continue;
         };