Repository: rust-analyzer/rust-analyzer (rust)

Issue:
Type inference not working when default type parameter is used in trait
Example:

```rust
struct A;

trait Op<RHS=Self> {
    type Output;

    fn do_op(self, rhs: RHS) -> Self::Output;
}

impl Op for A {
    type Output = bool;

    fn do_op(self, rhs: Self) -> Self::Output {
        true
    }
}

impl std::ops::Sub for A {
    type Output = bool;
    fn sub(self, rhs: Self) -> Self::Output {
        true
    }
}

fn test() {
    let x = A;
    let y = A;
    let r = x.do_op(y);

    let x = A;
    let y = A;
    let r = x - y;
}

```

In both cases the type for variable r is not inferred correctly. It resolves to e.g. *Op::Output<A, A>*.

As soon as the impl block specifies the RHS type parameter, everything works just fine:


```rust
struct A;

trait Op<RHS=Self> {
    type Output;

    fn do_op(self, rhs: RHS) -> Self::Output;
}

impl Op<Self> for A {
    type Output = bool;

    fn do_op(self, rhs: Self) -> Self::Output {
        true
    }
}

impl std::ops::Sub<Self> for A {
    type Output = bool;
    fn sub(self, rhs: Self) -> Self::Output {
        true
    }
}

fn test() {
    let x = A;
    let y = A;
    let r = x.do_op(y);

    let x = A;
    let y = A;
    let r = x - y;
}

```

Both cases infer r to be of type bool.

Edit:

Type inference for overloaded operators in *std::ops* does not actually work in RA. I have a branch for that, which is currently pretty useless. If we can fix the default type parameter problem in traits, it will work just fine (I guess).

Pull request:
Correctly lower TraitRefs with default params
Fixes #5685

Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 19ee689cb4..9f013c2757 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1324,9 +1324,9 @@ checksum = "b5eb417147ba9860a96cfe72a0b93bf88fee1744b5636ec99ab20c1aa9376581"
 
 [[package]]
 name = "rowan"
-version = "0.13.0-pre.3"
+version = "0.13.0-pre.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "77d315d6f2e33f294412faa47f41b56bdb3fce72c999d384b5e78c8d21551b13"
+checksum = "8f300be7fa17c3fa563d2bc6ab5b1a8d5163162f9111599eda4f86a563714724"
 dependencies = [
  "countme",
  "hashbrown",
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 9e8e4e9ec6..0d3a0b54fa 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -322,23 +322,6 @@ impl DefMap {
         (res.resolved_def, res.segment_index)
     }
 
-    pub(crate) fn resolve_path_locally(
-        &self,
-        db: &dyn DefDatabase,
-        original_module: LocalModuleId,
-        path: &ModPath,
-        shadow: BuiltinShadowMode,
-    ) -> (PerNs, Option<usize>) {
-        let res = self.resolve_path_fp_with_macro_single(
-            db,
-            ResolveMode::Other,
-            original_module,
-            path,
-            shadow,
-        );
-        (res.resolved_def, res.segment_index)
-    }
-
     /// Ascends the `DefMap` hierarchy and calls `f` with every `DefMap` and containing module.
     ///
     /// If `f` returns `Some(val)`, iteration is stopped and `Some(val)` is returned. If `f` returns
diff --git a/crates/hir_def/src/nameres/path_resolution.rs b/crates/hir_def/src/nameres/path_resolution.rs
index 60471937c0..db459b1ed8 100644
--- a/crates/hir_def/src/nameres/path_resolution.rs
+++ b/crates/hir_def/src/nameres/path_resolution.rs
@@ -156,7 +156,7 @@ impl DefMap {
         }
     }
 
