diff --git a/Cargo.lock b/Cargo.lock
index 333ea6fc91ae..89678bce5e17 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1,7 +1,5 @@
 # This file is automatically @generated by Cargo.
 # It is not intended for manual editing.
-version = 3
-
 [[package]]
 name = "addr2line"
 version = "0.15.2"
@@ -47,11 +45,17 @@ version = "0.12.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
 
+[[package]]
+name = "array_iterator"
+version = "1.8.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "769af754c2afad9a410ffdfdae3c0e48b98fba3d72bfe0b5316b277e7d1566e1"
+
 [[package]]
 name = "arrayvec"
-version = "0.7.1"
+version = "0.5.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd"
+checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
 
 [[package]]
 name = "atty"
@@ -611,6 +615,7 @@ dependencies = [
 name = "ide_completion"
 version = "0.0.0"
 dependencies = [
+ "array_iterator",
  "base_db",
  "cov-mark",
  "either",
@@ -813,9 +818,9 @@ dependencies = [
 
 [[package]]
 name = "lsp-server"
-version = "0.5.2"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c351c75989da23b355226dc188dc2b52538a7f4f218d70fd7393c6b62b110444"
+checksum = "69b18dfe0e4a380b872aa79d8e0ee6c3d7a9682466e84b83ad807c88b3545f79"
 dependencies = [
  "crossbeam-channel",
  "log",
diff --git a/Cargo.toml b/Cargo.toml
index 4d6908fa93e9..fd3d9781fd3e 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -1,5 +1,5 @@
 [workspace]
-resolver = "2"
+#resolver = "2"
 members = ["xtask/", "lib/*", "crates/*"]
 exclude = ["crates/proc_macro_test/imp"]
 
diff --git a/crates/hir/Cargo.toml b/crates/hir/Cargo.toml
index 192490620150..c418d6112cb8 100644
--- a/crates/hir/Cargo.toml
+++ b/crates/hir/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
 log = "0.4.8"
 rustc-hash = "1.1.0"
 either = "1.5.3"
-arrayvec = "0.7"
+arrayvec = "0.5.1"
 itertools = "0.10.0"
 smallvec = "1.4.0"
 once_cell = "1"
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 9c74d8c5f744..406c8a26c0b6 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2669,7 +2669,7 @@ pub enum ScopeDef {
 }
 
 impl ScopeDef {
-    pub fn all_items(def: PerNs) -> ArrayVec<Self, 3> {
+    pub fn all_items(def: PerNs) -> ArrayVec<[Self; 3]> {
         let mut items = ArrayVec::new();
 
         match (def.take_types(), def.take_values()) {
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index cc320227f803..d2f2af3c43a6 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -51,14 +51,12 @@ impl PathResolution {
             PathResolution::Def(ModuleDef::BuiltinType(builtin)) => {
                 Some(TypeNs::BuiltinType((*builtin).into()))
             }
-            PathResolution::Def(
-                ModuleDef::Const(_)
-                | ModuleDef::Variant(_)
-                | ModuleDef::Function(_)
-                | ModuleDef::Module(_)
-                | ModuleDef::Static(_)
-                | ModuleDef::Trait(_),
-            ) => None,
+            PathResolution::Def(ModuleDef::Const(_))
+            | PathResolution::Def(ModuleDef::Variant(_))
+            | PathResolution::Def(ModuleDef::Function(_))
+            | PathResolution::Def(ModuleDef::Module(_))
+            | PathResolution::Def(ModuleDef::Static(_))
+            | PathResolution::Def(ModuleDef::Trait(_)) => None,
             PathResolution::Def(ModuleDef::TypeAlias(alias)) => {
                 Some(TypeNs::TypeAliasId((*alias).into()))
             }
@@ -67,7 +65,8 @@ impl PathResolution {
             }
             PathResolution::TypeParam(param) => Some(TypeNs::GenericParam((*param).into())),
             PathResolution::SelfType(impl_def) => Some(TypeNs::SelfType((*impl_def).into())),
-            PathResolution::AssocItem(AssocItem::Const(_) | AssocItem::Function(_)) => None,
+            PathResolution::AssocItem(AssocItem::Const(_))
+            | PathResolution::AssocItem(AssocItem::Function(_)) => None,
             PathResolution::AssocItem(AssocItem::TypeAlias(alias)) => {
                 Some(TypeNs::TypeAliasId((*alias).into()))
             }
diff --git a/crates/hir_def/src/item_tree/pretty.rs b/crates/hir_def/src/item_tree/pretty.rs
index 603c594f2aa4..d2ef8e50d39a 100644
--- a/crates/hir_def/src/item_tree/pretty.rs
+++ b/crates/hir_def/src/item_tree/pretty.rs
@@ -65,7 +65,7 @@ impl<'a> Printer<'a> {
     fn blank(&mut self) {
         let mut iter = self.buf.chars().rev().fuse();
         match (iter.next(), iter.next()) {
-            (Some('\n'), Some('\n') | None) | (None, None) => {}
+            (Some('\n'), Some('\n')) | (Some('\n'), None) | (None, None) => {}
             (Some('\n'), Some(_)) => {
                 self.buf.push('\n');
             }
@@ -79,7 +79,7 @@ impl<'a> Printer<'a> {
 
     fn whitespace(&mut self) {
         match self.buf.chars().next_back() {
-            None | Some('\n' | ' ') => {}
+            None | Some('\n') | Some(' ') => {}
             _ => self.buf.push(' '),
         }
     }
@@ -721,18 +721,20 @@ impl<'a> Printer<'a> {
 
 impl<'a> Write for Printer<'a> {
     fn write_str(&mut self, s: &str) -> fmt::Result {
-        for line in s.split_inclusive('\n') {
+        match self.buf.chars().last() {
+           Some('\n') | None => {}
+           _ => self.buf.push('\n'),
+        }
+
+        for line in s.split('\n') {
             if self.needs_indent {
-                match self.buf.chars().last() {
-                    Some('\n') | None => {}
-                    _ => self.buf.push('\n'),
-                }
+                self.buf.push('\n');
                 self.buf.push_str(&"    ".repeat(self.indent_level));
                 self.needs_indent = false;
             }
 
             self.buf.push_str(line);
-            self.needs_indent = line.ends_with('\n');
+            self.needs_indent = true;
         }
 
         Ok(())
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 79452bba548f..dd0155a42f88 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -1270,7 +1270,7 @@ impl DefCollector<'_> {
         for directive in &self.unresolved_imports {
             if let ImportSource::Import { id: import, use_tree } = &directive.import.source {
                 match (directive.import.path.segments().first(), &directive.import.path.kind) {
-                    (Some(krate), PathKind::Plain | PathKind::Abs) => {
+                    (Some(krate), PathKind::Plain) | (Some(krate), PathKind::Abs) => {
                         if diagnosed_extern_crates.contains(krate) {
                             continue;
                         }
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index a11439c3b54b..1841fe98968c 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -605,7 +605,8 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
         ModuleDefId::ConstId(it) => ValueNs::ConstId(it),
         ModuleDefId::StaticId(it) => ValueNs::StaticId(it),
 
-        ModuleDefId::AdtId(AdtId::EnumId(_) | AdtId::UnionId(_))
+        ModuleDefId::AdtId(AdtId::EnumId(_))
+        | ModuleDefId::AdtId(AdtId::UnionId(_))
         | ModuleDefId::TraitId(_)
         | ModuleDefId::TypeAliasId(_)
         | ModuleDefId::BuiltinType(_)
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs
index 7d335582ed02..512dcd3c3642 100644
--- a/crates/hir_def/src/visibility.rs
+++ b/crates/hir_def/src/visibility.rs
@@ -187,8 +187,9 @@ impl Visibility {
     /// visible in unrelated modules).
     pub(crate) fn max(self, other: Visibility, def_map: &DefMap) -> Option<Visibility> {
         match (self, other) {
-            (Visibility::Module(_) | Visibility::Public, Visibility::Public)
-            | (Visibility::Public, Visibility::Module(_)) => Some(Visibility::Public),
+            (Visibility::Module(_), Visibility::Public)
+            | (Visibility::Public, Visibility::Module(_))
+            | (Visibility::Public, Visibility::Public) => Some(Visibility::Public),
             (Visibility::Module(mod_a), Visibility::Module(mod_b)) => {
                 if mod_a.krate != mod_b.krate {
                     return None;
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs
index 848522411557..05c6c3fb1644 100644
--- a/crates/hir_expand/src/hygiene.rs
+++ b/crates/hir_expand/src/hygiene.rs
@@ -146,11 +146,10 @@ impl HygieneInfo {
                 (&self.macro_arg.1, InFile::new(loc.kind.file_id(), arg_start))
             }
             mbe::Origin::Def => match (&*self.macro_def, self.def_start) {
-                (
-                    TokenExpander::MacroDef { def_site_token_map, .. }
-                    | TokenExpander::MacroRules { def_site_token_map, .. },
-                    Some(tt),
-                ) => (def_site_token_map, tt),
+                (TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt))
+                | (TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt)) => {
+                    (def_site_token_map, tt)
+                }
                 _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
             },
         };
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index c31426d7cc7e..33107aa2484f 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -368,11 +368,10 @@ impl ExpansionInfo {
         let (token_map, tt) = match origin {
             mbe::Origin::Call => (&self.macro_arg.1, self.arg.clone()),
             mbe::Origin::Def => match (&*self.macro_def, self.def.as_ref()) {
-                (
-                    db::TokenExpander::MacroRules { def_site_token_map, .. }
-                    | db::TokenExpander::MacroDef { def_site_token_map, .. },
-                    Some(tt),
-                ) => (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone())),
+                (db::TokenExpander::MacroRules { def_site_token_map, .. }, Some(tt))
+                | (db::TokenExpander::MacroDef { def_site_token_map, .. }, Some(tt)) => {
+                    (def_site_token_map, tt.as_ref().map(|tt| tt.syntax().clone()))
+                }
                 _ => panic!("`Origin::Def` used with non-`macro_rules!` macro"),
             },
         };
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index f8280e0c5c40..f410432fa898 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -11,7 +11,7 @@ doctest = false
 [dependencies]
 cov-mark = "2.0.0-pre.1"
 itertools = "0.10.0"
-arrayvec = "0.7"
+arrayvec = "0.5.1"
 smallvec = "1.2.0"
 ena = "0.14.0"
 log = "0.4.8"
diff --git a/crates/hir_ty/src/consteval.rs b/crates/hir_ty/src/consteval.rs
index ab1afce081f3..6f0bf8f8c6c9 100644
--- a/crates/hir_ty/src/consteval.rs
+++ b/crates/hir_ty/src/consteval.rs
@@ -38,7 +38,8 @@ impl ConstExt for Const {
 // FIXME: support more than just evaluating literals
 pub fn eval_usize(expr: &Expr) -> Option<u64> {
     match expr {
-        Expr::Literal(Literal::Uint(v, None | Some(BuiltinUint::Usize))) => (*v).try_into().ok(),
+        Expr::Literal(Literal::Uint(v, None))
+        | Expr::Literal(Literal::Uint(v, Some(BuiltinUint::Usize))) => (*v).try_into().ok(),
         _ => None,
     }
 }
diff --git a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
index e3d640a7969e..471cd49210b0 100644
--- a/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
+++ b/crates/hir_ty/src/diagnostics/match_check/deconstruct_pat.rs
@@ -84,7 +84,10 @@ impl IntRange {
     #[inline]
     fn is_integral(ty: &Ty) -> bool {
         match ty.kind(&Interner) {
-            TyKind::Scalar(Scalar::Char | Scalar::Int(_) | Scalar::Uint(_) | Scalar::Bool) => true,
+            TyKind::Scalar(Scalar::Char)
+            | TyKind::Scalar(Scalar::Int(_))
+            | TyKind::Scalar(Scalar::Uint(_))
+            | TyKind::Scalar(Scalar::Bool) => true,
             _ => false,
         }
     }
@@ -378,7 +381,7 @@ impl Constructor {
             // Wildcards cover anything
             (_, Wildcard) => true,
             // The missing ctors are not covered by anything in the matrix except wildcards.
-            (Missing | Wildcard, _) => false,
+            (Missing, _) | (Wildcard, _) => false,
 
             (Single, Single) => true,
             (Variant(self_id), Variant(other_id)) => self_id == other_id,
@@ -520,7 +523,7 @@ impl SplitWildcard {
                 }
             }
             TyKind::Scalar(Scalar::Char) => unhandled(),
-            TyKind::Scalar(Scalar::Int(..) | Scalar::Uint(..)) => unhandled(),
+            TyKind::Scalar(Scalar::Int(..)) | TyKind::Scalar(Scalar::Uint(..)) => unhandled(),
             TyKind::Never if !cx.feature_exhaustive_patterns() && !pcx.is_top_level => {
                 smallvec![NonExhaustive]
             }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index d2e999a730f7..8a0d0d38c8c4 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -71,7 +71,11 @@ impl CoerceMany {
         // pointers to have a chance at getting a match. See
         // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
         let sig = match (self.expected_ty.kind(&Interner), expr_ty.kind(&Interner)) {
-            (TyKind::FnDef(..) | TyKind::Closure(..), TyKind::FnDef(..) | TyKind::Closure(..)) => {
+            (TyKind::FnDef(..), TyKind::FnDef(..)) |
+(TyKind::FnDef(..), TyKind::Closure(..)) |
+            (TyKind::Closure(..), TyKind::FnDef(..)) |
+(TyKind::Closure(..), TyKind::Closure(..))
+ => {
                 // FIXME: we're ignoring safety here. To be more correct, if we have one FnDef and one Closure,
                 // we should be coercing the closure to a fn pointer of the safety of the FnDef
                 cov_mark::hit!(coerce_fn_reification);
@@ -611,7 +615,8 @@ fn safe_to_unsafe_fn_ty(fn_ty: FnPointer) -> FnPointer {
 
 fn coerce_mutabilities(from: Mutability, to: Mutability) -> Result<(), TypeError> {
     match (from, to) {
-        (Mutability::Mut, Mutability::Mut | Mutability::Not)
+        (Mutability::Mut, Mutability::Mut)
+        | (Mutability::Mut, Mutability::Not)
         | (Mutability::Not, Mutability::Not) => Ok(()),
         (Mutability::Not, Mutability::Mut) => Err(TypeError),
     }
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index f1bc6895c82c..576705047233 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -623,11 +623,11 @@ impl<'a> InferenceContext<'a> {
                     UnaryOp::Neg => {
                         match inner_ty.kind(&Interner) {
                             // Fast path for builtins
-                            TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_))
-                            | TyKind::InferenceVar(
-                                _,
-                                TyVariableKind::Integer | TyVariableKind::Float,
-                            ) => inner_ty,
+                            TyKind::Scalar(Scalar::Int(_))
+                            | TyKind::Scalar(Scalar::Uint(_))
+                            | TyKind::Scalar(Scalar::Float(_))
+                            | TyKind::InferenceVar(_, TyVariableKind::Integer)
+                            | TyKind::InferenceVar(_, TyVariableKind::Float) => inner_ty,
                             // Otherwise we resolve via the std::ops::Neg trait
                             _ => self
                                 .resolve_associated_type(inner_ty, self.resolve_ops_neg_output()),
@@ -636,7 +636,9 @@ impl<'a> InferenceContext<'a> {
                     UnaryOp::Not => {
                         match inner_ty.kind(&Interner) {
                             // Fast path for builtins
-                            TyKind::Scalar(Scalar::Bool | Scalar::Int(_) | Scalar::Uint(_))
+                            TyKind::Scalar(Scalar::Bool)
+                            | TyKind::Scalar(Scalar::Int(_))
+                            | TyKind::Scalar(Scalar::Uint(_))
                             | TyKind::InferenceVar(_, TyVariableKind::Integer) => inner_ty,
                             // Otherwise we resolve via the std::ops::Not trait
                             _ => self
@@ -763,7 +765,7 @@ impl<'a> InferenceContext<'a> {
             Expr::Array(array) => {
                 let elem_ty =
                     match expected.to_option(&mut self.table).as_ref().map(|t| t.kind(&Interner)) {
-                        Some(TyKind::Array(st, _) | TyKind::Slice(st)) => st.clone(),
+                        Some(TyKind::Array(st, _)) | Some(TyKind::Slice(st)) => st.clone(),
                         _ => self.table.new_type_var(),
                     };
                 let mut coerce = CoerceMany::new(elem_ty.clone());
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 86e2d1b8dfab..cd8d78bcfc24 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -301,11 +301,10 @@ fn is_non_ref_pat(body: &hir_def::body::Body, pat: PatId) -> bool {
             Expr::Literal(Literal::String(..)) => false,
             _ => true,
         },
-        Pat::Bind {
-            mode: BindingAnnotation::Mutable | BindingAnnotation::Unannotated,
-            subpat: Some(subpat),
-            ..
-        } => is_non_ref_pat(body, *subpat),
+        Pat::Bind { mode: BindingAnnotation::Mutable, subpat: Some(subpat), .. }
+        | Pat::Bind { mode: BindingAnnotation::Unannotated, subpat: Some(subpat), .. } => {
+            is_non_ref_pat(body, *subpat)
+        }
         Pat::Wild | Pat::Bind { .. } | Pat::Ref { .. } | Pat::Box { .. } | Pat::Missing => false,
     }
 }
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 3d233b1e20ab..133e20b1fa91 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -309,12 +309,12 @@ pub fn def_crates(
     db: &dyn HirDatabase,
     ty: &Ty,
     cur_crate: CrateId,
-) -> Option<ArrayVec<CrateId, 2>> {
+) -> Option<ArrayVec<[CrateId; 2]>> {
     // Types like slice can have inherent impls in several crates, (core and alloc).
     // The corresponding impls are marked with lang items, so we can use them to find the required crates.
     macro_rules! lang_item_crate {
             ($($name:expr),+ $(,)?) => {{
-                let mut v = ArrayVec::<LangItemTarget, 2>::new();
+                let mut v = ArrayVec::<[LangItemTarget; 2]>::new();
                 $(
                     v.extend(db.lang_item(cur_crate, $name.into()));
                 )+
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 5ef6342d57bd..0222de2bc210 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -8,15 +8,17 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
     match op {
         BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
         BinaryOp::Assignment { .. } => TyBuilder::unit(),
-        BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => {
+        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
             // all integer combinations are valid here
             if matches!(
                 lhs_ty.kind(&Interner),
-                TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))
+                TyKind::Scalar(Scalar::Int(_))
+                    | TyKind::Scalar(Scalar::Uint(_))
                     | TyKind::InferenceVar(_, TyVariableKind::Integer)
             ) && matches!(
                 rhs_ty.kind(&Interner),
-                TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_))
+                TyKind::Scalar(Scalar::Int(_))
+                    | TyKind::Scalar(Scalar::Uint(_))
                     | TyKind::InferenceVar(_, TyVariableKind::Integer)
             ) {
                 lhs_ty
@@ -30,15 +32,15 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
             | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
             | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty,
             // ({int}, int) | ({int}, uint)
-            (
-                TyKind::InferenceVar(_, TyVariableKind::Integer),
-                TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)),
-            ) => rhs_ty,
+            (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_)))
+            | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => {
+                rhs_ty
+            }
             // (int, {int}) | (uint, {int})
-            (
-                TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_)),
-                TyKind::InferenceVar(_, TyVariableKind::Integer),
-            ) => lhs_ty,
+            (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer))
+            | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => {
+                lhs_ty
+            }
             // ({float} | float)
             (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => {
                 rhs_ty
@@ -67,15 +69,21 @@ pub(super) fn binary_op_rhs_expectation(op: BinaryOp, lhs_ty: Ty) -> Ty {
         BinaryOp::Assignment { op: None } => lhs_ty,
         BinaryOp::CmpOp(CmpOp::Eq { .. }) => match lhs_ty.kind(&Interner) {
             TyKind::Scalar(_) | TyKind::Str => lhs_ty,
-            TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty,
+            TyKind::InferenceVar(_, TyVariableKind::Integer)
+            | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
             _ => TyKind::Error.intern(&Interner),
         },
-        BinaryOp::ArithOp(ArithOp::Shl | ArithOp::Shr) => TyKind::Error.intern(&Interner),
+        BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
+            TyKind::Error.intern(&Interner)
+        }
         BinaryOp::CmpOp(CmpOp::Ord { .. })
         | BinaryOp::Assignment { op: Some(_) }
         | BinaryOp::ArithOp(_) => match lhs_ty.kind(&Interner) {
-            TyKind::Scalar(Scalar::Int(_) | Scalar::Uint(_) | Scalar::Float(_)) => lhs_ty,
-            TyKind::InferenceVar(_, TyVariableKind::Integer | TyVariableKind::Float) => lhs_ty,
+            TyKind::Scalar(Scalar::Int(_))
+            | TyKind::Scalar(Scalar::Uint(_))
+            | TyKind::Scalar(Scalar::Float(_)) => lhs_ty,
+            TyKind::InferenceVar(_, TyVariableKind::Integer)
+            | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty,
             _ => TyKind::Error.intern(&Interner),
         },
     }
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 076b2c8cba33..fc083a416f3f 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -3,6 +3,7 @@
 
 use std::{array, iter};
 
+use arrayvec::ArrayVec;
 use base_db::CrateId;
 use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
 use hir_def::{
@@ -30,7 +31,8 @@ pub(crate) fn fn_traits(db: &dyn DefDatabase, krate: CrateId) -> impl Iterator<I
         db.lang_item(krate, "fn_mut".into()),
         db.lang_item(krate, "fn_once".into()),
     ];
-    array::IntoIter::new(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
+    // FIXME: Replace ArrayVec when into_iter is a thing on arrays
+    ArrayVec::from(fn_traits).into_iter().flatten().flat_map(|it| it.as_trait())
 }
 
 fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
diff --git a/crates/ide/src/references.rs b/crates/ide/src/references.rs
index 305836f79d83..5279faa753a7 100644
--- a/crates/ide/src/references.rs
+++ b/crates/ide/src/references.rs
@@ -169,7 +169,7 @@ fn retain_adt_literal_usages(
             });
             usages.references.retain(|_, it| !it.is_empty());
         }
-        Definition::ModuleDef(hir::ModuleDef::Adt(_) | hir::ModuleDef::Variant(_)) => {
+        Definition::ModuleDef(hir::ModuleDef::Adt(_)) | Definition::ModuleDef(hir::ModuleDef::Variant(_)) => {
             refs.for_each(|it| {
                 it.retain(|reference| reference.name.as_name_ref().map_or(false, is_lit_name_ref))
             });
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs
index b8e62a1a860d..b4085818733e 100644
--- a/crates/ide/src/syntax_highlighting.rs
+++ b/crates/ide/src/syntax_highlighting.rs
@@ -296,7 +296,7 @@ fn traverse(
                 Some(parent) => {
                     // We only care Name and Name_ref
                     match (token.kind(), parent.kind()) {
-                        (IDENT, NAME | NAME_REF) => parent.into(),
+                        (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(),
                         _ => token.into(),
                     }
                 }
@@ -312,7 +312,7 @@ fn traverse(
                 Some(parent) => {
                     // We only care Name and Name_ref
                     match (token.kind(), parent.kind()) {
-                        (IDENT, NAME | NAME_REF) => parent.into(),
+                        (IDENT, NAME) | (IDENT, NAME_REF) => parent.into(),
                         _ => token.into(),
                     }
                 }
diff --git a/crates/ide_assists/src/handlers/extract_function.rs b/crates/ide_assists/src/handlers/extract_function.rs
index 4f0b1f5b7905..1a85dbd80161 100644
--- a/crates/ide_assists/src/handlers/extract_function.rs
+++ b/crates/ide_assists/src/handlers/extract_function.rs
@@ -1407,7 +1407,7 @@ fn fix_param_usages(ctx: &AssistContext, params: &[Param], syntax: &SyntaxNode)
     for (param, usages) in usages_for_param {
         for usage in usages {
             match usage.syntax().ancestors().skip(1).find_map(ast::Expr::cast) {
-                Some(ast::Expr::MethodCallExpr(_) | ast::Expr::FieldExpr(_)) => {
+                Some(ast::Expr::MethodCallExpr(_)) | Some(ast::Expr::FieldExpr(_)) => {
                     // do nothing
                 }
                 Some(ast::Expr::RefExpr(node))
diff --git a/crates/ide_assists/src/handlers/remove_dbg.rs b/crates/ide_assists/src/handlers/remove_dbg.rs
index e6aab9e84813..da48c26503a5 100644
--- a/crates/ide_assists/src/handlers/remove_dbg.rs
+++ b/crates/ide_assists/src/handlers/remove_dbg.rs
@@ -71,31 +71,69 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
             let wrap = match ast::Expr::cast(parent) {
                 Some(parent) => match (expr, parent) {
                     (ast::Expr::CastExpr(_), ast::Expr::CastExpr(_)) => false,
-                    (
-                        ast::Expr::BoxExpr(_) | ast::Expr::PrefixExpr(_) | ast::Expr::RefExpr(_),
-                        ast::Expr::AwaitExpr(_)
-                        | ast::Expr::CallExpr(_)
-                        | ast::Expr::CastExpr(_)
-                        | ast::Expr::FieldExpr(_)
-                        | ast::Expr::IndexExpr(_)
-                        | ast::Expr::MethodCallExpr(_)
-                        | ast::Expr::RangeExpr(_)
-                        | ast::Expr::TryExpr(_),
-                    ) => true,
-                    (
-                        ast::Expr::BinExpr(_) | ast::Expr::CastExpr(_) | ast::Expr::RangeExpr(_),
-                        ast::Expr::AwaitExpr(_)
-                        | ast::Expr::BinExpr(_)
-                        | ast::Expr::CallExpr(_)
-                        | ast::Expr::CastExpr(_)
-                        | ast::Expr::FieldExpr(_)
-                        | ast::Expr::IndexExpr(_)
-                        | ast::Expr::MethodCallExpr(_)
-                        | ast::Expr::PrefixExpr(_)
-                        | ast::Expr::RangeExpr(_)
-                        | ast::Expr::RefExpr(_)
-                        | ast::Expr::TryExpr(_),
-                    ) => true,
+
+                    (ast::Expr::BoxExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::CastExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::BoxExpr(_), ast::Expr::TryExpr(_)) => true,
+
+                    (ast::Expr::PrefixExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::CastExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::PrefixExpr(_), ast::Expr::TryExpr(_)) => true,
+
+                    (ast::Expr::RefExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::CastExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::RefExpr(_), ast::Expr::TryExpr(_)) => true,
+
+                    (ast::Expr::BinExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::BinExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::CastExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::PrefixExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::RefExpr(_)) |
+                    (ast::Expr::BinExpr(_), ast::Expr::TryExpr(_))  => true,
+
+                    (ast::Expr::CastExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::BinExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::PrefixExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::RefExpr(_)) |
+                    (ast::Expr::CastExpr(_), ast::Expr::TryExpr(_))  => true,
+
+                    (ast::Expr::RangeExpr(_), ast::Expr::AwaitExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::BinExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::CallExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::CastExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::FieldExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::IndexExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::MethodCallExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::PrefixExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::RangeExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::RefExpr(_)) |
+                    (ast::Expr::RangeExpr(_), ast::Expr::TryExpr(_))  => true,
+
                     _ => false,
                 },
                 None => false,
diff --git a/crates/ide_assists/src/tests.rs b/crates/ide_assists/src/tests.rs
index 5cd3642ce0d8..8c3d307b3f3f 100644
--- a/crates/ide_assists/src/tests.rs
+++ b/crates/ide_assists/src/tests.rs
@@ -182,10 +182,9 @@ fn check(handler: Handler, before: &str, expected: ExpectedResult, assist_label:
             "unresolved assist should not contain source changes"
         ),
         (Some(_), ExpectedResult::NotApplicable) => panic!("assist should not be applicable!"),
-        (
-            None,
-            ExpectedResult::After(_) | ExpectedResult::Target(_) | ExpectedResult::Unresolved,
-        ) => {
+        (None, ExpectedResult::After(_))
+        | (None, ExpectedResult::Target(_))
+        | (None, ExpectedResult::Unresolved) => {
             panic!("code action is not applicable")
         }
         (None, ExpectedResult::NotApplicable) => (),
diff --git a/crates/ide_completion/Cargo.toml b/crates/ide_completion/Cargo.toml
index 447744da17c2..d2dda48c68c5 100644
--- a/crates/ide_completion/Cargo.toml
+++ b/crates/ide_completion/Cargo.toml
@@ -22,6 +22,7 @@ text_edit = { path = "../text_edit", version = "0.0.0" }
 base_db = { path = "../base_db", version = "0.0.0" }
 ide_db = { path = "../ide_db", version = "0.0.0" }
 profile = { path = "../profile", version = "0.0.0" }
+array_iterator = "1.8.0"
 
 # completions crate should depend only on the top-level `hir` package. if you need
 # something from some `hir_xxx` subpackage, reexport the API via `hir`.
diff --git a/crates/ide_completion/src/completions/attribute.rs b/crates/ide_completion/src/completions/attribute.rs
index 53cee3f4e254..a6090f3c64db 100644
--- a/crates/ide_completion/src/completions/attribute.rs
+++ b/crates/ide_completion/src/completions/attribute.rs
@@ -3,6 +3,7 @@
 //! This module uses a bit of static metadata to provide completions
 //! for built-in attributes.
 
+use array_iterator::ArrayIterator;
 use hir::HasAttrs;
 use ide_db::helpers::generated_lints::{CLIPPY_LINTS, DEFAULT_LINTS, FEATURES};
 use once_cell::sync::Lazy;
@@ -168,7 +169,7 @@ macro_rules! attrs {
 #[rustfmt::skip]
 static KIND_TO_ATTRIBUTES: Lazy<FxHashMap<SyntaxKind, &[&str]>> = Lazy::new(|| {
     use SyntaxKind::*;
-    std::array::IntoIter::new([
+    ArrayIterator::new([
         (
             SOURCE_FILE,
             attrs!(
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs
index ed0f902017a7..b2d5d0054266 100644
--- a/crates/ide_completion/src/completions/qualified_path.rs
+++ b/crates/ide_completion/src/completions/qualified_path.rs
@@ -86,11 +86,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                     // Don't suggest attribute macros and derives.
                     hir::ScopeDef::MacroDef(mac) => mac.is_fn_like(),
                     // no values in type places
-                    hir::ScopeDef::ModuleDef(
-                        hir::ModuleDef::Function(_)
-                        | hir::ModuleDef::Variant(_)
-                        | hir::ModuleDef::Static(_),
-                    )
+                    hir::ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
+                    | hir::ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
+                    | hir::ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
                     | hir::ScopeDef::Local(_) => !ctx.expects_type(),
                     // unless its a constant in a generic arg list position
                     hir::ScopeDef::ModuleDef(hir::ModuleDef::Const(_)) => {
@@ -104,13 +102,9 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon
                 }
             }
         }
-        hir::PathResolution::Def(
-            def
-            @
-            (hir::ModuleDef::Adt(_)
-            | hir::ModuleDef::TypeAlias(_)
-            | hir::ModuleDef::BuiltinType(_)),
-        ) => {
+        hir::PathResolution::Def(def @ hir::ModuleDef::Adt(_))
+        | hir::PathResolution::Def(def @ hir::ModuleDef::TypeAlias(_))
+        | hir::PathResolution::Def(def @ hir::ModuleDef::BuiltinType(_)) => {
             if let hir::ModuleDef::Adt(hir::Adt::Enum(e)) = def {
                 add_enum_variants(acc, ctx, e);
             }
diff --git a/crates/ide_completion/src/completions/unqualified_path.rs b/crates/ide_completion/src/completions/unqualified_path.rs
index facfe005186f..1f5faeb7be27 100644
--- a/crates/ide_completion/src/completions/unqualified_path.rs
+++ b/crates/ide_completion/src/completions/unqualified_path.rs
@@ -1,5 +1,6 @@
 //! Completion of names from the current scope, e.g. locals and imported items.
 
+use array_iterator::ArrayIterator;
 use hir::ScopeDef;
 use syntax::{ast, AstNode};
 
@@ -19,11 +20,11 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
             }
         });
 
-        std::array::IntoIter::new(["self::", "super::", "crate::"])
+        ArrayIterator::new(["self::", "super::", "crate::"])
             .for_each(|kw| acc.add_keyword(ctx, kw));
         return;
     }
-    std::array::IntoIter::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
+    ArrayIterator::new(["self", "super", "crate"]).for_each(|kw| acc.add_keyword(ctx, kw));
 
     if ctx.expects_item() || ctx.expects_assoc_item() {
         // only show macros in {Assoc}ItemList
@@ -44,7 +45,8 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
         ctx.scope.process_all_names(&mut |name, res| {
             let add_resolution = match res {
                 ScopeDef::MacroDef(mac) => mac.is_fn_like(),
-                ScopeDef::ModuleDef(hir::ModuleDef::Trait(_) | hir::ModuleDef::Module(_)) => true,
+                ScopeDef::ModuleDef(hir::ModuleDef::Trait(_)) |
+                ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
                 _ => false,
             };
             if add_resolution {
@@ -92,11 +94,9 @@ pub(crate) fn complete_unqualified_path(acc: &mut Completions, ctx: &CompletionC
             // Don't suggest attribute macros and derives.
             ScopeDef::MacroDef(mac) => mac.is_fn_like(),
             // no values in type places
-            ScopeDef::ModuleDef(
-                hir::ModuleDef::Function(_)
-                | hir::ModuleDef::Variant(_)
-                | hir::ModuleDef::Static(_),
-            )
+            ScopeDef::ModuleDef(hir::ModuleDef::Function(_))
+            | ScopeDef::ModuleDef(hir::ModuleDef::Variant(_))
+            | ScopeDef::ModuleDef(hir::ModuleDef::Static(_))
             | ScopeDef::Local(_) => !ctx.expects_type(),
             // unless its a constant in a generic arg list position
             ScopeDef::ModuleDef(hir::ModuleDef::Const(_))
diff --git a/crates/ide_completion/src/context.rs b/crates/ide_completion/src/context.rs
index f0da98739fd3..17001406cd99 100644
--- a/crates/ide_completion/src/context.rs
+++ b/crates/ide_completion/src/context.rs
@@ -242,23 +242,24 @@ impl<'a> CompletionContext<'a> {
     }
 
     pub(crate) fn expects_assoc_item(&self) -> bool {
-        matches!(self.completion_location, Some(ImmediateLocation::Trait | ImmediateLocation::Impl))
+        matches!(
+            self.completion_location,
+            Some(ImmediateLocation::Trait) | Some(ImmediateLocation::Impl)
+        )
     }
 
     pub(crate) fn has_dot_receiver(&self) -> bool {
         matches!(
             &self.completion_location,
-            Some(ImmediateLocation::FieldAccess { receiver, .. } | ImmediateLocation::MethodCall { receiver,.. })
+            Some(ImmediateLocation::FieldAccess { receiver, .. }) | Some(ImmediateLocation::MethodCall { receiver,.. })
                 if receiver.is_some()
         )
     }
 
     pub(crate) fn dot_receiver(&self) -> Option<&ast::Expr> {
         match &self.completion_location {
-            Some(
-                ImmediateLocation::MethodCall { receiver, .. }
-                | ImmediateLocation::FieldAccess { receiver, .. },
-            ) => receiver.as_ref(),
+            Some(ImmediateLocation::MethodCall { receiver, .. })
+            | Some(ImmediateLocation::FieldAccess { receiver, .. }) => receiver.as_ref(),
             _ => None,
         }
     }
@@ -282,28 +283,28 @@ impl<'a> CompletionContext<'a> {
     pub(crate) fn expects_ident_pat_or_ref_expr(&self) -> bool {
         matches!(
             self.completion_location,
-            Some(ImmediateLocation::IdentPat | ImmediateLocation::RefExpr)
+            Some(ImmediateLocation::IdentPat) | Some(ImmediateLocation::RefExpr)
         )
     }
 
     pub(crate) fn expect_field(&self) -> bool {
         matches!(
             self.completion_location,
-            Some(ImmediateLocation::RecordField | ImmediateLocation::TupleField)
+            Some(ImmediateLocation::RecordField) | Some(ImmediateLocation::TupleField)
         )
     }
 
     pub(crate) fn in_use_tree(&self) -> bool {
         matches!(
             self.completion_location,
-            Some(ImmediateLocation::Use | ImmediateLocation::UseTree)
+            Some(ImmediateLocation::Use) | Some(ImmediateLocation::UseTree)
         )
     }
 
     pub(crate) fn has_impl_or_trait_prev_sibling(&self) -> bool {
         matches!(
             self.prev_sibling,
-            Some(ImmediatePrevSibling::ImplDefType | ImmediatePrevSibling::TraitDefName)
+            Some(ImmediatePrevSibling::ImplDefType) | Some(ImmediatePrevSibling::TraitDefName)
         )
     }
 
@@ -324,16 +325,14 @@ impl<'a> CompletionContext<'a> {
             || self.previous_token_is(T![unsafe])
             || matches!(
                 self.prev_sibling,
-                Some(ImmediatePrevSibling::Attribute | ImmediatePrevSibling::Visibility)
+                Some(ImmediatePrevSibling::Attribute) | Some(ImmediatePrevSibling::Visibility)
             )
             || matches!(
                 self.completion_location,
-                Some(
-                    ImmediateLocation::Attribute(_)
-                        | ImmediateLocation::ModDeclaration(_)
-                        | ImmediateLocation::RecordPat(_)
-                        | ImmediateLocation::RecordExpr(_)
-                )
+                Some(ImmediateLocation::Attribute(_))
+                    | Some(ImmediateLocation::ModDeclaration(_))
+                    | Some(ImmediateLocation::RecordPat(_))
+                    | Some(ImmediateLocation::RecordExpr(_))
             )
     }
 
@@ -707,8 +706,8 @@ fn path_or_use_tree_qualifier(path: &ast::Path) -> Option<(ast::Path, bool)> {
 
 fn has_ref(token: &SyntaxToken) -> bool {
     let mut token = token.clone();
-    for skip in [WHITESPACE, IDENT, T![mut]] {
-        if token.kind() == skip {
+    for skip in [WHITESPACE, IDENT, T![mut]].iter() {
+        if &token.kind() == skip {
             token = match token.prev_token() {
                 Some(it) => it,
                 None => return false,
diff --git a/crates/ide_completion/src/render/builder_ext.rs b/crates/ide_completion/src/render/builder_ext.rs
index 33d3a5ee1889..749dfc665a02 100644
--- a/crates/ide_completion/src/render/builder_ext.rs
+++ b/crates/ide_completion/src/render/builder_ext.rs
@@ -32,7 +32,7 @@ impl Builder {
             cov_mark::hit!(no_parens_in_use_item);
             return false;
         }
-        if matches!(ctx.path_call_kind(), Some(CallKind::Expr | CallKind::Pat))
+        if matches!(ctx.path_call_kind(), Some(CallKind::Expr) | Some(CallKind::Pat))
             | matches!(
                 ctx.completion_location,
                 Some(ImmediateLocation::MethodCall { has_parens: true, .. })
diff --git a/crates/ide_completion/src/tests/sourcegen.rs b/crates/ide_completion/src/tests/sourcegen.rs
index ed3ac7203b9f..c48cefd7bd54 100644
--- a/crates/ide_completion/src/tests/sourcegen.rs
+++ b/crates/ide_completion/src/tests/sourcegen.rs
@@ -56,16 +56,51 @@ fn generate_lint_descriptor(buf: &mut String) {
         .skip(1)
         .filter(|l| !l.is_empty())
         .map(|line| {
-            let (name, rest) = line.trim().split_once(char::is_whitespace).unwrap();
-            let (_default_level, description) =
-                rest.trim().split_once(char::is_whitespace).unwrap();
-            (name.trim(), Cow::Borrowed(description.trim()))
+            let mut name: &str = "";
+            let mut _default_level: &str= "";
+            let mut description: String = "".to_string();
+            let mut splitted = line.trim().split(char::is_whitespace);
+            let mut piece = splitted.next();
+            while !piece.is_some() {
+                match piece{
+                    None => piece = splitted.next(),
+                    Some(piece_v) => {name = piece_v; break;}
+                }
+            }
+            while !piece.is_some() {
+                match piece{
+                    None => piece = splitted.next(),
+                    Some(piece_v) => {_default_level = piece_v; break;}
+                }
+            }
+            while !piece.is_some() {
+                match piece{
+                    None => piece = splitted.next(),
+                    Some(_piece_v) => {description =  splitted.collect::<Vec<&str>>().join(" "); break;}
+                }
+            }
+            (name.trim(), Cow::Owned(description.trim().to_string()))
         })
         .collect::<Vec<_>>();
     lints.extend(
         stdout[start_lint_groups..end_lint_groups].lines().skip(1).filter(|l| !l.is_empty()).map(
             |line| {
-                let (name, lints) = line.trim().split_once(char::is_whitespace).unwrap();
+                let mut name: &str = "";
+                let mut lints: String = "".to_string();
+                let mut splitted = line.trim().split(char::is_whitespace);
+                let mut piece = splitted.next();
+                while !piece.is_some() {
+                    match piece{
+                        None => piece = splitted.next(),
+                        Some(piece_v) => {name = piece_v; break;}
+                    }
+                }
+                while !piece.is_some() {
+                    match piece{
+                        None => piece = splitted.next(),
+                        Some(piece_v) => {lints =  splitted.collect::<Vec<&str>>().join(" "); break;}
+                    }
+                }
                 (name.trim(), format!("lint group for: {}", lints.trim()).into())
             },
         ),
diff --git a/crates/ide_db/src/line_index.rs b/crates/ide_db/src/line_index.rs
index 816edfe6a8e2..8e9d8cca233d 100644
--- a/crates/ide_db/src/line_index.rs
+++ b/crates/ide_db/src/line_index.rs
@@ -3,6 +3,7 @@
 use std::iter;
 
 use rustc_hash::FxHashMap;
+use stdx::partition_point;
 use syntax::{TextRange, TextSize};
 
 #[derive(Clone, Debug, PartialEq, Eq)]
@@ -96,7 +97,7 @@ impl LineIndex {
     }
 
     pub fn line_col(&self, offset: TextSize) -> LineCol {
-        let line = self.newlines.partition_point(|&it| it <= offset) - 1;
+        let line = partition_point(&self.newlines, |&it| it <= offset) - 1;
         let line_start_offset = self.newlines[line];
         let col = offset - line_start_offset;
         LineCol { line: line as u32, col: col.into() }
@@ -117,8 +118,8 @@ impl LineIndex {
     }
 
     pub fn lines(&self, range: TextRange) -> impl Iterator<Item = TextRange> + '_ {
-        let lo = self.newlines.partition_point(|&it| it < range.start());
-        let hi = self.newlines.partition_point(|&it| it <= range.end());
+        let lo = partition_point(&self.newlines, |&it| it < range.start());
+        let hi = partition_point(&self.newlines, |&it| it <= range.end());
         let all = iter::once(range.start())
             .chain(self.newlines[lo..hi].iter().copied())
             .chain(iter::once(range.end()));
diff --git a/crates/mbe/src/expander/matcher.rs b/crates/mbe/src/expander/matcher.rs
index 0d694b1a7820..5c4680d193c0 100644
--- a/crates/mbe/src/expander/matcher.rs
+++ b/crates/mbe/src/expander/matcher.rs
@@ -804,17 +804,33 @@ impl<'a> TtIter<'a> {
         };
 
         match (punct.char, second, third) {
-            ('.', '.', Some('.' | '=')) | ('<', '<', Some('=')) | ('>', '>', Some('=')) => {
+            ('.', '.', Some('.'))
+            | ('.', '.', Some('='))
+            | ('<', '<', Some('='))
+            | ('>', '>', Some('=')) => {
                 let tt2 = self.next().unwrap().clone();
                 let tt3 = self.next().unwrap().clone();
                 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2, tt3] }.into())
             }
-            ('-' | '!' | '*' | '/' | '&' | '%' | '^' | '+' | '<' | '=' | '>' | '|', '=', _)
-            | ('-' | '=' | '>', '>', _)
+            ('-', '=', _)
+            | ('-', '>', _)
             | (':', ':', _)
+            | ('!', '=', _)
             | ('.', '.', _)
+            | ('*', '=', _)
+            | ('/', '=', _)
             | ('&', '&', _)
+            | ('&', '=', _)
+            | ('%', '=', _)
+            | ('^', '=', _)
+            | ('+', '=', _)
             | ('<', '<', _)
+            | ('<', '=', _)
+            | ('=', '=', _)
+            | ('=', '>', _)
+            | ('>', '=', _)
+            | ('>', '>', _)
+            | ('|', '=', _)
             | ('|', '|', _) => {
                 let tt2 = self.next().unwrap().clone();
                 Ok(tt::Subtree { delimiter: None, token_trees: vec![tt, tt2] }.into())
diff --git a/crates/parser/src/grammar/params.rs b/crates/parser/src/grammar/params.rs
index 8f028c619415..205b9ffa5f3e 100644
--- a/crates/parser/src/grammar/params.rs
+++ b/crates/parser/src/grammar/params.rs
@@ -194,7 +194,8 @@ fn opt_self_param(p: &mut Parser, m: Marker) -> Result<(), Marker> {
         if !matches!(
             (p.current(), la1, la2, la3),
             (T![&], T![self], _, _)
-                | (T![&], T![mut] | LIFETIME_IDENT, T![self], _)
+                | (T![&], T![mut], T![self], _)
+                | (T![&], LIFETIME_IDENT, T![self], _)
                 | (T![&], LIFETIME_IDENT, T![mut], T![self])
         ) {
             return Err(m);
diff --git a/crates/project_model/src/cfg_flag.rs b/crates/project_model/src/cfg_flag.rs
index bfdfd458fbfc..e92962cf6727 100644
--- a/crates/project_model/src/cfg_flag.rs
+++ b/crates/project_model/src/cfg_flag.rs
@@ -4,6 +4,7 @@
 use std::str::FromStr;
 
 use cfg::CfgOptions;
+use stdx::split_once;
 
 #[derive(Clone, Eq, PartialEq, Debug)]
 pub enum CfgFlag {
@@ -14,7 +15,7 @@ pub enum CfgFlag {
 impl FromStr for CfgFlag {
     type Err = String;
     fn from_str(s: &str) -> Result<Self, Self::Err> {
-        let res = match s.split_once('=') {
+        let res = match split_once(s, '=') {
             Some((key, value)) => {
                 if !(value.starts_with('"') && value.ends_with('"')) {
                     return Err(format!("Invalid cfg ({:?}), value should be in quotes", s));
diff --git a/crates/rust-analyzer/Cargo.toml b/crates/rust-analyzer/Cargo.toml
index 9ff95d004662..3400875eda75 100644
--- a/crates/rust-analyzer/Cargo.toml
+++ b/crates/rust-analyzer/Cargo.toml
@@ -32,7 +32,7 @@ serde_path_to_error = "0.1"
 threadpool = "1.7.1"
 rayon = "1.5"
 mimalloc = { version = "0.1.19", default-features = false, optional = true }
-lsp-server = "0.5.1"
+lsp-server = "0.5.0"
 tracing = "0.1"
 tracing-subscriber = { version = "0.2", default-features = false, features = ["env-filter", "registry"] }
 tracing-tree = { version = "0.1.4" }
diff --git a/crates/rust-analyzer/src/reload.rs b/crates/rust-analyzer/src/reload.rs
index 95751cae6db3..eca9e6d04dcc 100644
--- a/crates/rust-analyzer/src/reload.rs
+++ b/crates/rust-analyzer/src/reload.rs
@@ -274,13 +274,7 @@ impl GlobalState {
                         .flat_map(|it| it.to_roots(workspace_build_data.as_ref()))
                         .filter(|it| it.is_member)
                         .flat_map(|root| {
-                            root.include.into_iter().flat_map(|it| {
-                                [
-                                    format!("{}/**/*.rs", it.display()),
-                                    format!("{}/**/Cargo.toml", it.display()),
-                                    format!("{}/**/Cargo.lock", it.display()),
-                                ]
-                            })
+                            root.include.into_iter().map(|it| format!("{}/**/*.rs", it.display()))
                         })
                         .map(|glob_pattern| lsp_types::FileSystemWatcher {
                             glob_pattern,
diff --git a/crates/stdx/src/lib.rs b/crates/stdx/src/lib.rs
index e83d5db437d1..ed2c7b31ed03 100644
--- a/crates/stdx/src/lib.rs
+++ b/crates/stdx/src/lib.rs
@@ -65,6 +65,20 @@ pub fn replace(buf: &mut String, from: char, to: &str) {
     *buf = buf.replace(from, to)
 }
 
+// https://github.com/rust-lang/rust/issues/74773
+pub fn split_once(haystack: &str, delim: char) -> Option<(&str, &str)> {
+    let mut split = haystack.splitn(2, delim);
+    let prefix = split.next()?;
+    let suffix = split.next()?;
+    Some((prefix, suffix))
+}
+pub fn rsplit_once(haystack: &str, delim: char) -> Option<(&str, &str)> {
+    let mut split = haystack.rsplitn(2, delim);
+    let suffix = split.next()?;
+    let prefix = split.next()?;
+    Some((prefix, suffix))
+}
+
 pub fn trim_indent(mut text: &str) -> String {
     if text.starts_with('\n') {
         text = &text[1..];
@@ -75,7 +89,7 @@ pub fn trim_indent(mut text: &str) -> String {
         .map(|it| it.len() - it.trim_start().len())
         .min()
         .unwrap_or(0);
-    text.split_inclusive('\n')
+    lines_with_ends(text)
         .map(
             |line| {
                 if line.len() <= indent {
@@ -88,12 +102,70 @@ pub fn trim_indent(mut text: &str) -> String {
         .collect()
 }
 
+pub fn lines_with_ends(text: &str) -> LinesWithEnds {
+    LinesWithEnds { text }
+}
+
+pub struct LinesWithEnds<'a> {
+    text: &'a str,
+}
+
+impl<'a> Iterator for LinesWithEnds<'a> {
+    type Item = &'a str;
+    fn next(&mut self) -> Option<&'a str> {
+        if self.text.is_empty() {
+            return None;
+        }
+        let idx = self.text.find('\n').map_or(self.text.len(), |it| it + 1);
+        let (res, next) = self.text.split_at(idx);
+        self.text = next;
+        Some(res)
+    }
+}
+
+/// Returns `idx` such that:
+///
+/// ```text
+///     ∀ x in slice[..idx]:  pred(x)
+///  && ∀ x in slice[idx..]: !pred(x)
+/// ```
+///
+/// https://github.com/rust-lang/rust/issues/73831
+pub fn partition_point<T, P>(slice: &[T], mut pred: P) -> usize
+where
+    P: FnMut(&T) -> bool,
+{
+    let mut left = 0;
+    let mut right = slice.len();
+
+    while left != right {
+        let mid = left + (right - left) / 2;
+        // SAFETY:
+        // When left < right, left <= mid < right.
+        // Therefore left always increases and right always decreases,
+        // and either of them is selected.
+        // In both cases left <= right is satisfied.
+        // Therefore if left < right in a step,
+        // left <= right is satisfied in the next step.
+        // Therefore as long as left != right, 0 <= left < right <= len is satisfied
+        // and if this case 0 <= mid < len is satisfied too.
+        let value = unsafe { slice.get_unchecked(mid) };
+        if pred(value) {
+            left = mid + 1;
+        } else {
+            right = mid;
+        }
+    }
+
+    left
+}
+
 pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize>
 where
     F: FnMut(&T) -> Ordering,
 {
-    let start = slice.partition_point(|it| key(it) == Ordering::Less);
-    let len = slice[start..].partition_point(|it| key(it) == Ordering::Equal);
+    let start = partition_point(slice, |it| key(it) == Ordering::Less);
+    let len = partition_point(&slice[start..], |it| key(it) == Ordering::Equal);
     start..start + len
 }
 
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index e0fb33933c62..2cb5597d7f6f 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -15,7 +15,7 @@ itertools = "0.10.0"
 rowan = "=0.13.0-pre.7"
 rustc_lexer = { version = "725.0.0", package = "rustc-ap-rustc_lexer" }
 rustc-hash = "1.1.0"
-arrayvec = "0.7"
+arrayvec = "0.5.1"
 once_cell = "1.3.1"
 indexmap = "1.4.0"
 smol_str = { version = "0.1.15", features = ["serde"] }
diff --git a/crates/test_utils/src/fixture.rs b/crates/test_utils/src/fixture.rs
index 44656267fed5..0aa40bbb7232 100644
--- a/crates/test_utils/src/fixture.rs
+++ b/crates/test_utils/src/fixture.rs
@@ -62,7 +62,7 @@
 //! ```
 
 use rustc_hash::FxHashMap;
-use stdx::trim_indent;
+use stdx::{lines_with_ends, split_once, trim_indent};
 
 #[derive(Debug, Eq, PartialEq)]
 pub struct Fixture {
@@ -107,14 +107,15 @@ impl Fixture {
         let mut res: Vec<Fixture> = Vec::new();
 
         if fixture.starts_with("//- minicore:") {
-            let first_line = fixture.split_inclusive('\n').next().unwrap();
-            mini_core = Some(MiniCore::parse(first_line));
+            let first_line = fixture.split('\n').next().unwrap().to_owned() + "\n";
+            
+            mini_core = Some(MiniCore::parse(&first_line));
             fixture = &fixture[first_line.len()..];
         }
 
         let default = if fixture.contains("//-") { None } else { Some("//- /main.rs") };
 
-        for (ix, line) in default.into_iter().chain(fixture.split_inclusive('\n')).enumerate() {
+        for (ix, line) in default.into_iter().chain(lines_with_ends(&fixture)).enumerate() {
             if line.contains("//-") {
                 assert!(
                     line.starts_with("//-"),
@@ -164,16 +165,28 @@ impl Fixture {
         let mut env = FxHashMap::default();
         let mut introduce_new_source_root = false;
         for component in components[1..].iter() {
-            let (key, value) = component
-                .split_once(':')
-                .unwrap_or_else(|| panic!("invalid meta line: {:?}", meta));
+            let mut splitted = component.split(':');
+            let key: &str;
+            let value: &str;
+            match splitted.next() {
+                Some(key_part) => {
+                    match splitted.next() {
+                        Some(value_part) => {
+                            key = key_part;
+                            value = value_part;
+                        }
+                        None => {panic!("invalid meta line: {:?}", meta);}
+                   }
+                }
+                None => {panic!("invalid meta line: {:?}", meta);}
+            }
             match key {
                 "crate" => krate = Some(value.to_string()),
                 "deps" => deps = value.split(',').map(|it| it.to_string()).collect(),
                 "edition" => edition = Some(value.to_string()),
                 "cfg" => {
                     for entry in value.split(',') {
-                        match entry.split_once('=') {
+                        match split_once(entry, '=') {
                             Some((k, v)) => cfg_key_values.push((k.to_string(), v.to_string())),
                             None => cfg_atoms.push(entry.to_string()),
                         }
@@ -181,7 +194,7 @@ impl Fixture {
                 }
                 "env" => {
                     for key in value.split(',') {
-                        if let Some((k, v)) = key.split_once('=') {
+                        if let Some((k, v)) = split_once(key, '=') {
                             env.insert(k.into(), v.into());
                         }
                     }
@@ -237,7 +250,7 @@ impl MiniCore {
     pub fn source_code(mut self) -> String {
         let mut buf = String::new();
         let raw_mini_core = include_str!("./minicore.rs");
-        let mut lines = raw_mini_core.split_inclusive('\n');
+        let mut lines = raw_mini_core.split('\n');
 
         let mut parsing_flags = false;
         let mut implications = Vec::new();
@@ -245,7 +258,7 @@ impl MiniCore {
         // Parse `//!` preamble and extract flags and dependencies.
         for line in lines.by_ref() {
             let line = match line.strip_prefix("//!") {
-                Some(it) => it,
+                Some(it) => it.to_string() + "\n",
                 None => {
                     assert!(line.trim().is_empty());
                     break;
@@ -253,14 +266,33 @@ impl MiniCore {
             };
 
             if parsing_flags {
-                let (flag, deps) = line.split_once(':').unwrap();
+                let flag: String;
+                let deps: String;
+                let mut splitted = line.split(':');
+                match splitted.next() {
+                    Some(flag_v) => {
+                        flag = flag_v.to_owned();
+                        match splitted.next() {
+                            Some(deps_v) => {
+                                deps = deps_v.to_owned();
+                            },
+                            None => {
+                                deps = "".to_owned();
+                            }
+                        }
+                    },
+                    None => {
+                        flag = "".to_owned();
+                        deps = "".to_owned();
+                    }
+                }
                 let flag = flag.trim();
-                self.valid_flags.push(flag.to_string());
+                self.valid_flags.push(flag.to_string().to_owned());
                 for dep in deps.split(", ") {
                     let dep = dep.trim();
                     if !dep.is_empty() {
-                        self.assert_valid_flag(dep);
-                        implications.push((flag, dep));
+                        self.assert_valid_flag(&dep);
+                        implications.push((flag.to_owned(), dep.to_owned()));
                     }
                 }
             }
@@ -277,8 +309,8 @@ impl MiniCore {
         // Fixed point loop to compute transitive closure of flags.
         loop {
             let mut changed = false;
-            for &(u, v) in implications.iter() {
-                if self.has_flag(u) && !self.has_flag(v) {
+            for (u, v) in implications.iter() {
+                if self.has_flag(&u) && !self.has_flag(&v) {
                     self.activated_flags.push(v.to_string());
                     changed = true;
                 }
diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs
index d9c22c1803e1..e1d8e8429fbf 100644
--- a/crates/test_utils/src/lib.rs
+++ b/crates/test_utils/src/lib.rs
@@ -18,7 +18,7 @@ use std::{
 };
 
 use profile::StopWatch;
-use stdx::is_ci;
+use stdx::{is_ci, lines_with_ends};
 use text_size::{TextRange, TextSize};
 
 pub use dissimilar::diff as __diff;
@@ -222,7 +222,7 @@ pub fn extract_annotations(text: &str) -> Vec<(TextRange, String)> {
     let mut line_start_map = BTreeMap::new();
     let mut line_start: TextSize = 0.into();
     let mut prev_line_annotations: Vec<(TextSize, usize)> = Vec::new();
-    for line in text.split_inclusive('\n') {
+    for line in lines_with_ends(text) {
         let mut this_line_annotations = Vec::new();
         let line_length = if let Some(idx) = line.find("//") {
             let annotation_offset = TextSize::of(&line[..idx + "//".len()]);
diff --git a/crates/vfs/src/vfs_path.rs b/crates/vfs/src/vfs_path.rs
index 0ad56e00d7cb..08e7090dce62 100644
--- a/crates/vfs/src/vfs_path.rs
+++ b/crates/vfs/src/vfs_path.rs
@@ -390,7 +390,8 @@ impl VirtualPath {
 
             match (file_stem, extension) {
                 (None, None) => None,
-                (None | Some(""), Some(_)) => Some((file_name, None)),
+                (None, Some(_)) => Some((file_name, None)),
+                ( Some(""), Some(_)) => Some((file_name, None)),
                 (Some(file_stem), extension) => Some((file_stem, extension)),
             }
         }
diff --git a/xtask/src/install.rs b/xtask/src/install.rs
index 64ab12b42a9a..91d6a28533e5 100644
--- a/xtask/src/install.rs
+++ b/xtask/src/install.rs
@@ -8,7 +8,7 @@ use xshell::{cmd, pushd};
 use crate::flags;
 
 // Latest stable, feel free to send a PR if this lags behind.
-const REQUIRED_RUST_VERSION: u32 = 53;
+const REQUIRED_RUST_VERSION: u32 = 51;
 
 impl flags::Install {
     pub(crate) fn run(self) -> Result<()> {