Repository: rust-lang/rust-analyzer
Pull request #12773 (2022-07-16 10:17:52)

fix: Improve self param completion applicability
Fixes https://github.com/rust-lang/rust-analyzer/issues/9522


Patch:
diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml
index 3540706095..8ba4f07d4a 100644
--- a/.github/workflows/ci.yaml
+++ b/.github/workflows/ci.yaml
@@ -37,10 +37,21 @@ jobs:
         ref: ${{ github.event.pull_request.head.sha }}
         fetch-depth: 20
 
+    # We need to disable the existing toolchain to avoid updating rust-docs
+    # which takes a long time. The fastest way to do this is to rename the
+    # existing folder, as deleting it takes about as much time as not doing
+    # anything and just updating rust-docs.
+    - name: Rename existing rust toolchain (Windows)
+      if: matrix.os == 'windows-latest'
+      run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
+
     - name: Install Rust toolchain
-      run: |
-        rustup update stable
-        rustup component add rustfmt rust-src
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rustfmt, rust-src
 
     - name: Cache Dependencies
       uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
@@ -68,9 +79,14 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: |
-        rustup update stable
-        rustup target add ${{ env.targets }} ${{ env.targets_ide }}
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+
+    - name: Install Rust targets
+      run: rustup target add ${{ env.targets }} ${{ env.targets_ide }}
 
     - name: Cache Dependencies
       uses: Swatinem/rust-cache@ce325b60658c1b38465c06cc965b79baf32c1e72
diff --git a/.github/workflows/metrics.yaml b/.github/workflows/metrics.yaml
index 1407bd8f68..af6c610784 100644
--- a/.github/workflows/metrics.yaml
+++ b/.github/workflows/metrics.yaml
@@ -20,9 +20,12 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: |
-        rustup update stable
-        rustup component add rustfmt rust-src
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rust-src
 
     - name: Collect metrics
       run: cargo xtask metrics
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 7020726165..e4892dccf4 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -20,10 +20,16 @@ jobs:
           fetch-depth: 0
 
       - name: Install Rust toolchain
-        run: rustup update stable
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          profile: minimal
+          override: true
 
       - name: Install cargo-workspaces
-        run: cargo install cargo-workspaces
+        uses: actions-rs/install@v0.1
+        with:
+          crate: cargo-workspaces
 
       - name: Release
         env:
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index cb47d3973e..9205d86f93 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -55,11 +55,31 @@ jobs:
         with:
           fetch-depth: ${{ env.FETCH_DEPTH }}
 
+      # We need to disable the existing toolchain to avoid updating rust-docs
+      # which takes a long time. The fastest way to do this is to rename the
+      # existing folder, as deleting it takes about as much time as not doing
+      # anything and just updating rust-docs.
+      - name: Rename existing Rust toolchain
+        if: matrix.os == 'windows-latest'
+        run: Rename-Item C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc C:\Users\runneradmin\.rustup\toolchains\stable-x86_64-pc-windows-msvc.old
+
       - name: Install Rust toolchain
-        run: |
-          rustup update stable
-          rustup target add ${{ matrix.target }}
-          rustup component add rust-src
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          target: ${{ matrix.target }}
+          profile: minimal
+          override: true
+
+      - name: Install Rust library source
+        if: matrix.target == 'x86_64-unknown-linux-gnu'
+        uses: actions-rs/toolchain@v1
+        with:
+          toolchain: stable
+          target: ${{ matrix.target }}
+          profile: minimal
+          override: true
+          components: rust-src
 
       - name: Install Node.js
         uses: actions/setup-node@v1
diff --git a/.github/workflows/rustdoc.yaml b/.github/workflows/rustdoc.yaml
index 5ed4e8ca64..227fab54eb 100644
--- a/.github/workflows/rustdoc.yaml
+++ b/.github/workflows/rustdoc.yaml
@@ -20,7 +20,12 @@ jobs:
       uses: actions/checkout@v3
 
     - name: Install Rust toolchain
-      run: rustup update stable
+      uses: actions-rs/toolchain@v1
+      with:
+        toolchain: stable
+        profile: minimal
+        override: true
+        components: rustfmt, rust-src
 
     - name: Build Documentation
       run: cargo doc --all --no-deps