-    pub(super) fn resolve_path_fp_with_macro_single(
+    fn resolve_path_fp_with_macro_single(
         &self,
         db: &dyn DefDatabase,
         mode: ResolveMode,
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index a73585ee79..04ea9c5d7f 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -548,7 +548,7 @@ impl ModuleItemMap {
         path: &ModPath,
     ) -> Option<ResolveValueResult> {
         let (module_def, idx) =
-            self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
+            self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
         match idx {
             None => {
                 let value = to_value_ns(module_def)?;
@@ -578,7 +578,7 @@ impl ModuleItemMap {
         path: &ModPath,
     ) -> Option<(TypeNs, Option<usize>)> {
         let (module_def, idx) =
-            self.def_map.resolve_path_locally(db, self.module_id, &path, BuiltinShadowMode::Other);
+            self.def_map.resolve_path(db, self.module_id, &path, BuiltinShadowMode::Other);
         let res = to_type_ns(module_def)?;
         Some((res, idx))
     }
@@ -627,18 +627,8 @@ pub trait HasResolver: Copy {
 
 impl HasResolver for ModuleId {
     fn resolver(self, db: &dyn DefDatabase) -> Resolver {
-        let mut def_map = self.def_map(db);
-        let mut modules = Vec::new();
-        modules.push((def_map.clone(), self.local_id));
-        while let Some(parent) = def_map.parent() {
-            def_map = parent.def_map(db);
-            modules.push((def_map.clone(), parent.local_id));
-        }
-        let mut resolver = Resolver::default();
-        for (def_map, module) in modules.into_iter().rev() {
-            resolver = resolver.push_module_scope(def_map, module);
-        }
-        resolver
+        let def_map = self.def_map(db);
+        Resolver::default().push_module_scope(def_map, self.local_id)
     }
 }
 
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index f60cec649b..3153b5b74f 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -521,7 +521,7 @@ impl<'a> TyLoweringContext<'a> {
             TyDefId::AdtId(it) => Some(it.into()),
             TyDefId::TypeAliasId(it) => Some(it.into()),
         };
-        let substs = self.substs_from_path_segment(segment, generic_def, infer_args);
+        let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None);
         self.db.ty(typeable).subst(&substs)
     }
 
@@ -558,7 +558,7 @@ impl<'a> TyLoweringContext<'a> {
                 (segment, Some(var.parent.into()))
             }
         };
-        self.substs_from_path_segment(segment, generic_def, infer_args)
+        self.substs_from_path_segment(segment, generic_def, infer_args, None)
     }
 
     fn substs_from_path_segment(
@@ -566,6 +566,7 @@ impl<'a> TyLoweringContext<'a> {
         segment: PathSegment<'_>,
         def_generic: Option<GenericDefId>,
         infer_args: bool,
+        explicit_self_ty: Option<Ty>,
     ) -> Substitution {
         let mut substs = Vec::new();
         let def_generics = def_generic.map(|def| generics(self.db.upcast(), def));
@@ -576,11 +577,19 @@ impl<'a> TyLoweringContext<'a> {
 
         substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(parent_params));
 
+        let fill_self_params = || {
+            substs.extend(
+                explicit_self_ty
+                    .into_iter()
+                    .chain(iter::repeat(TyKind::Unknown.intern(&Interner)))
+                    .take(self_params),
+            )
+        };
         let mut had_explicit_type_args = false;
 
         if let Some(generic_args) = &segment.args_and_bindings {
             if !generic_args.has_self_type {
-                substs.extend(iter::repeat(TyKind::Unknown.intern(&Interner)).take(self_params));
+                fill_self_params();
             }
             let expected_num =
                 if generic_args.has_self_type { self_params + type_params } else { type_params };
@@ -602,6 +611,8 @@ impl<'a> TyLoweringContext<'a> {
                     GenericArg::Lifetime(_) => {}
                 }
             }
+        } else {
+            fill_self_params();
         }
 
         // handle defaults. In expression or pattern path segments without
@@ -650,10 +661,7 @@ impl<'a> TyLoweringContext<'a> {
         segment: PathSegment<'_>,
         explicit_self_ty: Option<Ty>,
     ) -> TraitRef {
-        let mut substs = self.trait_ref_substs_from_path(segment, resolved);
-        if let Some(self_ty) = explicit_self_ty {
-            substs.0[0] = self_ty;
-        }
+        let substs = self.trait_ref_substs_from_path(segment, resolved, explicit_self_ty);
         TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs }
     }
 
@@ -673,8 +681,9 @@ impl<'a> TyLoweringContext<'a> {
         &self,
         segment: PathSegment<'_>,
         resolved: TraitId,
+        explicit_self_ty: Option<Ty>,
     ) -> Substitution {
-        self.substs_from_path_segment(segment, Some(resolved.into()), false)
+        self.substs_from_path_segment(segment, Some(resolved.into()), false, explicit_self_ty)
     }
 
     pub(crate) fn lower_where_predicate(
diff --git a/crates/ide_assists/src/handlers/merge_imports.rs b/crates/ide_assists/src/handlers/merge_imports.rs
index cfc472a325..7bd7e1e369 100644
--- a/crates/ide_assists/src/handlers/merge_imports.rs
+++ b/crates/ide_assists/src/handlers/merge_imports.rs
@@ -1,5 +1,8 @@
 use ide_db::helpers::insert_use::{try_merge_imports, try_merge_trees, MergeBehavior};
-use syntax::{algo::neighbor, ast, ted, AstNode};
+use syntax::{
+    algo::{neighbor, SyntaxRewriter},
+    ast, AstNode,
+};
 
 use crate::{
     assist_context::{AssistContext, Assists},
@@ -21,29 +24,33 @@ use crate::{
 // ```
 pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
     let tree: ast::UseTree = ctx.find_node_at_offset()?;
-    let original_parent = tree.syntax().ancestors().last()?;
-
-    let tree = tree.clone_for_update();
-    let new_parent = tree.syntax().ancestors().last()?;
-
+    let mut rewriter = SyntaxRewriter::default();
     let mut offset = ctx.offset();
 
-    let mut imports = None;
-    let mut uses = None;
     if let Some(use_item) = tree.syntax().parent().and_then(ast::Use::cast) {
-        let (merged, to_remove) =
+        let (merged, to_delete) =
             next_prev().filter_map(|dir| neighbor(&use_item, dir)).find_map(|use_item2| {
                 try_merge_imports(&use_item, &use_item2, MergeBehavior::Full).zip(Some(use_item2))
             })?;
 
-        imports = Some((use_item, merged, to_remove));
+        rewriter.replace_ast(&use_item, &merged);
+        rewriter += to_delete.remove();
+
+        if to_delete.syntax().text_range().end() < offset {
+            offset -= to_delete.syntax().text_range().len();
+        }
     } else {
-        let (merged, to_remove) =
+        let (merged, to_delete) =
             next_prev().filter_map(|dir| neighbor(&tree, dir)).find_map(|use_tree| {
                 try_merge_trees(&tree, &use_tree, MergeBehavior::Full).zip(Some(use_tree))
             })?;
 
-        uses = Some((tree.clone(), merged, to_remove))
+        rewriter.replace_ast(&tree, &merged);
+        rewriter += to_delete.remove();
+
+        if to_delete.syntax().text_range().end() < offset {
+            offset -= to_delete.syntax().text_range().len();
+        }
     };
 
     let target = tree.syntax().text_range();
@@ -52,23 +59,7 @@ pub(crate) fn merge_imports(acc: &mut Assists, ctx: &AssistContext) -> Option<()
         "Merge imports",
         target,
         |builder| {
-            if let Some((to_replace, replacement, to_remove)) = imports {
-                if to_remove.syntax().text_range().end() < offset {
-                    offset -= to_remove.syntax().text_range().len();
-                }
-                ted::replace(to_replace.syntax().clone(), replacement.syntax().clone());
-                to_remove.remove();
-            }
-
-            if let Some((to_replace, replacement, to_remove)) = uses {
-                if to_remove.syntax().text_range().end() < offset {
-                    offset -= to_remove.syntax().text_range().len();
-                }
-                ted::replace(to_replace.syntax().clone(), replacement.syntax().clone());
-                to_remove.remove()
-            }
-
-            builder.replace(original_parent.text_range(), new_parent.to_string())
+            builder.rewrite(rewriter);
         },
     )
 }
diff --git a/crates/ide_assists/src/handlers/unmerge_use.rs b/crates/ide_assists/src/handlers/unmerge_use.rs
index 8d271e056f..616af7c2e6 100644
--- a/crates/ide_assists/src/handlers/unmerge_use.rs
+++ b/crates/ide_assists/src/handlers/unmerge_use.rs
@@ -1,6 +1,6 @@
 use syntax::{
-    ast::{self, VisibilityOwner},
-    ted::{self, Position},
+    algo::SyntaxRewriter,
+    ast::{self, edit::AstNodeEdit, VisibilityOwner},
     AstNode, SyntaxKind,
 };
 
@@ -22,7 +22,7 @@ use crate::{
 // use std::fmt::Display;
 // ```
 pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
-    let tree: ast::UseTree = ctx.find_node_at_offset::<ast::UseTree>()?.clone_for_update();
+    let tree: ast::UseTree = ctx.find_node_at_offset()?;
 
     let tree_list = tree.syntax().parent().and_then(ast::UseTreeList::cast)?;
     if tree_list.use_trees().count() < 2 {
@@ -33,9 +33,6 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
     let use_: ast::Use = tree_list.syntax().ancestors().find_map(ast::Use::cast)?;
     let path = resolve_full_path(&tree)?;
 
-    let old_parent_range = use_.syntax().parent()?.text_range();
-    let new_parent = use_.syntax().parent()?;
-
     let target = tree.syntax().text_range();
     acc.add(
         AssistId("unmerge_use", AssistKind::RefactorRewrite),
@@ -50,13 +47,20 @@ pub(crate) fn unmerge_use(acc: &mut Assists, ctx: &AssistContext) -> Option<()>
                     tree.rename(),
                     tree.star_token().is_some(),
                 ),
-            )
-            .clone_for_update();
-
-            tree.remove();
-            ted::insert(Position::after(use_.syntax()), new_use.syntax());
-
-            builder.replace(old_parent_range, new_parent.to_string());
+            );
+
+            let mut rewriter = SyntaxRewriter::default();
+            rewriter += tree.remove();
+            rewriter.insert_after(use_.syntax(), &ast::make::tokens::single_newline());
+            if let ident_level @ 1..=usize::MAX = use_.indent_level().0 as usize {
+                rewriter.insert_after(
+                    use_.syntax(),
+                    &ast::make::tokens::whitespace(&" ".repeat(4 * ident_level)),
+                );
+            }
+            rewriter.insert_after(use_.syntax(), new_use.syntax());
+
+            builder.rewrite(rewriter);
         },
     )
 }
