Repository: rust-lang/rust-analyzer
Pull request #13051 (2022-08-18 07:07:46)

fix: Only move comments when extracting a struct from an enum variant
Motivating example:

```rs
#[derive(Debug, thiserror::Error)]
enum Error {
    /// Some explanation for this error
    #[error("message")]
    $0Woops {
        code: u32
    }
}
```
now becomes
```rs
/// Some explanation for this error
#[derive(Debug, thiserror::Error)]
struct Woops{
    code: u32
}

#[derive(Debug, thiserror::Error)]
enum Error {
    #[error("message")]
    Woops(Woops)
}
```
(the `thiserror::Error` derive being copied and the struct formatting aren't ideal, though those are issues for another day)


Patch:
diff --git a/crates/flycheck/src/lib.rs b/crates/flycheck/src/lib.rs
index c22945c81f..2bebea2fbf 100644
--- a/crates/flycheck/src/lib.rs
+++ b/crates/flycheck/src/lib.rs
@@ -77,13 +77,8 @@ impl FlycheckHandle {
     }
 
     /// Schedule a re-start of the cargo check worker.
-    pub fn restart(&self) {
-        self.sender.send(Restart::Yes).unwrap();
-    }
-
-    /// Stop this cargo check worker.
-    pub fn cancel(&self) {
-        self.sender.send(Restart::No).unwrap();
+    pub fn update(&self) {
+        self.sender.send(Restart).unwrap();
     }
 
     pub fn id(&self) -> usize {
@@ -127,10 +122,7 @@ pub enum Progress {
     DidCancel,
 }
 
-enum Restart {
-    Yes,
-    No,
-}
+struct Restart;
 
 struct FlycheckActor {
     id: usize,
@@ -157,7 +149,6 @@ impl FlycheckActor {
         config: FlycheckConfig,
         workspace_root: AbsPathBuf,
     ) -> FlycheckActor {
-        tracing::info!(%id, ?workspace_root, "Spawning flycheck");
         FlycheckActor { id, sender, config, workspace_root, cargo_handle: None }
     }
     fn progress(&self, progress: Progress) {
@@ -173,13 +164,10 @@ impl FlycheckActor {
     fn run(mut self, inbox: Receiver<Restart>) {
         while let Some(event) = self.next_event(&inbox) {
             match event {
-                Event::Restart(Restart::No) => {
-                    self.cancel_check_process();
-                }
-                Event::Restart(Restart::Yes) => {
+                Event::Restart(Restart) => {
                     // Cancel the previously spawned process
                     self.cancel_check_process();
-                    while let Ok(_) = inbox.recv_timeout(Duration::from_millis(50)) {}
+                    while let Ok(Restart) = inbox.recv_timeout(Duration::from_millis(50)) {}
 
                     let command = self.check_command();
                     tracing::debug!(?command, "will restart flycheck");
@@ -235,10 +223,6 @@ impl FlycheckActor {
 
     fn cancel_check_process(&mut self) {
         if let Some(cargo_handle) = self.cargo_handle.take() {
-            tracing::debug!(
-                command = ?self.check_command(),
-                "did  cancel flycheck"
-            );
             cargo_handle.cancel();
             self.progress(Progress::DidCancel);
         }
diff --git a/crates/hir-expand/src/mod_path.rs b/crates/hir-expand/src/mod_path.rs
index d7586d129b..d0f73ec820 100644
--- a/crates/hir-expand/src/mod_path.rs
+++ b/crates/hir-expand/src/mod_path.rs
@@ -257,7 +257,6 @@ macro_rules! __known_path {
     (core::ops::RangeToInclusive) => {};
     (core::ops::RangeInclusive) => {};
     (core::future::Future) => {};
-    (core::future::IntoFuture) => {};
     (core::ops::Try) => {};
     ($path:path) => {
         compile_error!("Please register your known path in the path module")
diff --git a/crates/hir-expand/src/name.rs b/crates/hir-expand/src/name.rs
index 2b859f7750..a1bb353374 100644
--- a/crates/hir-expand/src/name.rs
+++ b/crates/hir-expand/src/name.rs
@@ -266,7 +266,6 @@ pub mod known {
         Try,
         Ok,
         Future,
-        IntoFuture,
         Result,
         Option,
         Output,
@@ -400,7 +399,6 @@ pub mod known {
         future_trait,
         index,
         index_mut,
-        into_future,
         mul_assign,
         mul,
         neg,
diff --git a/crates/hir-ty/src/infer.rs b/crates/hir-ty/src/infer.rs
index 5df48e5fdc..46eeea0e6f 100644
--- a/crates/hir-ty/src/infer.rs
+++ b/crates/hir-ty/src/infer.rs
@@ -734,7 +734,6 @@ impl<'a> InferenceContext<'a> {
                         let ty = self.insert_type_vars(ty.substitute(Interner, &substs));
                         return (ty, Some(strukt.into()));
                     }
-                    ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
                     _ => return (self.err_ty(), None),
                 },
                 Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)),
@@ -876,10 +875,7 @@ impl<'a> InferenceContext<'a> {
     }
 
     fn resolve_future_future_output(&self) -> Option<TypeAliasId> {
-        let trait_ = self
-            .resolver
-            .resolve_known_trait(self.db.upcast(), &path![core::future::IntoFuture])
-            .or_else(|| self.resolve_lang_item(name![future_trait])?.as_trait())?;
+        let trait_ = self.resolve_lang_item(name![future_trait])?.as_trait()?;
         self.db.trait_data(trait_).associated_type_by_name(&name![Output])
     }
 
diff --git a/crates/hir-ty/src/lower.rs b/crates/hir-ty/src/lower.rs
index ae115c8c0d..239f66bcb7 100644
--- a/crates/hir-ty/src/lower.rs
+++ b/crates/hir-ty/src/lower.rs
@@ -238,7 +238,18 @@ impl<'a> TyLoweringContext<'a> {
                 })
                 .intern(Interner)
             }
-            TypeRef::DynTrait(bounds) => self.lower_dyn_trait(bounds),
+            TypeRef::DynTrait(bounds) => {
+                let self_ty =
+                    TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
+                let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
+                    QuantifiedWhereClauses::from_iter(
+                        Interner,
+                        bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
+                    )
+                });
+                let bounds = crate::make_single_type_binders(bounds);
+                TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
+            }
             TypeRef::ImplTrait(bounds) => {
                 match self.impl_trait_mode {
                     ImplTraitLoweringMode::Opaque => {
@@ -457,10 +468,29 @@ impl<'a> TyLoweringContext<'a> {
                         }
                     }
                     0 => {
-                        // Trait object type without dyn; this should be handled in upstream. See
-                        // `lower_path()`.
-                        stdx::never!("unexpected fully resolved trait path");
-                        TyKind::Error.intern(Interner)
+                        let self_ty = Some(
+                            TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
+                                .intern(Interner),
+                        );
+                        let trait_ref = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
+                            ctx.lower_trait_ref_from_resolved_path(
+                                trait_,
+                                resolved_segment,
+                                self_ty,
+                            )
+                        });
+                        let dyn_ty = DynTy {
+                            bounds: crate::make_single_type_binders(
+                                QuantifiedWhereClauses::from_iter(
+                                    Interner,
+                                    Some(crate::wrap_empty_binders(WhereClause::Implemented(
+                                        trait_ref,
+                                    ))),
+                                ),
+                            ),
+                            lifetime: static_lifetime(),
+                        };
+                        TyKind::Dyn(dyn_ty).intern(Interner)
                     }
                     _ => {
                         // FIXME report error (ambiguous associated type)
@@ -525,20 +555,11 @@ impl<'a> TyLoweringContext<'a> {
             let (ty, res) = self.lower_ty_ext(type_ref);
             return self.lower_ty_relative_path(ty, res, path.segments());
         }
-
         let (resolution, remaining_index) =
             match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path.mod_path()) {
                 Some(it) => it,
                 None => return (TyKind::Error.intern(Interner), None),
             };
-
-        if matches!(resolution, TypeNs::TraitId(_)) && remaining_index.is_none() {
-            // trait object type without dyn
-            let bound = TypeBound::Path(path.clone(), TraitBoundModifier::None);
-            let ty = self.lower_dyn_trait(&[Interned::new(bound)]);
-            return (ty, None);
-        }
-
         let (resolved_segment, remaining_segments) = match remaining_index {
             None => (
                 path.segments().last().expect("resolved path has at least one element"),
@@ -966,18 +987,6 @@ impl<'a> TyLoweringContext<'a> {
             })
     }
 
-    fn lower_dyn_trait(&self, bounds: &[Interned<TypeBound>]) -> Ty {
-        let self_ty = TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(Interner);
-        let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
-            QuantifiedWhereClauses::from_iter(
-                Interner,
-                bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
-            )
-        });
-        let bounds = crate::make_single_type_binders(bounds);
-        TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(Interner)
-    }
-
     fn lower_impl_trait(
         &self,
         bounds: &[Interned<TypeBound>],
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index aa019ca483..3561bdeba7 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -2778,32 +2778,20 @@ impl Type {
         self.ty.is_unknown()
     }
 
-    /// Checks that particular type `ty` implements `std::future::IntoFuture` or
-    /// `std::future::Future`.
+    /// Checks that particular type `ty` implements `std::future::Future`.
     /// This function is used in `.await` syntax completion.
-    pub fn impls_into_future(&self, db: &dyn HirDatabase) -> bool {
-        let trait_ = db
-            .lang_item(self.env.krate, SmolStr::new_inline("into_future"))
-            .and_then(|it| {
-                let into_future_fn = it.as_function()?;
-                let assoc_item = as_assoc_item(db, AssocItem::Function, into_future_fn)?;
-                let into_future_trait = assoc_item.containing_trait_or_trait_impl(db)?;
-                Some(into_future_trait.id)
-            })
-            .or_else(|| {
-                let future_trait =
-                    db.lang_item(self.env.krate, SmolStr::new_inline("future_trait"))?;
-                future_trait.as_trait()
-            });
-
-        let trait_ = match trait_ {
+    pub fn impls_future(&self, db: &dyn HirDatabase) -> bool {
+        let std_future_trait = db
+            .lang_item(self.env.krate, SmolStr::new_inline("future_trait"))
+            .and_then(|it| it.as_trait());
+        let std_future_trait = match std_future_trait {
             Some(it) => it,
             None => return false,
         };
 
         let canonical_ty =
             Canonical { value: self.ty.clone(), binders: CanonicalVarKinds::empty(Interner) };
-        method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), trait_)
+        method_resolution::implements_trait(&canonical_ty, db, self.env.clone(), std_future_trait)
     }
 
     /// Checks that particular type `ty` implements `std::ops::FnOnce`.
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index bd35af06e2..ae2896e193 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -27,7 +27,6 @@ use hir_def::{
 use hir_expand::{
     builtin_fn_macro::BuiltinFnLikeExpander,
     hygiene::Hygiene,
-    mod_path::path,
     name,
     name::{AsName, Name},
     HirFileId, InFile,
@@ -270,35 +269,14 @@ impl SourceAnalyzer {
         db: &dyn HirDatabase,
         await_expr: &ast::AwaitExpr,
     ) -> Option<FunctionId> {
-        let mut ty = self.ty_of_expr(db, &await_expr.expr()?.into())?.clone();
-
-        let into_future_trait = self
-            .resolver
-            .resolve_known_trait(db.upcast(), &path![core::future::IntoFuture])
-            .map(Trait::from);
-
-        if let Some(into_future_trait) = into_future_trait {
-            let type_ = Type::new_with_resolver(db, &self.resolver, ty.clone());
-            if type_.impls_trait(db, into_future_trait, &[]) {
-                let items = into_future_trait.items(db);
-                let into_future_type = items.into_iter().find_map(|item| match item {
-                    AssocItem::TypeAlias(alias)
-                        if alias.name(db) == hir_expand::name![IntoFuture] =>
-                    {
-                        Some(alias)
-                    }
-                    _ => None,
-                })?;
-                let future_trait = type_.normalize_trait_assoc_type(db, &[], into_future_type)?;
-                ty = future_trait.ty;
-            }
-        }
+        let ty = self.ty_of_expr(db, &await_expr.expr()?.into())?;
 
-        let poll_fn = db
+        let op_fn = db
             .lang_item(self.resolver.krate(), hir_expand::name![poll].to_smol_str())?
             .as_function()?;
-        let substs = hir_ty::TyBuilder::subst_for_def(db, poll_fn).push(ty.clone()).build();
-        Some(self.resolve_impl_method_or_trait_def(db, poll_fn, &substs))
+        let substs = hir_ty::TyBuilder::subst_for_def(db, op_fn).push(ty.clone()).build();
+
+        Some(self.resolve_impl_method_or_trait_def(db, op_fn, &substs))
     }
 
     pub(crate) fn resolve_prefix_expr(
diff --git a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
index dfb5652126..ddc2052e7a 100644
--- a/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
+++ b/crates/ide-assists/src/handlers/extract_struct_from_enum_variant.rs
@@ -101,21 +101,22 @@ pub(crate) fn extract_struct_from_enum_variant(
                 });
             }
 
-            let indent = enum_ast.indent_level();
             let generic_params = enum_ast
                 .generic_param_list()
                 .and_then(|known_generics| extract_generic_params(&known_generics, &field_list));
             let generics = generic_params.as_ref().map(|generics| generics.clone_for_update());
             let def =
                 create_struct_def(variant_name.clone(), &variant, &field_list, generics, &enum_ast);
+
+            let enum_ast = variant.parent_enum();
+            let indent = enum_ast.indent_level();
             def.reindent_to(indent);
 
-            let start_offset = &variant.parent_enum().syntax().clone();
-            ted::insert_all_raw(
-                ted::Position::before(start_offset),
+            ted::insert_all(
+                ted::Position::before(enum_ast.syntax()),
                 vec![
                     def.syntax().clone().into(),
-                    make::tokens::whitespace(&format!("\n\n{}", indent)).into(),
+                    make::tokens::whitespace(&format!("\n\n{indent}")).into(),
                 ],
             );
 
@@ -227,7 +228,7 @@ fn tag_generics_in_variant(ty: &ast::Type, generics: &mut [(ast::GenericParam, b
 }
 
 fn create_struct_def(
-    variant_name: ast::Name,
+    name: ast::Name,
     variant: &ast::Variant,
     field_list: &Either<ast::RecordFieldList, ast::TupleFieldList>,
     generics: Option<ast::GenericParamList>,
@@ -269,43 +270,27 @@ fn create_struct_def(
             field_list.into()
         }
     };
-
     field_list.reindent_to(IndentLevel::single());
 
-    let strukt = make::struct_(enum_vis, variant_name, generics, field_list).clone_for_update();
-
-    // FIXME: Consider making this an actual function somewhere (like in `AttrsOwnerEdit`) after some deliberation
-    let attrs_and_docs = |node: &SyntaxNode| {
-        let mut select_next_ws = false;
-        node.children_with_tokens().filter(move |child| {
-            let accept = match child.kind() {
-                ATTR | COMMENT => {
-                    select_next_ws = true;
-                    return true;
-                }
-                WHITESPACE if select_next_ws => true,
-                _ => false,
-            };
-            select_next_ws = false;
-
-            accept
-        })
-    };
+    let strukt = make::struct_(enum_vis, name, generics, field_list).clone_for_update();
 
-    // copy attributes & comments from variant
-    let variant_attrs = attrs_and_docs(variant.syntax())
-        .map(|tok| match tok.kind() {
-            WHITESPACE => make::tokens::single_newline().into(),
-            _ => tok,
-        })
-        .collect();
-    ted::insert_all(ted::Position::first_child_of(strukt.syntax()), variant_attrs);
+    // take comments from variant
+    ted::insert_all(
+        ted::Position::first_child_of(strukt.syntax()),
+        take_all_comments(variant.syntax()),
+    );
 
     // copy attributes from enum
     ted::insert_all(
         ted::Position::first_child_of(strukt.syntax()),
-        enum_.attrs().map(|it| it.syntax().clone_for_update().into()).collect(),
+        enum_
+            .attrs()
+            .flat_map(|it| {
+                vec![it.syntax().clone_for_update().into(), make::tokens::single_newline().into()]
+            })
+            .collect(),
     );
+
     strukt
 }
 
@@ -346,16 +331,48 @@ fn update_variant(variant: &ast::Variant, generics: Option<ast::GenericParamList
         })
         .unwrap_or_else(|| make::ty(&name.text()));
 
+    // change from a record to a tuple field list
     let tuple_field = make::tuple_field(None, ty);
-    let replacement = make::variant(
-        name,
-        Some(ast::FieldList::TupleFieldList(make::tuple_field_list(iter::once(tuple_field)))),
-    )
-    .clone_for_update();
-    ted::replace(variant.syntax(), replacement.syntax());
+    let field_list = make::tuple_field_list(iter::once(tuple_field)).clone_for_update();
+    ted::replace(variant.field_list()?.syntax(), field_list.syntax());
+
+    // remove any ws after the name
+    if let Some(ws) = name
+        .syntax()
+        .siblings_with_tokens(syntax::Direction::Next)
+        .find_map(|tok| tok.into_token().filter(|tok| tok.kind() == WHITESPACE))
+    {
+        ted::remove(SyntaxElement::Token(ws));
+    }
+
     Some(())
 }
 
+// Note: this also detaches whitespace after comments,
+// since `SyntaxNode::splice_children` (and by extension `ted::insert_all_raw`)
+// detaches nodes. If we only took the comments, we'd leave behind the old whitespace.
+fn take_all_comments(node: &SyntaxNode) -> Vec<SyntaxElement> {
+    let mut remove_next_ws = false;
+    node.children_with_tokens()
+        .filter_map(move |child| match child.kind() {
+            COMMENT => {
+                remove_next_ws = true;
+                child.detach();
+                Some(child)
+            }
+            WHITESPACE if remove_next_ws => {
+                remove_next_ws = false;
+                child.detach();
+                Some(make::tokens::single_newline().into())
+            }
+            _ => {
+                remove_next_ws = false;
+                None
+            }
+        })
+        .collect()
+}
+
 fn apply_references(
     insert_use_cfg: InsertUseConfig,
     segment: ast::PathSegment,
@@ -480,10 +497,14 @@ enum En<T> { Var(Var<T>) }"#,
     fn test_extract_struct_carries_over_attributes() {
         check_assist(
             extract_struct_from_enum_variant,
-            r#"#[derive(Debug)]
+            r#"
+#[derive(Debug)]
 #[derive(Clone)]
 enum Enum { Variant{ field: u32$0 } }"#,
-            r#"#[derive(Debug)]#[derive(Clone)] struct Variant{ field: u32 }
+            r#"
+#[derive(Debug)]
+#[derive(Clone)]
+struct Variant{ field: u32 }
 
 #[derive(Debug)]
 #[derive(Clone)]
@@ -614,7 +635,7 @@ enum A { One(One) }"#,
     }
 
     #[test]
-    fn test_extract_struct_keep_comments_and_attrs_on_variant_struct() {
+    fn test_extract_struct_move_struct_variant_comments() {
         check_assist(
             extract_struct_from_enum_variant,
             r#"
@@ -631,19 +652,19 @@ enum A {
 /* comment */
 // other
 /// comment
-#[attr]
 struct One{
     a: u32
 }
 
 enum A {
+    #[attr]
     One(One)
 }"#,
         );
     }
 
     #[test]
-    fn test_extract_struct_keep_comments_and_attrs_on_variant_tuple() {
+    fn test_extract_struct_move_tuple_variant_comments() {
         check_assist(
             extract_struct_from_enum_variant,
             r#"
@@ -658,10 +679,10 @@ enum A {
 /* comment */
 // other
 /// comment
-#[attr]
 struct One(u32, u32);
 
 enum A {
+    #[attr]
     One(One)
 }"#,
         );
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index e26c76da18..d564a05408 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -61,72 +61,56 @@ fn gen_fn(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
     }
 
     let fn_name = &*name_ref.text();
-    let TargetInfo { target_module, adt_name, target, file, insert_offset } =
-        fn_target_info(ctx, path, &call, fn_name)?;
-    let function_builder = FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target)?;
-    let text_range = call.syntax().text_range();
-    let label = format!("Generate {} function", function_builder.fn_name);
-    add_func_to_accumulator(
-        acc,
-        ctx,
-        text_range,
-        function_builder,
-        insert_offset,
-        file,
-        adt_name,
-        label,
-    )
-}
-
-struct TargetInfo {
-    target_module: Option<Module>,
-    adt_name: Option<hir::Name>,
-    target: GeneratedFunctionTarget,
-    file: FileId,
-    insert_offset: TextSize,
-}
+    let target_module;
+    let mut adt_name = None;
 
-impl TargetInfo {
-    fn new(
-        target_module: Option<Module>,
-        adt_name: Option<hir::Name>,
-        target: GeneratedFunctionTarget,
-        file: FileId,
-        insert_offset: TextSize,
-    ) -> Self {
-        Self { target_module, adt_name, target, file, insert_offset }
-    }
-}
-
-fn fn_target_info(
-    ctx: &AssistContext<'_>,
-    path: ast::Path,
-    call: &CallExpr,
-    fn_name: &str,
-) -> Option<TargetInfo> {
-    match path.qualifier() {
+    let (target, file, insert_offset) = match path.qualifier() {
         Some(qualifier) => match ctx.sema.resolve_path(&qualifier) {
             Some(hir::PathResolution::Def(hir::ModuleDef::Module(module))) => {
-                get_fn_target_info(ctx, &Some(module), call.clone())
+                target_module = Some(module);
+                get_fn_target(ctx, &target_module, call.clone())?
             }
             Some(hir::PathResolution::Def(hir::ModuleDef::Adt(adt))) => {
                 if let hir::Adt::Enum(_) = adt {
                     // Don't suggest generating function if the name starts with an uppercase letter
-                    if fn_name.starts_with(char::is_uppercase) {
+                    if name_ref.text().starts_with(char::is_uppercase) {
                         return None;
                     }
                 }
 
-                assoc_fn_target_info(ctx, call, adt, fn_name)
+                let current_module = ctx.sema.scope(call.syntax())?.module();
+                let module = adt.module(ctx.sema.db);
+                target_module = if current_module == module { None } else { Some(module) };
+                if current_module.krate() != module.krate() {
+                    return None;
+                }
+                let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
+                let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
+                adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
+                (target, file, insert_offset)
             }
-            Some(hir::PathResolution::SelfType(impl_)) => {
-                let adt = impl_.self_ty(ctx.db()).as_adt()?;
-                assoc_fn_target_info(ctx, call, adt, fn_name)
+            _ => {
+                return None;
             }
-            _ => None,
         },
-        _ => get_fn_target_info(ctx, &None, call.clone()),
-    }
+        _ => {
+            target_module = None;
+            get_fn_target(ctx, &target_module, call.clone())?
+        }
+    };
+    let function_builder = FunctionBuilder::from_call(ctx, &call, fn_name, target_module, target)?;
+    let text_range = call.syntax().text_range();
+    let label = format!("Generate {} function", function_builder.fn_name);
+    add_func_to_accumulator(
+        acc,
+        ctx,
+        text_range,
+        function_builder,
+        insert_offset,
+        file,
+        adt_name,
+        label,
+    )
 }
 
 fn gen_method(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
@@ -382,15 +366,6 @@ fn make_return_type(
     (ret_type, should_focus_return_type)
 }
 
-fn get_fn_target_info(
-    ctx: &AssistContext<'_>,
-    target_module: &Option<Module>,
-    call: CallExpr,
-) -> Option<TargetInfo> {
-    let (target, file, insert_offset) = get_fn_target(ctx, target_module, call)?;
-    Some(TargetInfo::new(*target_module, None, target, file, insert_offset))
-}
-
 fn get_fn_target(
     ctx: &AssistContext<'_>,
     target_module: &Option<Module>,
@@ -424,24 +399,6 @@ fn get_method_target(
     Some((target.clone(), get_insert_offset(&target)))
 }
 
-fn assoc_fn_target_info(
-    ctx: &AssistContext<'_>,
-    call: &CallExpr,
-    adt: hir::Adt,
-    fn_name: &str,
-) -> Option<TargetInfo> {
-    let current_module = ctx.sema.scope(call.syntax())?.module();
-    let module = adt.module(ctx.sema.db);
-    let target_module = if current_module == module { None } else { Some(module) };
-    if current_module.krate() != module.krate() {
-        return None;
-    }
-    let (impl_, file) = get_adt_source(ctx, &adt, fn_name)?;
-    let (target, insert_offset) = get_method_target(ctx, &module, &impl_)?;
-    let adt_name = if impl_.is_none() { Some(adt.name(ctx.sema.db)) } else { None };
-    Some(TargetInfo::new(target_module, adt_name, target, file, insert_offset))
-}
-
 fn get_insert_offset(target: &GeneratedFunctionTarget) -> TextSize {
     match &target {
         GeneratedFunctionTarget::BehindItem(it) => it.text_range().end(),
@@ -1676,33 +1633,6 @@ fn bar() ${0:-> _} {
         )
     }
 
-    #[test]
-    fn create_static_method_within_an_impl_with_self_syntax() {
-        check_assist(
-            generate_function,
-            r"
-struct S;
-impl S {
-    fn foo(&self) {
-        Self::bar$0();
-    }
-}
-",
-            r"
-struct S;
-impl S {
-    fn foo(&self) {
-        Self::bar();
-    }
-
-    fn bar() ${0:-> _} {
-        todo!()
-    }
-}
-",
-        )
-    }
-
     #[test]
     fn no_panic_on_invalid_global_path() {
         check_assist(
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index b5d092e39b..80d3b92559 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -13,7 +13,7 @@ use ide_db::{
 use itertools::{izip, Itertools};
 use syntax::{
     ast::{self, edit_in_place::Indent, HasArgList, PathExpr},
-    ted, AstNode, NodeOrToken, SyntaxKind,
+    ted, AstNode,
 };
 
 use crate::{
@@ -311,13 +311,6 @@ fn inline(
     } else {
         fn_body.clone_for_update()
     };
-    if let Some(t) = body.syntax().ancestors().find_map(ast::Impl::cast).and_then(|i| i.self_ty()) {
-        body.syntax()
-            .descendants_with_tokens()
-            .filter_map(NodeOrToken::into_token)
-            .filter(|tok| tok.kind() == SyntaxKind::SELF_TYPE_KW)
-            .for_each(|tok| ted::replace(tok, t.syntax()));
-    }
     let usages_for_locals = |local| {
         Definition::Local(local)
             .usages(sema)
@@ -352,7 +345,6 @@ fn inline(
             }
         })
         .collect();
-
     if function.self_param(sema.db).is_some() {
         let this = || make::name_ref("this").syntax().clone_for_update();
         if let Some(self_local) = params[0].2.as_local(sema.db) {
@@ -1196,31 +1188,6 @@ fn bar() -> u32 {
       x
     }
 }
-"#,
-        )
-    }
-
-    #[test]
-    fn inline_call_with_self_type() {
-        check_assist(
-            inline_call,
-            r#"
-struct A(u32);
-impl A {
-    fn f() -> Self { Self(114514) }
-}
-fn main() {
-    A::f$0();
-}
-"#,
-            r#"
-struct A(u32);
-impl A {
-    fn f() -> Self { Self(114514) }
-}
-fn main() {
-    A(114514);
-}
 "#,
         )
     }
diff --git a/crates/ide-assists/src/handlers/inline_type_alias.rs b/crates/ide-assists/src/handlers/inline_type_alias.rs
index 9adf6381c1..054663a06a 100644
--- a/crates/ide-assists/src/handlers/inline_type_alias.rs
+++ b/crates/ide-assists/src/handlers/inline_type_alias.rs
@@ -1,9 +1,9 @@
 // Some ideas for future improvements:
 // - Support replacing aliases which are used in expressions, e.g. `A::new()`.
+// - "inline_alias_to_users" assist #10881.
 // - Remove unused aliases if there are no longer any users, see inline_call.rs.
 
 use hir::{HasSource, PathResolution};
-use ide_db::{defs::Definition, search::FileReference};
 use itertools::Itertools;
 use std::collections::HashMap;
 use syntax::{
@@ -16,78 +16,6 @@ use crate::{
     AssistId, AssistKind,
 };
 
-// Assist: inline_type_alias_uses
-//
-// Inline a type alias into all of its uses where possible.
-//
-// ```
-// type $0A = i32;
-// fn id(x: A) -> A {
-//     x
-// };
-// fn foo() {
-//     let _: A = 3;
-// }
-// ```
-// ->
-// ```
-// type A = i32;
-// fn id(x: i32) -> i32 {
-//     x
-// };
-// fn foo() {
-//     let _: i32 = 3;
-// }
-pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let name = ctx.find_node_at_offset::<ast::Name>()?;
-    let ast_alias = name.syntax().parent().and_then(ast::TypeAlias::cast)?;
-
-    let hir_alias = ctx.sema.to_def(&ast_alias)?;
-    let concrete_type = ast_alias.ty()?;
-
-    let usages = Definition::TypeAlias(hir_alias).usages(&ctx.sema);
-    if !usages.at_least_one() {
-        return None;
-    }
-
-    // until this is ok
-
-    acc.add(
-        AssistId("inline_type_alias_uses", AssistKind::RefactorInline),
-        "Inline type alias into all uses",
-        name.syntax().text_range(),
-        |builder| {
-            let usages = usages.all();
-
-            let mut inline_refs_for_file = |file_id, refs: Vec<FileReference>| {
-                builder.edit_file(file_id);
-
-                let path_types: Vec<ast::PathType> = refs
-                    .into_iter()
-                    .filter_map(|file_ref| match file_ref.name {
-                        ast::NameLike::NameRef(path_type) => {
-                            path_type.syntax().ancestors().nth(3).and_then(ast::PathType::cast)
-                        }
-                        _ => None,
-                    })
-                    .collect();
-
-                for (target, replacement) in path_types.into_iter().filter_map(|path_type| {
-                    let replacement = inline(&ast_alias, &path_type)?.to_text(&concrete_type);
-                    let target = path_type.syntax().text_range();
-                    Some((target, replacement))
-                }) {
-                    builder.replace(target, replacement);
-                }
-            };
-
-            for (file_id, refs) in usages.into_iter() {
-                inline_refs_for_file(file_id, refs);
-            }
-        },
-    )
-}
-
 // Assist: inline_type_alias
 //
 // Replace a type alias with its concrete type.
@@ -108,6 +36,11 @@ pub(crate) fn inline_type_alias_uses(acc: &mut Assists, ctx: &AssistContext<'_>)
 // }
 // ```
 pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
+    enum Replacement {
+        Generic { lifetime_map: LifetimeMap, const_and_type_map: ConstAndTypeMap },
+        Plain,
+    }
+
     let alias_instance = ctx.find_node_at_offset::<ast::PathType>()?;
     let concrete_type;
     let replacement;
@@ -126,7 +59,23 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
         _ => {
             let alias = get_type_alias(&ctx, &alias_instance)?;
             concrete_type = alias.ty()?;
-            replacement = inline(&alias, &alias_instance)?;
+
+            replacement = if let Some(alias_generics) = alias.generic_param_list() {
+                if alias_generics.generic_params().next().is_none() {
+                    cov_mark::hit!(no_generics_params);
+                    return None;
+                }
+
+                let instance_args =
+                    alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast);
+
+                Replacement::Generic {
+                    lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?,
+                    const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?,
+                }
+            } else {
+                Replacement::Plain
+            };
         }
     }
 
@@ -136,43 +85,17 @@ pub(crate) fn inline_type_alias(acc: &mut Assists, ctx: &AssistContext<'_>) -> O
         AssistId("inline_type_alias", AssistKind::RefactorInline),
         "Inline type alias",
         target,
-        |builder| builder.replace(target, replacement.to_text(&concrete_type)),
-    )
-}
-
-impl Replacement {
-    fn to_text(&self, concrete_type: &ast::Type) -> String {
-        match self {
-            Replacement::Generic { lifetime_map, const_and_type_map } => {
-                create_replacement(&lifetime_map, &const_and_type_map, &concrete_type)
-            }
-            Replacement::Plain => concrete_type.to_string(),
-        }
-    }
-}
-
-enum Replacement {
-    Generic { lifetime_map: LifetimeMap, const_and_type_map: ConstAndTypeMap },
-    Plain,
-}
-
-fn inline(alias_def: &ast::TypeAlias, alias_instance: &ast::PathType) -> Option<Replacement> {
-    let repl = if let Some(alias_generics) = alias_def.generic_param_list() {
-        if alias_generics.generic_params().next().is_none() {
-            cov_mark::hit!(no_generics_params);
-            return None;
-        }
-        let instance_args =
-            alias_instance.syntax().descendants().find_map(ast::GenericArgList::cast);
+        |builder| {
+            let replacement_text = match replacement {
+                Replacement::Generic { lifetime_map, const_and_type_map } => {
+                    create_replacement(&lifetime_map, &const_and_type_map, &concrete_type)
+                }
+                Replacement::Plain => concrete_type.to_string(),
+            };
 
-        Replacement::Generic {
-            lifetime_map: LifetimeMap::new(&instance_args, &alias_generics)?,
-            const_and_type_map: ConstAndTypeMap::new(&instance_args, &alias_generics)?,
-        }
-    } else {
-        Replacement::Plain
-    };
-    Some(repl)
+            builder.replace(target, replacement_text);
+        },
+    )
 }
 
 struct LifetimeMap(HashMap<String, ast::Lifetime>);
@@ -912,90 +835,4 @@ trait Tr {
 "#,
         );
     }
-
-    mod inline_type_alias_uses {
-        use crate::{handlers::inline_type_alias::inline_type_alias_uses, tests::check_assist};
-
-        #[test]
-        fn inline_uses() {
-            check_assist(
-                inline_type_alias_uses,
-                r#"
-type $0A = u32;
-
-fn foo() {
-    let _: A = 3;
-    let _: A = 4;
-}
-"#,
-                r#"
-type A = u32;
-
-fn foo() {
-    let _: u32 = 3;
-    let _: u32 = 4;
-}
-"#,
-            );
-        }
-
-        #[test]
-        fn inline_uses_across_files() {
-            check_assist(
-                inline_type_alias_uses,
-                r#"
-//- /lib.rs
-mod foo;
-type $0T<E> = Vec<E>;
-fn f() -> T<&str> {
-    vec!["hello"]
-}
-
-//- /foo.rs
-use super::T;
-fn foo() {
-    let _: T<i8> = Vec::new();
-}
-"#,
-                r#"
-//- /lib.rs
-mod foo;
-type T<E> = Vec<E>;
-fn f() -> Vec<&str> {
-    vec!["hello"]
-}
-
-//- /foo.rs
-use super::T;
-fn foo() {
-    let _: Vec<i8> = Vec::new();
-}
-"#,
-            );
-        }
-
-        #[test]
-        fn inline_uses_across_files_2() {
-            check_assist(
-                inline_type_alias_uses,
-                r#"
-//- /lib.rs
-mod foo;
-type $0I = i32;
-
-//- /foo.rs
-use super::I;
-fn foo() {
-    let _: I = 0;
-}
-"#,
-                r#"
-use super::I;
-fn foo() {
-    let _: i32 = 0;
-}
-"#,
-            );
-        }
-    }
 }
diff --git a/crates/ide-assists/src/lib.rs b/crates/ide-assists/src/lib.rs
index 7fb35143fa..fe87aa15fc 100644
--- a/crates/ide-assists/src/lib.rs
+++ b/crates/ide-assists/src/lib.rs
@@ -243,7 +243,6 @@ mod handlers {
             inline_call::inline_into_callers,
             inline_local_variable::inline_local_variable,
             inline_type_alias::inline_type_alias,
-            inline_type_alias::inline_type_alias_uses,
             introduce_named_generic::introduce_named_generic,
             introduce_named_lifetime::introduce_named_lifetime,
             invert_if::invert_if,
diff --git a/crates/ide-assists/src/utils/suggest_name.rs b/crates/ide-assists/src/utils/suggest_name.rs
index c521a10fcc..662ddd063f 100644
--- a/crates/ide-assists/src/utils/suggest_name.rs
+++ b/crates/ide-assists/src/utils/suggest_name.rs
@@ -55,7 +55,6 @@ const USELESS_METHODS: &[&str] = &[
     "iter",
     "into_iter",
     "iter_mut",
-    "into_future",
 ];
 
 pub(crate) fn for_generic_parameter(ty: &ast::ImplTraitType) -> SmolStr {
diff --git a/crates/ide-completion/src/completions/dot.rs b/crates/ide-completion/src/completions/dot.rs
index 02004ff7b6..cf40ca489c 100644
--- a/crates/ide-completion/src/completions/dot.rs
+++ b/crates/ide-completion/src/completions/dot.rs
@@ -19,7 +19,7 @@ pub(crate) fn complete_dot(
     };
 
     // Suggest .await syntax for types that implement Future trait
-    if receiver_ty.impls_into_future(ctx.db) {
+    if receiver_ty.impls_future(ctx.db) {
         let mut item =
             CompletionItem::new(CompletionItemKind::Keyword, ctx.source_range(), "await");
         item.detail("expr.await");
diff --git a/crates/ide-completion/src/completions/keyword.rs b/crates/ide-completion/src/completions/keyword.rs
index 1d03c8cc5c..3989a451bd 100644
--- a/crates/ide-completion/src/completions/keyword.rs
+++ b/crates/ide-completion/src/completions/keyword.rs
@@ -75,17 +75,16 @@ impl Future for A {}
 fn foo(a: A) { a.$0 }
 "#,
             expect![[r#"
-                kw await                  expr.await
-                me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
-                sn box                    Box::new(expr)
-                sn call                   function(expr)
-                sn dbg                    dbg!(expr)
-                sn dbgr                   dbg!(&expr)
-                sn let                    let
-                sn letm                   let mut
-                sn match                  match expr {}
-                sn ref                    &expr
-                sn refm                   &mut expr
+                kw await expr.await
+                sn box   Box::new(expr)
+                sn call  function(expr)
+                sn dbg   dbg!(expr)
+                sn dbgr  dbg!(&expr)
+                sn let   let
+                sn letm  let mut
+                sn match match expr {}
+                sn ref   &expr
+                sn refm  &mut expr
             "#]],
         );
 
@@ -99,45 +98,18 @@ fn foo() {
 }
 "#,
             expect![[r#"
-                kw await                  expr.await
-                me into_future() (use core::future::IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
-                sn box                    Box::new(expr)
-                sn call                   function(expr)
-                sn dbg                    dbg!(expr)
-                sn dbgr                   dbg!(&expr)
-                sn let                    let
-                sn letm                   let mut
-                sn match                  match expr {}
-                sn ref                    &expr
-                sn refm                   &mut expr
+                kw await expr.await
+                sn box   Box::new(expr)
+                sn call  function(expr)
+                sn dbg   dbg!(expr)
+                sn dbgr  dbg!(&expr)
+                sn let   let
+                sn letm  let mut
+                sn match match expr {}
+                sn ref   &expr
+                sn refm  &mut expr
             "#]],
-        );
-    }
-
-    #[test]
-    fn test_completion_await_impls_into_future() {
-        check(
-            r#"
-//- minicore: future
-use core::future::*;
-struct A {}
-impl IntoFuture for A {}
-fn foo(a: A) { a.$0 }
-"#,
-            expect![[r#"
-                kw await                  expr.await
-                me into_future() (as IntoFuture) fn(self) -> <Self as IntoFuture>::IntoFuture
-                sn box                    Box::new(expr)
-                sn call                   function(expr)
-                sn dbg                    dbg!(expr)
-                sn dbgr                   dbg!(&expr)
-                sn let                    let
-                sn letm                   let mut
-                sn match                  match expr {}
-                sn ref                    &expr
-                sn refm                   &mut expr
-            "#]],
-        );
+        )
     }
 
     #[test]
diff --git a/crates/ide/src/goto_definition.rs b/crates/ide/src/goto_definition.rs
index 36a648fe4a..d6cd5783f0 100644
--- a/crates/ide/src/goto_definition.rs
+++ b/crates/ide/src/goto_definition.rs
@@ -1664,40 +1664,6 @@ fn f() {
         );
     }
 
-    #[test]
-    fn goto_await_into_future_poll() {
-        check(
-            r#"
-//- minicore: future
-
-struct Futurable;
-
-impl core::future::IntoFuture for Futurable {
-    type IntoFuture = MyFut;
-}
-
-struct MyFut;
-
-impl core::future::Future for MyFut {
-    type Output = ();
-
-    fn poll(
-     //^^^^
-        self: std::pin::Pin<&mut Self>,
-        cx: &mut std::task::Context<'_>
-    ) -> std::task::Poll<Self::Output>
-    {
-        ()
-    }
-}
-
-fn f() {
-    Futurable.await$0;
-}
-"#,
-        );
-    }
-
     #[test]
     fn goto_try_op() {
         check(
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index e0bcc80b31..943d043bc1 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -51,12 +51,6 @@ pub(crate) fn handle_workspace_reload(state: &mut GlobalState, _: ()) -> Result<
     Ok(())
 }
 
-pub(crate) fn handle_cancel_flycheck(state: &mut GlobalState, _: ()) -> Result<()> {
-    let _p = profile::span("handle_stop_flycheck");
-    state.flycheck.iter().for_each(|flycheck| flycheck.cancel());
-    Ok(())
-}
-
 pub(crate) fn handle_analyzer_status(
     snap: GlobalStateSnapshot,
     params: lsp_ext::AnalyzerStatusParams,
@@ -709,8 +703,10 @@ pub(crate) fn handle_runnables(
 
     let mut res = Vec::new();
     for runnable in snap.analysis.runnables(file_id)? {
-        if should_skip_for_offset(&runnable, offset) {
-            continue;
+        if let Some(offset) = offset {
+            if !runnable.nav.full_range.contains_inclusive(offset) {
+                continue;
+            }
         }
         if should_skip_target(&runnable, cargo_spec.as_ref()) {
             continue;
@@ -776,14 +772,6 @@ pub(crate) fn handle_runnables(
     Ok(res)
 }
 
-fn should_skip_for_offset(runnable: &Runnable, offset: Option<TextSize>) -> bool {
-    match offset {
-        None => false,
-        _ if matches!(&runnable.kind, RunnableKind::TestMod { .. }) => false,
-        Some(offset) => !runnable.nav.full_range.contains_inclusive(offset),
-    }
-}
-
 pub(crate) fn handle_related_tests(
     snap: GlobalStateSnapshot,
     params: lsp_types::TextDocumentPositionParams,
@@ -1777,7 +1765,7 @@ fn run_rustfmt(
 
     let line_index = snap.file_line_index(file_id)?;
 
-    let mut command = match snap.config.rustfmt() {
+    let mut rustfmt = match snap.config.rustfmt() {
         RustfmtConfig::Rustfmt { extra_args, enable_range_formatting } => {
             let mut cmd = process::Command::new(toolchain::rustfmt());
             cmd.args(extra_args);
@@ -1842,12 +1830,12 @@ fn run_rustfmt(
         }
     };
 
-    let mut rustfmt = command
+    let mut rustfmt = rustfmt
         .stdin(Stdio::piped())
         .stdout(Stdio::piped())
         .stderr(Stdio::piped())
         .spawn()
-        .context(format!("Failed to spawn {:?}", command))?;
+        .context(format!("Failed to spawn {:?}", rustfmt))?;
 
     rustfmt.stdin.as_mut().unwrap().write_all(file.as_bytes())?;
 
@@ -1866,11 +1854,7 @@ fn run_rustfmt(
                 // formatting because otherwise an error is surfaced to the user on top of the
                 // syntax error diagnostics they're already receiving. This is especially jarring
                 // if they have format on save enabled.
-                tracing::warn!(
-                    ?command,
-                    %captured_stderr,
-                    "rustfmt exited with status 1"
-                );
+                tracing::info!("rustfmt exited with status 1, assuming parse error and ignoring");
                 Ok(None)
             }
             _ => {
diff --git a/crates/rust-analyzer/src/lsp_ext.rs b/crates/rust-analyzer/src/lsp_ext.rs
index e61c8b643d..5f0e108624 100644
--- a/crates/rust-analyzer/src/lsp_ext.rs
+++ b/crates/rust-analyzer/src/lsp_ext.rs
@@ -129,14 +129,6 @@ pub struct ExpandedMacro {
     pub expansion: String,
 }
 
-pub enum CancelFlycheck {}
-
-impl Request for CancelFlycheck {
-    type Params = ();
-    type Result = ();
-    const METHOD: &'static str = "rust-analyzer/cancelFlycheck";
-}
-
 pub enum MatchingBrace {}
 
 impl Request for MatchingBrace {
diff --git a/crates/rust-analyzer/src/main_loop.rs b/crates/rust-analyzer/src/main_loop.rs
index f187547019..7741999824 100644
--- a/crates/rust-analyzer/src/main_loop.rs
+++ b/crates/rust-analyzer/src/main_loop.rs
@@ -288,7 +288,7 @@ impl GlobalState {
 
             if became_quiescent {
                 // Project has loaded properly, kick off initial flycheck
-                self.flycheck.iter().for_each(FlycheckHandle::restart);
+                self.flycheck.iter().for_each(FlycheckHandle::update);
                 if self.config.prefill_caches() {
                     self.prime_caches_queue.request_op("became quiescent".to_string());
                 }
@@ -590,7 +590,6 @@ impl GlobalState {
             .on_sync_mut::<lsp_ext::ReloadWorkspace>(handlers::handle_workspace_reload)
             .on_sync_mut::<lsp_ext::MemoryUsage>(handlers::handle_memory_usage)
             .on_sync_mut::<lsp_ext::ShuffleCrateGraph>(handlers::handle_shuffle_crate_graph)
-            .on_sync_mut::<lsp_ext::CancelFlycheck>(handlers::handle_cancel_flycheck)
             .on_sync::<lsp_ext::JoinLines>(handlers::handle_join_lines)
             .on_sync::<lsp_ext::OnEnter>(handlers::handle_on_enter)
             .on_sync::<lsp_types::request::SelectionRangeRequest>(handlers::handle_selection_range)
@@ -780,7 +779,7 @@ impl GlobalState {
                             for (id, _) in workspace_ids.clone() {
                                 if id == flycheck.id() {
                                     updated = true;
-                                    flycheck.restart();
+                                    flycheck.update();
                                     continue;
                                 }
                             }
@@ -799,7 +798,7 @@ impl GlobalState {
                 // No specific flycheck was triggered, so let's trigger all of them.
                 if !updated {
                     for flycheck in &this.flycheck {
-                        flycheck.restart();
+                        flycheck.update();
                     }
                 }
                 Ok(())
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md
index 6d2c7d7b06..5040643d34 100644
--- a/docs/dev/lsp-extensions.md
+++ b/docs/dev/lsp-extensions.md
@@ -1,5 +1,5 @@
 <!---
-lsp_ext.rs hash: 7b710095d773b978
+lsp_ext.rs hash: 2a188defec26cc7c
 
 If you need to change the above hash to make the test pass, please check if you
 need to adjust this doc as well and ping this issue:
diff --git a/editors/code/package.json b/editors/code/package.json
index 2e38c05730..0714b356fe 100644
--- a/editors/code/package.json
+++ b/editors/code/package.json
@@ -235,11 +235,6 @@
                 "command": "rust-analyzer.moveItemDown",
                 "title": "Move item down",
                 "category": "rust-analyzer"
-            },
-            {
-                "command": "rust-analyzer.cancelFlycheck",
-                "title": "Cancel running flychecks",
-                "category": "rust-analyzer"
             }
         ],
         "keybindings": [
diff --git a/editors/code/src/commands.ts b/editors/code/src/commands.ts
index a21b304bbd..12f666401f 100644
--- a/editors/code/src/commands.ts
+++ b/editors/code/src/commands.ts
@@ -817,12 +817,6 @@ export function openDocs(ctx: Ctx): Cmd {
     };
 }
 
-export function cancelFlycheck(ctx: Ctx): Cmd {
-    return async () => {
-        await ctx.client.sendRequest(ra.cancelFlycheck);
-    };
-}
-
 export function resolveCodeAction(ctx: Ctx): Cmd {
     const client = ctx.client;
     return async (params: lc.CodeAction) => {
diff --git a/editors/code/src/config.ts b/editors/code/src/config.ts
index b83582a344..1c58040d58 100644
--- a/editors/code/src/config.ts
+++ b/editors/code/src/config.ts
@@ -5,6 +5,8 @@ import { log } from "./util";
 
 export type UpdatesChannel = "stable" | "nightly";
 
+const NIGHTLY_TAG = "nightly";
+
 export type RunnableEnvCfg =
     | undefined
     | Record<string, string>
@@ -173,6 +175,10 @@ export class Config {
             gotoTypeDef: this.get<boolean>("hover.actions.gotoTypeDef.enable"),
         };
     }
+
+    get currentExtensionIsNightly() {
+        return this.package.releaseTag === NIGHTLY_TAG;
+    }
 }
 
 export async function updateConfig(config: vscode.WorkspaceConfiguration) {
diff --git a/editors/code/src/lsp_ext.ts b/editors/code/src/lsp_ext.ts
index 875261c48a..f80af78a74 100644
--- a/editors/code/src/lsp_ext.ts
+++ b/editors/code/src/lsp_ext.ts
@@ -75,23 +75,6 @@ export const expandMacro = new lc.RequestType<ExpandMacroParams, ExpandedMacro |
     "rust-analyzer/expandMacro"
 );
 
-export const relatedTests = new lc.RequestType<lc.TextDocumentPositionParams, TestInfo[], void>(
-    "rust-analyzer/relatedTests"
-);
-
-export const cancelFlycheck = new lc.RequestType0<void, void>("rust-analyzer/cancelFlycheck");
-
-// Experimental extensions
-
-export interface SsrParams {
-    query: string;
-    parseOnly: boolean;
-    textDocument: lc.TextDocumentIdentifier;
-    position: lc.Position;
-    selections: readonly lc.Range[];
-}
-export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>("experimental/ssr");
-
 export interface MatchingBraceParams {
     textDocument: lc.TextDocumentIdentifier;
     positions: lc.Position[];
@@ -144,6 +127,19 @@ export interface TestInfo {
     runnable: Runnable;
 }
 
+export const relatedTests = new lc.RequestType<lc.TextDocumentPositionParams, TestInfo[], void>(
+    "rust-analyzer/relatedTests"
+);
+
+export interface SsrParams {
+    query: string;
+    parseOnly: boolean;
+    textDocument: lc.TextDocumentIdentifier;
+    position: lc.Position;
+    selections: readonly lc.Range[];
+}
+export const ssr = new lc.RequestType<SsrParams, lc.WorkspaceEdit, void>("experimental/ssr");
+
 export interface CommandLink extends lc.Command {
     /**
      * A tooltip for the command, when represented in the UI.
diff --git a/editors/code/src/main.ts b/editors/code/src/main.ts
index a9847dd2a6..d78b711a47 100644
--- a/editors/code/src/main.ts
+++ b/editors/code/src/main.ts
@@ -163,7 +163,6 @@ async function initCommonContext(context: vscode.ExtensionContext, ctx: Ctx) {
     ctx.registerCommand("peekTests", commands.peekTests);
     ctx.registerCommand("moveItemUp", commands.moveItemUp);
     ctx.registerCommand("moveItemDown", commands.moveItemDown);
-    ctx.registerCommand("cancelFlycheck", commands.cancelFlycheck);
 
     defaultOnEnter.dispose();
     ctx.registerCommand("onEnter", commands.onEnter);


Test patch:
diff --git a/crates/hir-ty/src/tests/patterns.rs b/crates/hir-ty/src/tests/patterns.rs
index eb04bf8778..94efe7bc11 100644
--- a/crates/hir-ty/src/tests/patterns.rs
+++ b/crates/hir-ty/src/tests/patterns.rs
@@ -488,42 +488,6 @@ fn infer_adt_pattern() {
     );
 }
 
-#[test]
-fn tuple_struct_destructured_with_self() {
-    check_infer(
-        r#"
-struct Foo(usize,);
-impl Foo {
-    fn f() {
-        let Self(s,) = &Foo(0,);
-        let Self(s,) = &mut Foo(0,);
-        let Self(s,) = Foo(0,);
-    }
-}
-        "#,
-        expect![[r#"
-            42..151 '{     ...     }': ()
-            56..64 'Self(s,)': Foo
-            61..62 's': &usize
-            67..75 '&Foo(0,)': &Foo
-            68..71 'Foo': Foo(usize) -> Foo
-            68..75 'Foo(0,)': Foo
-            72..73 '0': usize
-            89..97 'Self(s,)': Foo
-            94..95 's': &mut usize
-            100..112 '&mut Foo(0,)': &mut Foo
-            105..108 'Foo': Foo(usize) -> Foo
-            105..112 'Foo(0,)': Foo
-            109..110 '0': usize
-            126..134 'Self(s,)': Foo
-            131..132 's': usize
-            137..140 'Foo': Foo(usize) -> Foo
-            137..144 'Foo(0,)': Foo
-            141..142 '0': usize
-        "#]],
-    );
-}
-
 #[test]
 fn enum_variant_through_self_in_pattern() {
     check_infer(
diff --git a/crates/hir-ty/src/tests/traits.rs b/crates/hir-ty/src/tests/traits.rs
index 0f37970e2b..75802a5eb4 100644
--- a/crates/hir-ty/src/tests/traits.rs
+++ b/crates/hir-ty/src/tests/traits.rs
@@ -137,31 +137,6 @@ fn not_send() -> Box<dyn Future<Output = ()> + 'static> {
     );
 }
 
-#[test]
-fn into_future_trait() {
-    check_types(
-        r#"
-//- minicore: future
-struct Futurable;
-impl core::future::IntoFuture for Futurable {
-    type Output = u64;
-    type IntoFuture = IntFuture;
-}
-
-struct IntFuture;
-impl core::future::Future for IntFuture {
-    type Output = u64;
-}
-
-fn test() {
-    let r = Futurable;
-    let v = r.await;
-    v;
-} //^ u64
-"#,
-    );
-}
-
 #[test]
 fn infer_try() {
     check_types(
@@ -1501,34 +1476,6 @@ fn test(x: Trait, y: &Trait) -> u64 {
             165..172 'z.foo()': u64
         "#]],
     );
-
-    check_infer_with_mismatches(
-        r#"
-//- minicore: fn, coerce_unsized
-struct S;
-impl S {
-    fn foo(&self) {}
-}
-fn f(_: &Fn(S)) {}
-fn main() {
-    f(&|number| number.foo());
-}
-        "#,
-        expect![[r#"
-            31..35 'self': &S
-            37..39 '{}': ()
-            47..48 '_': &dyn Fn(S)
-            58..60 '{}': ()
-            71..105 '{     ...()); }': ()
-            77..78 'f': fn f(&dyn Fn(S))
-            77..102 'f(&|nu...foo())': ()
-            79..101 '&|numb....foo()': &|S| -> ()
-            80..101 '|numbe....foo()': |S| -> ()
-            81..87 'number': S
-            89..95 'number': S
-            89..101 'number.foo()': ()
-        "#]],
-    )
 }
 
 #[test]
diff --git a/crates/ide-assists/src/tests/generated.rs b/crates/ide-assists/src/tests/generated.rs
index 22319f3613..6eaab48a32 100644
--- a/crates/ide-assists/src/tests/generated.rs
+++ b/crates/ide-assists/src/tests/generated.rs
@@ -1356,31 +1356,6 @@ fn main() {
     )
 }
 
-#[test]
-fn doctest_inline_type_alias_uses() {
-    check_doc_test(
-        "inline_type_alias_uses",
-        r#####"
-type $0A = i32;
-fn id(x: A) -> A {
-    x
-};
-fn foo() {
-    let _: A = 3;
-}
-"#####,
-        r#####"
-type A = i32;
-fn id(x: i32) -> i32 {
-    x
-};
-fn foo() {
-    let _: i32 = 3;
-}
-"#####,
-    )
-}
-
 #[test]
 fn doctest_introduce_named_generic() {
     check_doc_test(
diff --git a/crates/test-utils/src/minicore.rs b/crates/test-utils/src/minicore.rs
index 6df29db474..f48d1ec66a 100644
--- a/crates/test-utils/src/minicore.rs
+++ b/crates/test-utils/src/minicore.rs
@@ -471,21 +471,6 @@ pub mod future {
         #[lang = "poll"]
         fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output>;
     }
-
-    pub trait IntoFuture {
-        type Output;
-        type IntoFuture: Future<Output = Self::Output>;
-        #[lang = "into_future"]
-        fn into_future(self) -> Self::IntoFuture;
-    }
-
-    impl<F: Future> IntoFuture for F {
-        type Output = F::Output;
-        type IntoFuture = F;
-        fn into_future(self) -> F {
-            self
-        }
-    }
 }
 pub mod task {
     pub enum Poll<T> {