diff --git a/crates/hir-def/src/nameres.rs b/crates/hir-def/src/nameres.rs
index a32513cf65..536eecf020 100644
--- a/crates/hir-def/src/nameres.rs
+++ b/crates/hir-def/src/nameres.rs
@@ -219,7 +219,7 @@ impl DefMap {
 
         let edition = crate_graph[krate].edition;
         let origin = ModuleOrigin::CrateRoot { definition: crate_graph[krate].root_file_id };
-        let def_map = DefMap::empty(krate, edition, ModuleData::new(origin, Visibility::Public));
+        let def_map = DefMap::empty(krate, edition, origin);
         let def_map = collector::collect_defs(
             db,
             def_map,
@@ -241,26 +241,30 @@ impl DefMap {
             return None;
         }
 
-        let parent_map = block.module.def_map(db);
-        let krate = block.module.krate;
-        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
-        // NB: we use `None` as block here, which would be wrong for implicit
-        // modules declared by blocks with items. At the moment, we don't use
-        // this visibility for anything outside IDE, so that's probably OK.
-        let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
-        let module_data =
-            ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
+        let block_info = BlockInfo { block: block_id, parent: block.module };
 
-        let mut def_map = DefMap::empty(krate, parent_map.edition, module_data);
-        def_map.block = Some(BlockInfo { block: block_id, parent: block.module });
+        let parent_map = block.module.def_map(db);
+        let mut def_map = DefMap::empty(
+            block.module.krate,
+            parent_map.edition,
+            ModuleOrigin::BlockExpr { block: block.ast_id },
+        );
+        def_map.block = Some(block_info);
 
         let def_map = collector::collect_defs(db, def_map, tree_id);
         Some(Arc::new(def_map))
     }
 
-    fn empty(krate: CrateId, edition: Edition, module_data: ModuleData) -> DefMap {
+    fn empty(krate: CrateId, edition: Edition, root_module_origin: ModuleOrigin) -> DefMap {
         let mut modules: Arena<ModuleData> = Arena::default();
-        let root = modules.alloc(module_data);
+
+        let local_id = LocalModuleId::from_raw(la_arena::RawIdx::from(0));
+        // NB: we use `None` as block here, which would be wrong for implicit
+        // modules declared by blocks with items. At the moment, we don't use
+        // this visibility for anything outside IDE, so that's probably OK.
+        let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
+        let root = modules.alloc(ModuleData::new(root_module_origin, visibility));
+        assert_eq!(local_id, root);
 
         DefMap {
             _c: Count::new(),
diff --git a/crates/hir-def/src/nameres/collector.rs b/crates/hir-def/src/nameres/collector.rs
index 221e78ac84..4ed81c1c2a 100644
--- a/crates/hir-def/src/nameres/collector.rs
+++ b/crates/hir-def/src/nameres/collector.rs
@@ -2138,8 +2138,7 @@ mod tests {
 
         let edition = db.crate_graph()[krate].edition;
         let module_origin = ModuleOrigin::CrateRoot { definition: file_id };
-        let def_map =
-            DefMap::empty(krate, edition, ModuleData::new(module_origin, Visibility::Public));
+        let def_map = DefMap::empty(krate, edition, module_origin);
         do_collect_defs(&db, def_map)
     }
 
diff --git a/crates/hir-expand/src/lib.rs b/crates/hir-expand/src/lib.rs
index 8fcfad2009..0844e1f625 100644
--- a/crates/hir-expand/src/lib.rs
+++ b/crates/hir-expand/src/lib.rs
@@ -778,19 +778,36 @@ impl<'a> InFile<&'a SyntaxNode> {
     /// For attributes and derives, this will point back to the attribute only.
     /// For the entire item `InFile::use original_file_range_full`.
     pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
+        if let Some(res) = self.original_file_range_opt(db) {
+            return res;
+        }
+
+        // Fall back to whole macro call.
         match self.file_id.0 {
             HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
             HirFileIdRepr::MacroFile(mac_file) => {
-                if let Some(res) = self.original_file_range_opt(db) {
-                    return res;
-                }
-                // Fall back to whole macro call.
                 let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
                 loc.kind.original_call_range(db)
             }
         }
     }
 
+    /// Falls back to the macro call range if the node cannot be mapped up fully.
+    pub fn original_file_range_full(self, db: &dyn db::AstDatabase) -> FileRange {
+        if let Some(res) = self.original_file_range_opt(db) {
+            return res;
+        }
+
+        // Fall back to whole macro call.
+        match self.file_id.0 {
+            HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
+            HirFileIdRepr::MacroFile(mac_file) => {
+                let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
+                loc.kind.original_call_range_with_body(db)
+            }
+        }
+    }
+
     /// Attempts to map the syntax node back up its macro calls.
     pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
         match ascend_node_border_tokens(db, self) {
@@ -817,49 +834,6 @@ impl InFile<SyntaxToken> {
         let expansion = self.file_id.expansion_info(db)?;
         expansion.map_token_up(db, self.as_ref()).map(|(it, _)| it)
     }
-
-    /// Falls back to the macro call range if the node cannot be mapped up fully.
-    pub fn original_file_range(self, db: &dyn db::AstDatabase) -> FileRange {
-        match self.file_id.0 {
-            HirFileIdRepr::FileId(file_id) => FileRange { file_id, range: self.value.text_range() },
-            HirFileIdRepr::MacroFile(mac_file) => {
-                if let Some(res) = self.original_file_range_opt(db) {
-                    return res;
-                }
-                // Fall back to whole macro call.
-                let loc = db.lookup_intern_macro_call(mac_file.macro_call_id);
-                loc.kind.original_call_range(db)
-            }
-        }
-    }
-
-    /// Attempts to map the syntax node back up its macro calls.
-    pub fn original_file_range_opt(self, db: &dyn db::AstDatabase) -> Option<FileRange> {
-        match self.file_id.0 {
-            HirFileIdRepr::FileId(file_id) => {
-                Some(FileRange { file_id, range: self.value.text_range() })
-            }
-            HirFileIdRepr::MacroFile(_) => {
-                let expansion = self.file_id.expansion_info(db)?;
-                let InFile { file_id, value } = ascend_call_token(db, &expansion, self)?;
-                let original_file = file_id.original_file(db);
-                if file_id != original_file.into() {
-                    return None;
-                }
-                Some(FileRange { file_id: original_file, range: value.text_range() })
-            }
-        }
-    }
-
-    pub fn ancestors_with_macros(
-        self,
-        db: &dyn db::AstDatabase,
-    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
-        self.value.parent().into_iter().flat_map({
-            let file_id = self.file_id;
-            move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
-        })
-    }
 }
 
 fn ascend_node_border_tokens(
@@ -893,6 +867,18 @@ fn ascend_call_token(
     None
 }
 
+impl InFile<SyntaxToken> {
+    pub fn ancestors_with_macros(
+        self,
+        db: &dyn db::AstDatabase,
+    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
+        self.value.parent().into_iter().flat_map({
+            let file_id = self.file_id;
+            move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
+        })
+    }
+}
+
 impl<N: AstNode> InFile<N> {
     pub fn descendants<T: AstNode>(self) -> impl Iterator<Item = InFile<T>> {
         self.value.syntax().descendants().filter_map(T::cast).map(move |n| self.with_value(n))
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index b4fd70d082..e26c8440d9 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -505,7 +505,7 @@ impl HirDisplay for Module {
         // FIXME: Module doesn't have visibility saved in data.
         match self.name(f.db) {
             Some(name) => write!(f, "mod {}", name),
-            None if self.is_crate_root(f.db) => match self.krate(f.db).display_name(f.db) {
+            None if self.is_crate_root(f.db) => match self.krate().display_name(f.db) {
                 Some(name) => write!(f, "extern crate {}", name),
                 None => f.write_str("extern crate {unknown}"),
             },
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 78ed3f3ce9..96424d087e 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -3307,15 +3307,6 @@ impl Type {
         let tys = hir_ty::replace_errors_with_variables(&(self.ty.clone(), to.ty.clone()));
         hir_ty::could_coerce(db, self.env.clone(), &tys)
     }
-
-    pub fn as_type_param(&self, db: &dyn HirDatabase) -> Option<TypeParam> {
-        match self.ty.kind(Interner) {
-            TyKind::Placeholder(p) => Some(TypeParam {
-                id: TypeParamId::from_unchecked(hir_ty::from_placeholder_idx(db, *p)),
-            }),
-            _ => None,
-        }
-    }
 }
 
 #[derive(Debug)]
@@ -3582,27 +3573,3 @@ impl HasCrate for Macro {
         self.module(db).krate()
     }
 }
-
-impl HasCrate for Trait {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Static {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Adt {
-    fn krate(&self, db: &dyn HirDatabase) -> Crate {
-        self.module(db).krate()
-    }
-}
-
-impl HasCrate for Module {
-    fn krate(&self, _: &dyn HirDatabase) -> Crate {
-        Module::krate(*self)
-    }
-}
diff --git a/crates/ide-assists/src/handlers/extract_function.rs b/crates/ide-assists/src/handlers/extract_function.rs
index 94b638d4c6..9233c198df 100644
--- a/crates/ide-assists/src/handlers/extract_function.rs
+++ b/crates/ide-assists/src/handlers/extract_function.rs
@@ -2,9 +2,7 @@ use std::iter;
 
 use ast::make;
 use either::Either;
-use hir::{
-    HasSource, HirDisplay, InFile, Local, ModuleDef, PathResolution, Semantics, TypeInfo, TypeParam,
-};
+use hir::{HasSource, HirDisplay, InFile, Local, ModuleDef, Semantics, TypeInfo};
 use ide_db::{
     defs::{Definition, NameRefClass},
     famous_defs::FamousDefs,
@@ -20,7 +18,7 @@ use syntax::{
     ast::{
         self,
         edit::{AstNodeEdit, IndentLevel},
-        AstNode, HasGenericParams,
+        AstNode,
     },
     match_ast, ted, SyntaxElement,
     SyntaxKind::{self, COMMENT},
@@ -296,8 +294,6 @@ struct ContainerInfo {
     parent_loop: Option<SyntaxNode>,
     /// The function's return type, const's type etc.
     ret_type: Option<hir::Type>,
-    generic_param_lists: Vec<ast::GenericParamList>,
-    where_clauses: Vec<ast::WhereClause>,
 }
 
 /// Control flow that is exported from extracted function
@@ -521,24 +517,6 @@ impl FunctionBody {
         }
     }
 
-    fn descendants(&self) -> impl Iterator<Item = SyntaxNode> {
-        match self {
-            FunctionBody::Expr(expr) => expr.syntax().descendants(),
-            FunctionBody::Span { parent, .. } => parent.syntax().descendants(),
-        }
-    }
-
-    fn descendant_paths(&self) -> impl Iterator<Item = ast::Path> {
-        self.descendants().filter_map(|node| {
-            match_ast! {
-                match node {
-                    ast::Path(it) => Some(it),
-                    _ => None
-                }
-            }
-        })
-    }
-
     fn from_expr(expr: ast::Expr) -> Option<Self> {
         match expr {
             ast::Expr::BreakExpr(it) => it.expr().map(Self::Expr),
@@ -753,7 +731,6 @@ impl FunctionBody {
                 parent_loop.get_or_insert(loop_.syntax().clone());
             }
         };
-
         let (is_const, expr, ty) = loop {
             let anc = ancestors.next()?;
             break match_ast! {
@@ -821,20 +798,7 @@ impl FunctionBody {
             container_tail.zip(self.tail_expr()).map_or(false, |(container_tail, body_tail)| {
                 container_tail.syntax().text_range().contains_range(body_tail.syntax().text_range())
             });
-
-        let parent = self.parent()?;
-        let parents = generic_parents(&parent);
-        let generic_param_lists = parents.iter().filter_map(|it| it.generic_param_list()).collect();
-        let where_clauses = parents.iter().filter_map(|it| it.where_clause()).collect();
-
-        Some(ContainerInfo {
-            is_in_tail,
-            is_const,
-            parent_loop,
-            ret_type: ty,
-            generic_param_lists,
-            where_clauses,
-        })
+        Some(ContainerInfo { is_in_tail, is_const, parent_loop, ret_type: ty })
     }
 
     fn return_ty(&self, ctx: &AssistContext) -> Option<RetType> {
@@ -991,56 +955,6 @@ impl FunctionBody {
     }
 }
 
-enum GenericParent {
-    Fn(ast::Fn),
-    Impl(ast::Impl),
-    Trait(ast::Trait),
-}
-
-impl GenericParent {
-    fn generic_param_list(&self) -> Option<ast::GenericParamList> {
-        match self {
-            GenericParent::Fn(fn_) => fn_.generic_param_list(),
-            GenericParent::Impl(impl_) => impl_.generic_param_list(),
-            GenericParent::Trait(trait_) => trait_.generic_param_list(),
-        }
-    }
-
-    fn where_clause(&self) -> Option<ast::WhereClause> {
-        match self {
-            GenericParent::Fn(fn_) => fn_.where_clause(),
-            GenericParent::Impl(impl_) => impl_.where_clause(),
-            GenericParent::Trait(trait_) => trait_.where_clause(),
-        }
-    }
-}
-
-/// Search `parent`'s ancestors for items with potentially applicable generic parameters
-fn generic_parents(parent: &SyntaxNode) -> Vec<GenericParent> {
-    let mut list = Vec::new();
-    if let Some(parent_item) = parent.ancestors().find_map(ast::Item::cast) {
-        match parent_item {
-            ast::Item::Fn(ref fn_) => {
-                if let Some(parent_parent) = parent_item
-                    .syntax()
-                    .parent()
-                    .and_then(|it| it.parent())
-                    .and_then(ast::Item::cast)
-                {
-                    match parent_parent {
-                        ast::Item::Impl(impl_) => list.push(GenericParent::Impl(impl_)),
-                        ast::Item::Trait(trait_) => list.push(GenericParent::Trait(trait_)),
-                        _ => (),
-                    }
-                }
-                list.push(GenericParent::Fn(fn_.clone()));
-            }
-            _ => (),
-        }
-    }
-    list
-}
-
 /// checks if relevant var is used with `&mut` access inside body
 fn has_exclusive_usages(ctx: &AssistContext, usages: &LocalUsages, body: &FunctionBody) -> bool {
     usages
@@ -1448,154 +1362,37 @@ fn format_function(
     let const_kw = if fun.mods.is_const { "const " } else { "" };
     let async_kw = if fun.control_flow.is_async { "async " } else { "" };
     let unsafe_kw = if fun.control_flow.is_unsafe { "unsafe " } else { "" };
-    let (generic_params, where_clause) = make_generic_params_and_where_clause(ctx, fun);
     match ctx.config.snippet_cap {
         Some(_) => format_to!(
             fn_def,
-            "\n\n{}{}{}{}fn $0{}",
+            "\n\n{}{}{}{}fn $0{}{}",
             new_indent,
             const_kw,
             async_kw,
             unsafe_kw,
             fun.name,
+            params
         ),
         None => format_to!(
             fn_def,
-            "\n\n{}{}{}{}fn {}",
+            "\n\n{}{}{}{}fn {}{}",
             new_indent,
             const_kw,
             async_kw,
             unsafe_kw,
             fun.name,
+            params
         ),
     }
-
-    if let Some(generic_params) = generic_params {
-        format_to!(fn_def, "{}", generic_params);
-    }
-
-    format_to!(fn_def, "{}", params);
-
     if let Some(ret_ty) = ret_ty {
         format_to!(fn_def, " {}", ret_ty);
     }
-
-    if let Some(where_clause) = where_clause {
-        format_to!(fn_def, " {}", where_clause);
-    }
-
     format_to!(fn_def, " {}", body);
 
     fn_def
 }
 
-fn make_generic_params_and_where_clause(
-    ctx: &AssistContext,
-    fun: &Function,
-) -> (Option<ast::GenericParamList>, Option<ast::WhereClause>) {
-    let used_type_params = fun.type_params(ctx);
-
-    let generic_param_list = make_generic_param_list(ctx, fun, &used_type_params);
-    let where_clause = make_where_clause(ctx, fun, &used_type_params);
-
-    (generic_param_list, where_clause)
-}
-
-fn make_generic_param_list(
-    ctx: &AssistContext,
-    fun: &Function,
-    used_type_params: &[TypeParam],
-) -> Option<ast::GenericParamList> {
-    let mut generic_params = fun
-        .mods
-        .generic_param_lists
-        .iter()
-        .flat_map(|parent_params| {
-            parent_params
-                .generic_params()
-                .filter(|param| param_is_required(ctx, param, used_type_params))
-        })
-        .peekable();
-
-    if generic_params.peek().is_some() {
-        Some(make::generic_param_list(generic_params))
-    } else {
-        None
-    }
-}
-
-fn param_is_required(
-    ctx: &AssistContext,
-    param: &ast::GenericParam,
-    used_type_params: &[TypeParam],
-) -> bool {
-    match param {
-        ast::GenericParam::ConstParam(_) | ast::GenericParam::LifetimeParam(_) => false,
-        ast::GenericParam::TypeParam(type_param) => match &ctx.sema.to_def(type_param) {
-            Some(def) => used_type_params.contains(def),
-            _ => false,
-        },
-    }
-}
-
-fn make_where_clause(
-    ctx: &AssistContext,
-    fun: &Function,
-    used_type_params: &[TypeParam],
-) -> Option<ast::WhereClause> {
-    let mut predicates = fun
-        .mods
-        .where_clauses
-        .iter()
-        .flat_map(|parent_where_clause| {
-            parent_where_clause
-                .predicates()
-                .filter(|pred| pred_is_required(ctx, pred, used_type_params))
-        })
-        .peekable();
-
-    if predicates.peek().is_some() {
-        Some(make::where_clause(predicates))
-    } else {
-        None
-    }
-}
-
-fn pred_is_required(
-    ctx: &AssistContext,
-    pred: &ast::WherePred,
-    used_type_params: &[TypeParam],
-) -> bool {
-    match resolved_type_param(ctx, pred) {
-        Some(it) => used_type_params.contains(&it),
-        None => false,
-    }
-}
-
-fn resolved_type_param(ctx: &AssistContext, pred: &ast::WherePred) -> Option<TypeParam> {
-    let path = match pred.ty()? {
-        ast::Type::PathType(path_type) => path_type.path(),
-        _ => None,
-    }?;
-
-    match ctx.sema.resolve_path(&path)? {
-        PathResolution::TypeParam(type_param) => Some(type_param),
-        _ => None,
-    }
-}
-
 impl Function {
-    /// Collect all the `TypeParam`s used in the `body` and `params`.
-    fn type_params(&self, ctx: &AssistContext) -> Vec<TypeParam> {
-        let type_params_in_descendant_paths =
-            self.body.descendant_paths().filter_map(|it| match ctx.sema.resolve_path(&it) {
-                Some(PathResolution::TypeParam(type_param)) => Some(type_param),
-                _ => None,
-            });
-        let type_params_in_params = self.params.iter().filter_map(|p| p.ty.as_type_param(ctx.db()));
-        type_params_in_descendant_paths.chain(type_params_in_params).collect()
-    }
-
     fn make_param_list(&self, ctx: &AssistContext, module: hir::Module) -> ast::ParamList {
         let self_param = self.self_param.clone();
         let params = self.params.iter().map(|param| param.to_param(ctx, module));
@@ -5075,254 +4872,6 @@ fn parent(factor: i32) {
 fn $0fun_name(v: &[i32; 3], factor: i32) {
     v.iter().map(|it| it * factor);
 }
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_generics() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug>(i: T) {
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug>(i: T) {
-    fun_name(i);
-}
-
-fn $0fun_name<T: Debug>(i: T) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_generics_from_body() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Default>() -> T {
-    $0T::default()$0
-}
-"#,
-            r#"
-fn func<T: Default>() -> T {
-    fun_name()
-}
-
-fn $0fun_name<T: Default>() -> T {
-    T::default()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filter_unused_generics() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug, U: Copy>(i: T, u: U) {
-    bar(u);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug, U: Copy>(i: T, u: U) {
-    bar(u);
-    fun_name(i);
-}
-
-fn $0fun_name<T: Debug>(i: T) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn empty_generic_param_list() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T: Debug>(t: T, i: u32) {
-    bar(t);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T: Debug>(t: T, i: u32) {
-    bar(t);
-    fun_name(i);
-}
-
-fn $0fun_name(i: u32) {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn preserve_where_clause() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T>(i: T) where T: Debug {
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T>(i: T) where T: Debug {
-    fun_name(i);
-}
-
-fn $0fun_name<T>(i: T) where T: Debug {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filter_unused_where_clause() {
-        check_assist(
-            extract_function,
-            r#"
-fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
-    bar(u);
-    $0foo(i);$0
-}
-"#,
-            r#"
-fn func<T, U>(i: T, u: U) where T: Debug, U: Copy {
-    bar(u);
-    fun_name(i);
-}
-
-fn $0fun_name<T>(i: T) where T: Debug {
-    foo(i);
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn nested_generics() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T: Into<i32>>(T);
-impl <T: Into<i32> + Copy> Struct<T> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T: Into<i32>>(T);
-impl <T: Into<i32> + Copy> Struct<T> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filters_unused_nested_generics() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T: Into<i32>, U: Debug>(T, U);
-impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T: Into<i32>, U: Debug>(T, U);
-impl <T: Into<i32> + Copy, U: Debug> Struct<T, U> {
-    fn func<V: Into<i32>>(&self, v: V) -> i32 {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T: Into<i32> + Copy, V: Into<i32>>(t: T, v: V) -> i32 {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn nested_where_clauses() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T>(T) where T: Into<i32>;
-impl <T> Struct<T> where T: Into<i32> + Copy {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T>(T) where T: Into<i32>;
-impl <T> Struct<T> where T: Into<i32> + Copy {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
-    t.into() + v.into()
-}
-"#,
-        );
-    }
-
-    #[test]
-    fn filters_unused_nested_where_clauses() {
-        check_assist(
-            extract_function,
-            r#"
-struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
-impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        $0t.into() + v.into()$0
-    }
-}
-"#,
-            r#"
-struct Struct<T, U>(T, U) where T: Into<i32>, U: Debug;
-impl <T, U> Struct<T, U> where T: Into<i32> + Copy, U: Debug {
-    fn func<V>(&self, v: V) -> i32 where V: Into<i32> {
-        let t = self.0;
-        fun_name(t, v)
-    }
-}
-
-fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
-    t.into() + v.into()
-}
 "#,
         );
     }
diff --git a/crates/ide-assists/src/handlers/generate_function.rs b/crates/ide-assists/src/handlers/generate_function.rs
index 061a481344..c8650979e9 100644
--- a/crates/ide-assists/src/handlers/generate_function.rs
+++ b/crates/ide-assists/src/handlers/generate_function.rs
@@ -176,7 +176,7 @@ fn get_adt_source(
     adt: &hir::Adt,
     fn_name: &str,
 ) -> Option<(Option<ast::Impl>, FileId)> {
-    let range = adt.source(ctx.sema.db)?.syntax().original_file_range(ctx.sema.db);
+    let range = adt.source(ctx.sema.db)?.syntax().original_file_range_full(ctx.sema.db);
     let file = ctx.sema.parse(range.file_id);
     let adt_source =
         ctx.sema.find_node_at_offset_with_macros(file.syntax(), range.range.start())?;
diff --git a/crates/ide-assists/src/handlers/inline_call.rs b/crates/ide-assists/src/handlers/inline_call.rs
index c857adf876..ab614b0ace 100644
--- a/crates/ide-assists/src/handlers/inline_call.rs
+++ b/crates/ide-assists/src/handlers/inline_call.rs
@@ -198,7 +198,7 @@ pub(crate) fn inline_call(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     let fn_body = fn_source.value.body()?;
     let param_list = fn_source.value.param_list()?;
 
-    let FileRange { file_id, range } = fn_source.syntax().original_file_range(ctx.sema.db);
+    let FileRange { file_id, range } = fn_source.syntax().original_file_range_full(ctx.sema.db);
     if file_id == ctx.file_id() && range.contains(ctx.offset()) {
         cov_mark::hit!(inline_call_recursive);
         return None;
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index 7b90307988..b254e458eb 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -174,19 +174,13 @@ impl Completions {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) {
-        let is_private_editable = match ctx.def_is_visible(&resolution) {
-            Visible::Yes => false,
-            Visible::Editable => true,
-            Visible::No => return,
-        };
+        if ctx.is_scope_def_hidden(resolution) {
+            cov_mark::hit!(qualified_path_doc_hidden);
+            return;
+        }
         self.add(
-            render_path_resolution(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                path_ctx,
-                local_name,
-                resolution,
-            )
-            .build(),
+            render_path_resolution(RenderContext::new(ctx), path_ctx, local_name, resolution)
+                .build(),
         );
     }
 
@@ -197,19 +191,13 @@ impl Completions {
         local_name: hir::Name,
         resolution: hir::ScopeDef,
     ) {
-        let is_private_editable = match ctx.def_is_visible(&resolution) {
-            Visible::Yes => false,
-            Visible::Editable => true,
-            Visible::No => return,
-        };
+        if ctx.is_scope_def_hidden(resolution) {
+            cov_mark::hit!(qualified_path_doc_hidden);
+            return;
+        }
         self.add(
-            render_pattern_resolution(
-                RenderContext::new(ctx).private_editable(is_private_editable),
-                pattern_ctx,
-                local_name,
-                resolution,
-            )
-            .build(),
+            render_pattern_resolution(RenderContext::new(ctx), pattern_ctx, local_name, resolution)
+                .build(),
         );
     }
 
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index 94e2f489f5..cc6c17450b 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -5,11 +5,11 @@ use ide_db::FxHashMap;
 use syntax::{
     algo,
     ast::{self, HasModuleItem},
-    match_ast, AstNode, Direction, SyntaxKind, TextRange,
+    match_ast, AstNode, Direction, SyntaxKind, TextRange, TextSize,
 };
 
 use crate::{
-    context::{ParamKind, PatternContext},
+    context::{ParamContext, ParamKind, PatternContext},
     CompletionContext, CompletionItem, CompletionItemKind, Completions,
 };
 
@@ -24,7 +24,7 @@ pub(crate) fn complete_fn_param(
     ctx: &CompletionContext,
     pattern_ctx: &PatternContext,
 ) -> Option<()> {
-    let ((param_list, _, param_kind), impl_) = match pattern_ctx {
+    let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx {
         PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
         _ => return None,
     };
@@ -43,7 +43,7 @@ pub(crate) fn complete_fn_param(
         item.add_to(acc)
     };
 
-    match param_kind {
+    match kind {
         ParamKind::Function(function) => {
             fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
         }
@@ -105,7 +105,7 @@ fn fill_fn_params(
     }
     remove_duplicated(&mut file_params, param_list.params());
     let self_completion_items = ["self", "&self", "mut self", "&mut self"];
-    if should_add_self_completions(param_list, impl_) {
+    if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) {
         self_completion_items.into_iter().for_each(|self_item| add_new_item_to_acc(self_item));
     }
 
@@ -156,10 +156,18 @@ fn remove_duplicated(
     })
 }
 
-fn should_add_self_completions(param_list: &ast::ParamList, impl_: &Option<ast::Impl>) -> bool {
-    let no_params = param_list.params().next().is_none() && param_list.self_param().is_none();
-
-    impl_.is_some() && no_params
+fn should_add_self_completions(
+    cursor: TextSize,
+    param_list: &ast::ParamList,
+    impl_: &Option<ast::Impl>,
+) -> bool {
+    if impl_.is_none() || param_list.self_param().is_some() {
+        return false;
+    }
+    match param_list.params().next() {
+        Some(first) => first.pat().map_or(false, |pat| pat.syntax().text_range().contains(cursor)),
+        None => true,
+    }
 }
 
 fn comma_wrapper(ctx: &CompletionContext) -> Option<(impl Fn(&str) -> String, TextRange)> {
diff --git a/crates/ide-completion/src/completions/item_list/trait_impl.rs b/crates/ide-completion/src/completions/item_list/trait_impl.rs
index 67eb175460..49b8537029 100644
--- a/crates/ide-completion/src/completions/item_list/trait_impl.rs
+++ b/crates/ide-completion/src/completions/item_list/trait_impl.rs
@@ -438,6 +438,10 @@ impl Test for T {
             expect![[r#"
                 sp Self
                 st T
+                bn &mut self
+                bn &self
+                bn mut self
+                bn self
             "#]],
         );
 
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 8fd059f87c..e80381c36a 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -33,7 +33,6 @@ pub(crate) enum PatternRefutability {
     Irrefutable,
 }
 
-#[derive(Debug)]
 pub(crate) enum Visible {
     Yes,
     Editable,
@@ -199,7 +198,7 @@ pub(super) enum Qualified {
 #[derive(Debug, Clone, PartialEq, Eq)]
 pub(super) struct PatternContext {
     pub(super) refutability: PatternRefutability,
-    pub(super) param_ctx: Option<(ast::ParamList, ast::Param, ParamKind)>,
+    pub(super) param_ctx: Option<ParamContext>,
     pub(super) has_type_ascription: bool,
     pub(super) parent_pat: Option<ast::Pat>,
     pub(super) ref_token: Option<SyntaxToken>,
@@ -209,6 +208,13 @@ pub(super) struct PatternContext {
     pub(super) impl_: Option<ast::Impl>,
 }
 
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub(super) struct ParamContext {
+    pub(super) param_list: ast::ParamList,
+    pub(super) param: ast::Param,
+    pub(super) kind: ParamKind,
+}
+
 /// The state of the lifetime we are completing.
 #[derive(Debug)]
 pub(super) struct LifetimeContext {
@@ -356,11 +362,10 @@ pub(crate) struct CompletionContext<'a> {
 
     pub(super) locals: FxHashMap<Name, Local>,
 
-    /// The module depth of the current module of the cursor position.
     /// - crate-root
     ///  - mod foo
     ///   - mod bar
-    /// Here depth will be 2
+    /// Here depth will be 2: {[bar<->foo], [foo<->crate-root]}
     pub(super) depth_from_crate_root: usize,
 }
 
@@ -385,30 +390,6 @@ impl<'a> CompletionContext<'a> {
         FamousDefs(&self.sema, self.krate)
     }
 
-    /// Checks if an item is visible and not `doc(hidden)` at the completion site.
-    pub(crate) fn def_is_visible(&self, item: &ScopeDef) -> Visible {
-        match item {
-            ScopeDef::ModuleDef(def) => match def {
-                hir::ModuleDef::Module(it) => self.is_visible(it),
-                hir::ModuleDef::Function(it) => self.is_visible(it),
-                hir::ModuleDef::Adt(it) => self.is_visible(it),
-                hir::ModuleDef::Variant(it) => self.is_visible(it),
-                hir::ModuleDef::Const(it) => self.is_visible(it),
-                hir::ModuleDef::Static(it) => self.is_visible(it),
-                hir::ModuleDef::Trait(it) => self.is_visible(it),
-                hir::ModuleDef::TypeAlias(it) => self.is_visible(it),
-                hir::ModuleDef::Macro(it) => self.is_visible(it),
-                hir::ModuleDef::BuiltinType(_) => Visible::Yes,
-            },
-            ScopeDef::GenericParam(_)
-            | ScopeDef::ImplSelfType(_)
-            | ScopeDef::AdtSelfType(_)
-            | ScopeDef::Local(_)
-            | ScopeDef::Label(_)
-            | ScopeDef::Unknown => Visible::Yes,
-        }
-    }
-
     /// Checks if an item is visible and not `doc(hidden)` at the completion site.
     pub(crate) fn is_visible<I>(&self, item: &I) -> Visible
     where
@@ -419,6 +400,14 @@ impl<'a> CompletionContext<'a> {
         self.is_visible_impl(&vis, &attrs, item.krate(self.db))
     }
 
+    pub(crate) fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
+        if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
+            return self.is_doc_hidden(&attrs, krate);
+        }
+
+        false
+    }
+
     /// Check if an item is `#[doc(hidden)]`.
     pub(crate) fn is_item_hidden(&self, item: &hir::ItemInNs) -> bool {
         let attrs = item.attrs(self.db);
@@ -486,14 +475,6 @@ impl<'a> CompletionContext<'a> {
         self.scope.process_all_names(&mut |name, def| f(name, def));
     }
 
-    fn is_scope_def_hidden(&self, scope_def: ScopeDef) -> bool {
-        if let (Some(attrs), Some(krate)) = (scope_def.attrs(self.db), scope_def.krate(self.db)) {
-            return self.is_doc_hidden(&attrs, krate);
-        }
-
-        false
-    }
-
     fn is_visible_impl(
         &self,
         vis: &hir::Visibility,
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 7fc77aae91..fabbbe867e 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -13,8 +13,9 @@ use syntax::{
 use crate::context::{
     AttrCtx, CompletionAnalysis, CompletionContext, DotAccess, DotAccessKind, ExprCtx,
     ItemListKind, LifetimeContext, LifetimeKind, NameContext, NameKind, NameRefContext,
-    NameRefKind, ParamKind, PathCompletionCtx, PathKind, PatternContext, PatternRefutability,
-    Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation, COMPLETION_MARKER,
+    NameRefKind, ParamContext, ParamKind, PathCompletionCtx, PathKind, PatternContext,
+    PatternRefutability, Qualified, QualifierCtx, TypeAscriptionTarget, TypeLocation,
+    COMPLETION_MARKER,
 };
 
 impl<'a> CompletionContext<'a> {
@@ -990,7 +991,7 @@ fn pattern_context_for(
     original_file: &SyntaxNode,
     pat: ast::Pat,
 ) -> PatternContext {
-    let mut is_param = None;
+    let mut param_ctx = None;
     let (refutability, has_type_ascription) =
     pat
         .syntax()
@@ -1003,7 +1004,7 @@ fn pattern_context_for(
                     ast::LetStmt(let_) => return (PatternRefutability::Irrefutable, let_.ty().is_some()),
                     ast::Param(param) => {
                         let has_type_ascription = param.ty().is_some();
-                        is_param = (|| {
+                        param_ctx = (|| {
                             let fake_param_list = param.syntax().parent().and_then(ast::ParamList::cast)?;
                             let param_list = find_node_in_file_compensated(sema, original_file, &fake_param_list)?;
                             let param_list_owner = param_list.syntax().parent()?;
@@ -1014,7 +1015,9 @@ fn pattern_context_for(
                                     _ => return None,
                                 }
                             };
-                            Some((param_list, param, kind))
+                            Some(ParamContext {
+                                param_list, param, kind
+                            })
                         })();
                         return (PatternRefutability::Irrefutable, has_type_ascription)
                     },
@@ -1033,7 +1036,7 @@ fn pattern_context_for(
 
     PatternContext {
         refutability,
-        param_ctx: is_param,
+        param_ctx,
         has_type_ascription,
         parent_pat: pat.syntax().parent().and_then(ast::Pat::cast),
         mut_token,
diff --git a/crates/ide-completion/src/render/pattern.rs b/crates/ide-completion/src/render/pattern.rs
index d6779961c0..03db08a911 100644
--- a/crates/ide-completion/src/render/pattern.rs
+++ b/crates/ide-completion/src/render/pattern.rs
@@ -6,7 +6,7 @@ use itertools::Itertools;
 use syntax::SmolStr;
 
 use crate::{
-    context::{ParamKind, PatternContext},
+    context::{ParamContext, ParamKind, PatternContext},
     render::{
         variant::{format_literal_label, visible_fields},
         RenderContext,
@@ -102,7 +102,7 @@ fn render_pat(
     let needs_ascription = matches!(
         pattern_ctx,
         PatternContext {
-            param_ctx: Some((.., ParamKind::Function(_))),
+            param_ctx: Some(ParamContext { kind: ParamKind::Function(_), .. }),
             has_type_ascription: false,
             ..
         }
diff --git a/crates/ide-db/src/imports/insert_use.rs b/crates/ide-db/src/imports/insert_use.rs
index c14182279d..d1cd347819 100644
--- a/crates/ide-db/src/imports/insert_use.rs
+++ b/crates/ide-db/src/imports/insert_use.rs
@@ -396,19 +396,10 @@ fn insert_use_(
         }
     }
 
-    let l_curly = match scope {
-        ImportScope::File(_) => None,
-        // don't insert the imports before the item list/block expr's opening curly brace
-        ImportScope::Module(item_list) => item_list.l_curly_token(),
-        // don't insert the imports before the item list's opening curly brace
-        ImportScope::Block(block) => block.l_curly_token(),
-    };
     // there are no imports in this file at all
     // so put the import after all inner module attributes and possible license header comments
     if let Some(last_inner_element) = scope_syntax
         .children_with_tokens()
-        // skip the curly brace
-        .skip(l_curly.is_some() as usize)
         .take_while(|child| match child {
             NodeOrToken::Node(node) => is_inner_attribute(node.clone()),
             NodeOrToken::Token(token) => {
@@ -422,21 +413,30 @@ fn insert_use_(
         cov_mark::hit!(insert_empty_inner_attr);
         ted::insert(ted::Position::after(&last_inner_element), use_item.syntax());
         ted::insert(ted::Position::after(last_inner_element), make::tokens::single_newline());
-    } else {
-        match l_curly {
-            Some(b) => {
-                cov_mark::hit!(insert_empty_module);
-                ted::insert(ted::Position::after(&b), make::tokens::single_newline());
-                ted::insert(ted::Position::after(&b), use_item.syntax());
-            }
-            None => {
-                cov_mark::hit!(insert_empty_file);
-                ted::insert(
-                    ted::Position::first_child_of(scope_syntax),
-                    make::tokens::blank_line(),
-                );
-                ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
-            }
+        return;
+    }
+    let l_curly = match scope {
+        ImportScope::File(_) => {
+            cov_mark::hit!(insert_empty_file);
+            ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
+            ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
+            return;
+        }
+        // don't insert the imports before the item list/block expr's opening curly brace
+        ImportScope::Module(item_list) => item_list.l_curly_token(),
+        // don't insert the imports before the item list's opening curly brace
+        ImportScope::Block(block) => block.l_curly_token(),
+    };
+    match l_curly {
+        Some(b) => {
+            cov_mark::hit!(insert_empty_module);
+            ted::insert(ted::Position::after(&b), make::tokens::single_newline());
+            ted::insert(ted::Position::after(&b), use_item.syntax());
+        }
+        None => {
+            // This should never happens, broken module syntax node
+            ted::insert(ted::Position::first_child_of(scope_syntax), make::tokens::blank_line());
+            ted::insert(ted::Position::first_child_of(scope_syntax), use_item.syntax());
         }
     }
 }
diff --git a/crates/ide-db/src/search.rs b/crates/ide-db/src/search.rs
index 4a11fb73cd..e6bd46347d 100644
--- a/crates/ide-db/src/search.rs
+++ b/crates/ide-db/src/search.rs
@@ -239,14 +239,14 @@ impl Definition {
                 DefWithBody::Static(s) => s.source(db).map(|src| src.syntax().cloned()),
             };
             return match def {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
 
         if let Definition::SelfType(impl_) = self {
             return match impl_.source(db).map(|src| src.syntax().cloned()) {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
@@ -262,7 +262,7 @@ impl Definition {
                 hir::GenericDef::Const(it) => it.source(db).map(|src| src.syntax().cloned()),
             };
             return match def {
-                Some(def) => SearchScope::file_range(def.as_ref().original_file_range(db)),
+                Some(def) => SearchScope::file_range(def.as_ref().original_file_range_full(db)),
                 None => SearchScope::single_file(file_id),
             };
         }
diff --git a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
index 760f51f904..fde3901a73 100644
--- a/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
+++ b/crates/ide-diagnostics/src/handlers/unresolved_proc_macro.rs
@@ -1,5 +1,4 @@
 use hir::db::DefDatabase;
-use syntax::NodeOrToken;
 
 use crate::{Diagnostic, DiagnosticsContext, Severity};
 
@@ -19,16 +18,9 @@ pub(crate) fn unresolved_proc_macro(
     proc_attr_macros_enabled: bool,
 ) -> Diagnostic {
     // Use more accurate position if available.
-    let display_range = (|| {
-        let precise_location = d.precise_location?;
-        let root = ctx.sema.parse_or_expand(d.node.file_id)?;
-        match root.covering_element(precise_location) {
-            NodeOrToken::Node(it) => Some(ctx.sema.original_range(&it)),
-            NodeOrToken::Token(it) => d.node.with_value(it).original_file_range_opt(ctx.sema.db),
-        }
-    })()
-    .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()))
-    .range;
+    let display_range = d
+        .precise_location
+        .unwrap_or_else(|| ctx.sema.diagnostics_display_range(d.node.clone()).range);
 
     let config_enabled = match d.kind {
         hir::MacroKind::Attr => proc_macros_enabled && proc_attr_macros_enabled,
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs
index b91d54dd92..4c5bdfd967 100644
--- a/crates/ide/src/syntax_highlighting/highlight.rs
+++ b/crates/ide/src/syntax_highlighting/highlight.rs
@@ -328,8 +328,8 @@ fn highlight_def(sema: &Semantics<RootDatabase>, krate: hir::Crate, def: Definit
         Definition::Field(_) => Highlight::new(HlTag::Symbol(SymbolKind::Field)),
         Definition::Module(module) => {
             let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Module));
-            if module.is_crate_root(db) {
-                h |= HlMod::CrateRoot;
+            if module.parent(db).is_none() {
+                h |= HlMod::CrateRoot
             }
             h
         }


Test patch:
diff --git a/crates/ide-completion/src/tests/pattern.rs b/crates/ide-completion/src/tests/pattern.rs
index 1808868066..877b5f2164 100644
--- a/crates/ide-completion/src/tests/pattern.rs
+++ b/crates/ide-completion/src/tests/pattern.rs
@@ -630,3 +630,87 @@ fn f(v: u32) {
         "#]],
     );
 }
+
+#[test]
+fn in_method_param() {
+    check_empty(
+        r#"
+struct Ty(u8);
+
+impl Ty {
+    fn foo($0)
+}
+"#,
+        expect![[r#"
+            sp Self
+            st Ty
+            bn &mut self
+            bn &self
+            bn Self(…)   Self($1): Self$0
+            bn Ty(…)     Ty($1): Ty$0
+            bn mut self
+            bn self
+            kw mut
+            kw ref
+        "#]],
+    );
+    check_empty(
+        r#"
+struct Ty(u8);
+
+impl Ty {
+    fn foo(s$0)
+}
+"#,
+        expect![[r#"
+            sp Self
+            st Ty
+            bn &mut self
+            bn &self
+            bn Self(…)   Self($1): Self$0
+            bn Ty(…)     Ty($1): Ty$0
+            bn mut self
+            bn self
+            kw mut
+            kw ref
+        "#]],
+    );
+    check_empty(
+        r#"
+struct Ty(u8);
+
+impl Ty {
+    fn foo(s$0, foo: u8)
+}
+"#,
+        expect![[r#"
+            sp Self
+            st Ty
+            bn &mut self
+            bn &self
+            bn Self(…)   Self($1): Self$0
+            bn Ty(…)     Ty($1): Ty$0
+            bn mut self
+            bn self
+            kw mut
+            kw ref
+        "#]],
+    );
+    check_empty(
+        r#"
+struct Ty(u8);
+
+impl Ty {
+    fn foo(foo: u8, b$0)
+}
+"#,
+        expect![[r#"
+            sp Self
+            st Ty
+            bn Self(…) Self($1): Self$0
+            bn Ty(…)   Ty($1): Ty$0
+            kw mut
+            kw ref
+        "#]],
+    );
+}
diff --git a/crates/ide-completion/src/tests/special.rs b/crates/ide-completion/src/tests/special.rs
index ca779c2fc7..fc59f781dd 100644
--- a/crates/ide-completion/src/tests/special.rs
+++ b/crates/ide-completion/src/tests/special.rs
@@ -419,9 +419,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
         expect![[r#"
@@ -442,9 +442,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
         r#"
@@ -456,9 +456,9 @@ mod m {
     pub use super::p::WrongType as RightType;
 }
 mod p {
-    pub fn wrong_fn() {}
-    pub const WRONG_CONST: u32 = 1;
-    pub struct WrongType {};
+    fn wrong_fn() {}
+    const WRONG_CONST: u32 = 1;
+    struct WrongType {};
 }
 "#,
     );
@@ -627,6 +627,7 @@ fn main() {
 
 #[test]
 fn respects_doc_hidden2() {
+    cov_mark::check!(qualified_path_doc_hidden);
     check(
         r#"
 //- /lib.rs crate:lib deps:dep
diff --git a/crates/ide-db/src/imports/insert_use/tests.rs b/crates/ide-db/src/imports/insert_use/tests.rs
index 59673af320..70a7a15232 100644
--- a/crates/ide-db/src/imports/insert_use/tests.rs
+++ b/crates/ide-db/src/imports/insert_use/tests.rs
@@ -441,19 +441,6 @@ fn inserts_after_single_line_inner_comments() {
 
 use foo::bar::Baz;"#,
     );
-    check_none(
-        "foo::bar::Baz",
-        r"mod foo {
-    //! Single line inner comments do not allow any code before them.
-$0
-}",
-        r"mod foo {
-    //! Single line inner comments do not allow any code before them.
-
-    use foo::bar::Baz;
-
-}",
-    );
 }
 
 #[test]
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
index 1e4c06df7e..6704e5e8d5 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_crate_root.html
@@ -49,18 +49,18 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 <span class="keyword">use</span> <span class="module crate_root library">foo</span> <span class="keyword">as</span> <span class="module crate_root declaration library">foooo</span><span class="semicolon">;</span>
 
-<span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword crate_root public">crate</span><span class="parenthesis">)</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
+<span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword crate_root">crate</span><span class="parenthesis">)</span> <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span>
     <span class="keyword">let</span> <span class="variable declaration">baz</span> <span class="operator">=</span> <span class="module default_library library">iter</span><span class="operator">::</span><span class="function default_library library">repeat</span><span class="parenthesis">(</span><span class="numeric_literal">92</span><span class="parenthesis">)</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">mod</span> <span class="module declaration">bar</span> <span class="brace">{</span>
-    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
+    <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword crate_root">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">FORTY_TWO</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">42</span><span class="semicolon">;</span>
 
     <span class="keyword">mod</span> <span class="module declaration">baz</span> <span class="brace">{</span>
-        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="operator">::</span><span class="constant public">NINETY_TWO</span><span class="semicolon">;</span>
-        <span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="operator">::</span><span class="module crate_root library">foooo</span><span class="operator">::</span><span class="struct library">Point</span><span class="semicolon">;</span>
+        <span class="keyword">use</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root">super</span><span class="operator">::</span><span class="constant public">NINETY_TWO</span><span class="semicolon">;</span>
+        <span class="keyword">use</span> <span class="keyword crate_root">crate</span><span class="operator">::</span><span class="module crate_root library">foooo</span><span class="operator">::</span><span class="struct library">Point</span><span class="semicolon">;</span>
 
-        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root public">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
+        <span class="keyword">pub</span><span class="parenthesis">(</span><span class="keyword control">in</span> <span class="keyword">super</span><span class="operator">::</span><span class="keyword crate_root">super</span><span class="parenthesis">)</span> <span class="keyword">const</span> <span class="constant declaration">TWENTY_NINE</span><span class="colon">:</span> <span class="builtin_type">u8</span> <span class="operator">=</span> <span class="numeric_literal">29</span><span class="semicolon">;</span>
     <span class="brace">}</span>
 <span class="brace">}</span>
 </code></pre>
\ No newline at end of file
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
index a97802cbbd..7bb7ddd280 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_general.html
@@ -84,7 +84,7 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
     <span class="brace">}</span>
 <span class="brace">}</span>
 
-<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="operator">::</span><span class="struct">FooCopy</span><span class="operator">::</span><span class="brace">{</span><span class="self_keyword">self</span> <span class="keyword">as</span> <span class="struct declaration">BarCopy</span><span class="brace">}</span><span class="semicolon">;</span>
 
 <span class="attribute_bracket attribute">#</span><span class="attribute_bracket attribute">[</span><span class="attribute attribute default_library library">derive</span><span class="parenthesis attribute">(</span><span class="derive attribute default_library library">Copy</span><span class="parenthesis attribute">)</span><span class="attribute_bracket attribute">]</span>
 <span class="keyword">struct</span> <span class="struct declaration">FooCopy</span> <span class="brace">{</span>
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
index 66f9ede962..ba62b68e9d 100644
--- a/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
+++ b/crates/ide/src/syntax_highlighting/test_data/highlight_keywords.html
@@ -42,12 +42,12 @@ pre                 { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd
 
 .unresolved_reference { color: #FC5555; text-decoration: wavy underline; }
 </style>
-<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
+<pre><code><span class="keyword">extern</span> <span class="keyword">crate</span> <span class="self_keyword crate_root">self</span><span class="semicolon">;</span>
 
-<span class="keyword">use</span> <span class="keyword crate_root public">crate</span><span class="semicolon">;</span>
-<span class="keyword">use</span> <span class="self_keyword crate_root public">self</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="keyword crate_root">crate</span><span class="semicolon">;</span>
+<span class="keyword">use</span> <span class="self_keyword crate_root">self</span><span class="semicolon">;</span>
 <span class="keyword">mod</span> <span class="module declaration">__</span> <span class="brace">{</span>
-    <span class="keyword">use</span> <span class="keyword crate_root public">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
+    <span class="keyword">use</span> <span class="keyword crate_root">super</span><span class="operator">::</span><span class="punctuation">*</span><span class="semicolon">;</span>
 <span class="brace">}</span>
 
 <span class="keyword">macro_rules</span><span class="macro_bang">!</span> <span class="macro declaration">void</span> <span class="brace">{</span>