diff --git a/crates/ide_db/src/helpers/insert_use.rs b/crates/ide_db/src/helpers/insert_use.rs
index 20c195f825..37acf95f0f 100644
--- a/crates/ide_db/src/helpers/insert_use.rs
+++ b/crates/ide_db/src/helpers/insert_use.rs
@@ -213,7 +213,7 @@ pub fn try_merge_imports(
     let lhs_tree = lhs.use_tree()?;
     let rhs_tree = rhs.use_tree()?;
     let merged = try_merge_trees(&lhs_tree, &rhs_tree, merge_behavior)?;
-    Some(lhs.with_use_tree(merged).clone_for_update())
+    Some(lhs.with_use_tree(merged))
 }
 
 pub fn try_merge_trees(
@@ -234,7 +234,7 @@ pub fn try_merge_trees(
     } else {
         (lhs.split_prefix(&lhs_prefix), rhs.split_prefix(&rhs_prefix))
     };
-    recursive_merge(&lhs, &rhs, merge).map(|it| it.clone_for_update())
+    recursive_merge(&lhs, &rhs, merge)
 }
 
 /// Recursively "zips" together lhs and rhs.
diff --git a/crates/syntax/Cargo.toml b/crates/syntax/Cargo.toml
index 0c3fec3c7f..74cafaa8d2 100644
--- a/crates/syntax/Cargo.toml
+++ b/crates/syntax/Cargo.toml
@@ -13,7 +13,7 @@ doctest = false
 [dependencies]
 cov-mark = { version = "1.1", features = ["thread-local"] }
 itertools = "0.10.0"
-rowan = "0.13.0-pre.3"
+rowan = "0.13.0-pre.2"
 rustc_lexer = { version = "710.0.0", package = "rustc-ap-rustc_lexer" }
 rustc-hash = "1.1.0"
 arrayvec = "0.5.1"
diff --git a/crates/syntax/src/ast/edit.rs b/crates/syntax/src/ast/edit.rs
index 18820786a5..347862b8a4 100644
--- a/crates/syntax/src/ast/edit.rs
+++ b/crates/syntax/src/ast/edit.rs
@@ -9,7 +9,7 @@ use std::{
 use arrayvec::ArrayVec;
 
 use crate::{
-    algo::{self, SyntaxRewriter},
+    algo::{self, neighbor, SyntaxRewriter},
     ast::{
         self,
         make::{self, tokens},
@@ -322,6 +322,27 @@ impl ast::Use {
         }
         self.clone()
     }
+
+    pub fn remove(&self) -> SyntaxRewriter<'static> {
+        let mut res = SyntaxRewriter::default();
+        res.delete(self.syntax());
+        let next_ws = self
+            .syntax()
+            .next_sibling_or_token()
+            .and_then(|it| it.into_token())
+            .and_then(ast::Whitespace::cast);
+        if let Some(next_ws) = next_ws {
+            let ws_text = next_ws.syntax().text();
+            if let Some(rest) = ws_text.strip_prefix('\n') {
+                if rest.is_empty() {
+                    res.delete(next_ws.syntax())
+                } else {
+                    res.replace(next_ws.syntax(), &make::tokens::whitespace(rest));
+                }
+            }
+        }
+        res
+    }
 }
 
 impl ast::UseTree {
@@ -375,6 +396,22 @@ impl ast::UseTree {
             Some(res)
         }
     }
+
+    pub fn remove(&self) -> SyntaxRewriter<'static> {
+        let mut res = SyntaxRewriter::default();
+        res.delete(self.syntax());
+        for &dir in [Direction::Next, Direction::Prev].iter() {
+            if let Some(nb) = neighbor(self, dir) {
+                self.syntax()
+                    .siblings_with_tokens(dir)
+                    .skip(1)
+                    .take_while(|it| it.as_node() != Some(nb.syntax()))
+                    .for_each(|el| res.delete(&el));
+                return res;
+            }
+        }
+        res
+    }
 }
 
 impl ast::MatchArmList {
@@ -555,13 +592,6 @@ impl ops::Add<u8> for IndentLevel {
 }
 
 impl IndentLevel {
-    pub fn from_element(element: &SyntaxElement) -> IndentLevel {
-        match element {
-            rowan::NodeOrToken::Node(it) => IndentLevel::from_node(it),
-            rowan::NodeOrToken::Token(it) => IndentLevel::from_token(it),
-        }
-    }
-
     pub fn from_node(node: &SyntaxNode) -> IndentLevel {
         match node.first_token() {
             Some(it) => Self::from_token(&it),
diff --git a/crates/syntax/src/ast/edit_in_place.rs b/crates/syntax/src/ast/edit_in_place.rs
index 529bd0eb14..b1eed0a2cc 100644
--- a/crates/syntax/src/ast/edit_in_place.rs
+++ b/crates/syntax/src/ast/edit_in_place.rs
@@ -2,13 +2,13 @@
 
 use std::iter::empty;
 
+use ast::{edit::AstNodeEdit, make, GenericParamsOwner, WhereClause};
 use parser::T;
 
 use crate::{
-    algo::neighbor,
-    ast::{self, edit::AstNodeEdit, make, GenericParamsOwner, WhereClause},
+    ast,
     ted::{self, Position},
-    AstNode, AstToken, Direction,
+    AstNode, Direction,
 };
 
 use super::NameOwner;
@@ -126,41 +126,3 @@ impl ast::TypeBoundList {
         }
     }
 }
-
-impl ast::UseTree {
-    pub fn remove(&self) {
-        for &dir in [Direction::Next, Direction::Prev].iter() {
-            if let Some(next_use_tree) = neighbor(self, dir) {
-                let separators = self
-                    .syntax()
-                    .siblings_with_tokens(dir)
-                    .skip(1)
-                    .take_while(|it| it.as_node() != Some(next_use_tree.syntax()));
-                ted::remove_all_iter(separators);
-                break;
-            }
-        }
-        ted::remove(self.syntax())
-    }
-}
-
-impl ast::Use {
-    pub fn remove(&self) {
-        let next_ws = self
-            .syntax()
-            .next_sibling_or_token()
-            .and_then(|it| it.into_token())
-            .and_then(ast::Whitespace::cast);
-        if let Some(next_ws) = next_ws {
-            let ws_text = next_ws.syntax().text();
-            if let Some(rest) = ws_text.strip_prefix('\n') {
-                if rest.is_empty() {
-                    ted::remove(next_ws.syntax())
-                } else {
-                    ted::replace(next_ws.syntax(), make::tokens::whitespace(rest))
-                }
-            }
-        }
-        ted::remove(self.syntax())
-    }
-}
diff --git a/crates/syntax/src/ast/make.rs b/crates/syntax/src/ast/make.rs
index c08f2c14f5..7049affd95 100644
--- a/crates/syntax/src/ast/make.rs
+++ b/crates/syntax/src/ast/make.rs
@@ -560,7 +560,7 @@ pub mod tokens {
     pub fn whitespace(text: &str) -> SyntaxToken {
         assert!(text.trim().is_empty());
         let sf = SourceFile::parse(text).ok().unwrap();
-        sf.syntax().clone_for_update().first_child_or_token().unwrap().into_token().unwrap()
+        sf.syntax().first_child_or_token().unwrap().into_token().unwrap()
     }
 
     pub fn doc_comment(text: &str) -> SyntaxToken {
diff --git a/crates/syntax/src/ted.rs b/crates/syntax/src/ted.rs
index 177d4ff67a..be2b846b15 100644
--- a/crates/syntax/src/ted.rs
+++ b/crates/syntax/src/ted.rs
@@ -2,14 +2,11 @@
 //!
 //! The `_raw`-suffixed functions insert elements as is, unsuffixed versions fix
 //! up elements around the edges.
-use std::{mem, ops::RangeInclusive};
+use std::ops::RangeInclusive;
 
 use parser::T;
 
-use crate::{
-    ast::{edit::IndentLevel, make},
-    SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken,
-};
+use crate::{ast::make, SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken};
 
 /// Utility trait to allow calling `ted` functions with references or owned
 /// nodes. Do not use outside of this module.
@@ -104,25 +101,12 @@ pub fn insert_all_raw(position: Position, elements: Vec<SyntaxElement>) {
 }
 
 pub fn remove(elem: impl Element) {
-    elem.syntax_element().detach()
+    let elem = elem.syntax_element();
+    remove_all(elem.clone()..=elem)
 }
 pub fn remove_all(range: RangeInclusive<SyntaxElement>) {
     replace_all(range, Vec::new())
 }
-pub fn remove_all_iter(range: impl IntoIterator<Item = SyntaxElement>) {
-    let mut it = range.into_iter();
-    if let Some(mut first) = it.next() {
-        match it.last() {
-            Some(mut last) => {
-                if first.index() > last.index() {
-                    mem::swap(&mut first, &mut last)
-                }
-                remove_all(first..=last)
-            }
-            None => remove(first),
-        }
-    }
-}
 
 pub fn replace(old: impl Element, new: impl Element) {
     let old = old.syntax_element();
@@ -165,9 +149,5 @@ fn ws_between(left: &SyntaxElement, right: &SyntaxElement) -> Option<SyntaxToken
     if right.kind() == T![;] || right.kind() == T![,] {
         return None;
     }
-    if right.kind() == SyntaxKind::USE {
-        let indent = IndentLevel::from_element(left);
-        return Some(make::tokens::whitespace(&format!("\n{}", indent)));
-    }
     Some(make::tokens::single_space())
 }


Test patch:
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index b69f860502..69314e245b 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -961,16 +961,3 @@ fn issue_6852() {
         "#]],
     );
 }
-
-#[test]
-fn param_overrides_fn() {
-    check_types(
-        r#"
-        fn example(example: i32) {
-            fn f() {}
-            example;
-          //^^^^^^^ i32
-        }
-        "#,
-    )
-}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 37cd04c6f7..45a1958e30 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -3324,3 +3324,49 @@ fn f() {
         "#]],
     )
 }
+
+#[test]
+fn infer_default_trait_type_parameter() {
+    check_infer(
+        r#"
+struct A;
+
+trait Op<RHS=Self> {
+    type Output;
+
+    fn do_op(self, rhs: RHS) -> Self::Output;
+}
+
+impl Op for A {
+    type Output = bool;
+
+    fn do_op(self, rhs: Self) -> Self::Output {
+        true
+    }
+}
+
+fn test() {
+    let x = A;
+    let y = A;
+    let r = x.do_op(y);
+}
+        "#,
+        expect![[r#"
+            63..67 'self': Self
+            69..72 'rhs': RHS
+            153..157 'self': A
+            159..162 'rhs': A
+            186..206 '{     ...     }': bool
+            196..200 'true': bool
+            220..277 '{     ...(y); }': ()
+            230..231 'x': A
+            234..235 'A': A
+            245..246 'y': A
+            249..250 'A': A
+            260..261 'r': bool
+            264..265 'x': A
+            264..274 'x.do_op(y)': bool
+            272..273 'y': A
+        "#]],
+    )
+}