Add self param completions for trait assoc fn

Example
---
```rust
trait A {
    fn foo(file_id: usize) {}
    fn new($0) {}
}
```

**Before this PR**:

```text
bn file_id: usize
kw mut
kw ref
```

**After this PR**:

```text
bn &mut self
bn &self
bn file_id: usize
bn mut self
bn self
kw mut
kw ref
```
diff --git a/crates/ide-completion/src/completions.rs b/crates/ide-completion/src/completions.rs
index eb2bb31..b822f53 100644
--- a/crates/ide-completion/src/completions.rs
+++ b/crates/ide-completion/src/completions.rs
@@ -630,7 +630,7 @@
     acc: &mut Completions,
     ctx: &CompletionContext<'_>,
     enum_: hir::Enum,
-    impl_: &Option<ast::Impl>,
+    impl_: Option<&ast::Impl>,
     cb: impl Fn(&mut Completions, &CompletionContext<'_>, hir::Variant, hir::ModPath),
 ) {
     let mut process_variant = |variant: Variant| {
@@ -644,7 +644,7 @@
 
     let variants = enum_.variants(ctx.db);
 
-    if let Some(impl_) = impl_.as_ref().and_then(|impl_| ctx.sema.to_def(impl_))
+    if let Some(impl_) = impl_.and_then(|impl_| ctx.sema.to_def(impl_))
         && impl_.self_ty(ctx.db).as_adt() == Some(hir::Adt::Enum(enum_))
     {
         variants.iter().for_each(|variant| process_variant(*variant));
diff --git a/crates/ide-completion/src/completions/expr.rs b/crates/ide-completion/src/completions/expr.rs
index 080875e..4c79357 100644
--- a/crates/ide-completion/src/completions/expr.rs
+++ b/crates/ide-completion/src/completions/expr.rs
@@ -297,7 +297,7 @@
                             acc,
                             ctx,
                             e,
-                            impl_,
+                            impl_.as_ref(),
                             |acc, ctx, variant, path| {
                                 acc.add_qualified_enum_variant(ctx, path_ctx, variant, path)
                             },
diff --git a/crates/ide-completion/src/completions/fn_param.rs b/crates/ide-completion/src/completions/fn_param.rs
index fb78386..34d25c9 100644
--- a/crates/ide-completion/src/completions/fn_param.rs
+++ b/crates/ide-completion/src/completions/fn_param.rs
@@ -2,6 +2,7 @@
 
 use hir::HirDisplay;
 use ide_db::FxHashMap;
+use itertools::Either;
 use syntax::{
     AstNode, Direction, SyntaxKind, TextRange, TextSize, algo,
     ast::{self, HasModuleItem},
@@ -24,8 +25,8 @@
     ctx: &CompletionContext<'_>,
     pattern_ctx: &PatternContext,
 ) -> Option<()> {
-    let (ParamContext { param_list, kind, .. }, impl_) = match pattern_ctx {
-        PatternContext { param_ctx: Some(kind), impl_, .. } => (kind, impl_),
+    let (ParamContext { param_list, kind, .. }, impl_or_trait) = match pattern_ctx {
+        PatternContext { param_ctx: Some(kind), impl_or_trait, .. } => (kind, impl_or_trait),
         _ => return None,
     };
 
@@ -45,7 +46,7 @@
 
     match kind {
         ParamKind::Function(function) => {
-            fill_fn_params(ctx, function, param_list, impl_, add_new_item_to_acc);
+            fill_fn_params(ctx, function, param_list, impl_or_trait, add_new_item_to_acc);
         }
         ParamKind::Closure(closure) => {
             let stmt_list = closure.syntax().ancestors().find_map(ast::StmtList::cast)?;
@@ -62,7 +63,7 @@
     ctx: &CompletionContext<'_>,
     function: &ast::Fn,
     param_list: &ast::ParamList,
-    impl_: &Option<ast::Impl>,
+    impl_or_trait: &Option<Either<ast::Impl, ast::Trait>>,
     mut add_new_item_to_acc: impl FnMut(&str),
 ) {
     let mut file_params = FxHashMap::default();
@@ -107,7 +108,7 @@
     }
     remove_duplicated(&mut file_params, param_list.params());
     let self_completion_items = ["self", "&self", "mut self", "&mut self"];
-    if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_) {
+    if should_add_self_completions(ctx.token.text_range().start(), param_list, impl_or_trait) {
         self_completion_items.into_iter().for_each(&mut add_new_item_to_acc);
     }
 
@@ -161,9 +162,9 @@
 fn should_add_self_completions(
     cursor: TextSize,
     param_list: &ast::ParamList,
-    impl_: &Option<ast::Impl>,
+    impl_or_trait: &Option<Either<ast::Impl, ast::Trait>>,
 ) -> bool {
-    if impl_.is_none() || param_list.self_param().is_some() {
+    if impl_or_trait.is_none() || param_list.self_param().is_some() {
         return false;
     }
     match param_list.params().next() {
diff --git a/crates/ide-completion/src/completions/pattern.rs b/crates/ide-completion/src/completions/pattern.rs
index 815ce51..0ce81d0 100644
--- a/crates/ide-completion/src/completions/pattern.rs
+++ b/crates/ide-completion/src/completions/pattern.rs
@@ -70,7 +70,7 @@
             acc,
             ctx,
             e,
-            &pattern_ctx.impl_,
+            pattern_ctx.impl_or_trait.as_ref().and_then(|it| it.as_ref().left()),
             |acc, ctx, variant, path| {
                 acc.add_qualified_variant_pat(ctx, pattern_ctx, variant, path);
             },
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 9deaaf6..d9b0d32 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -15,6 +15,7 @@
     FilePosition, FxHashMap, FxHashSet, RootDatabase, famous_defs::FamousDefs,
     helpers::is_editable_crate,
 };
+use itertools::Either;
 use syntax::{
     AstNode, Edition, SmolStr,
     SyntaxKind::{self, *},
@@ -282,7 +283,7 @@
     pub(crate) mut_token: Option<SyntaxToken>,
     /// The record pattern this name or ref is a field of
     pub(crate) record_pat: Option<ast::RecordPat>,
-    pub(crate) impl_: Option<ast::Impl>,
+    pub(crate) impl_or_trait: Option<Either<ast::Impl, ast::Trait>>,
     /// List of missing variants in a match expr
     pub(crate) missing_variants: Vec<hir::Variant>,
 }
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 9ab7b7c..6cd0984 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -1302,7 +1302,8 @@
             .is_some_and(|it| it.semicolon_token().is_none())
             || after_incomplete_let && incomplete_expr_stmt.unwrap_or(true) && !before_else_kw;
         let in_value = it.parent().and_then(Either::<ast::LetStmt, ast::ArgList>::cast).is_some();
-        let impl_ = fetch_immediate_impl(sema, original_file, expr.syntax());
+        let impl_ = fetch_immediate_impl_or_trait(sema, original_file, expr.syntax())
+            .and_then(Either::left);
 
         let in_match_guard = match it.parent().and_then(ast::MatchArm::cast) {
             Some(arm) => arm
@@ -1755,27 +1756,29 @@
         mut_token,
         ref_token,
         record_pat: None,
-        impl_: fetch_immediate_impl(sema, original_file, pat.syntax()),
+        impl_or_trait: fetch_immediate_impl_or_trait(sema, original_file, pat.syntax()),
         missing_variants,
     }
 }
 
-fn fetch_immediate_impl(
+fn fetch_immediate_impl_or_trait(
     sema: &Semantics<'_, RootDatabase>,
     original_file: &SyntaxNode,
     node: &SyntaxNode,
-) -> Option<ast::Impl> {
+) -> Option<Either<ast::Impl, ast::Trait>> {
     let mut ancestors = ancestors_in_file_compensated(sema, original_file, node)?
         .filter_map(ast::Item::cast)
         .filter(|it| !matches!(it, ast::Item::MacroCall(_)));
 
     match ancestors.next()? {
         ast::Item::Const(_) | ast::Item::Fn(_) | ast::Item::TypeAlias(_) => (),
-        ast::Item::Impl(it) => return Some(it),
+        ast::Item::Impl(it) => return Some(Either::Left(it)),
+        ast::Item::Trait(it) => return Some(Either::Right(it)),
         _ => return None,
     }
     match ancestors.next()? {
-        ast::Item::Impl(it) => Some(it),
+        ast::Item::Impl(it) => Some(Either::Left(it)),
+        ast::Item::Trait(it) => Some(Either::Right(it)),
         _ => None,
     }
 }
diff --git a/crates/ide-completion/src/tests/fn_param.rs b/crates/ide-completion/src/tests/fn_param.rs
index 451ce07..02cba6b 100644
--- a/crates/ide-completion/src/tests/fn_param.rs
+++ b/crates/ide-completion/src/tests/fn_param.rs
@@ -85,7 +85,11 @@
 }
 "#,
         expect![[r#"
+            bn &mut self
+            bn &self
             bn file_id: usize
+            bn mut self
+            bn self
             kw mut
             kw ref
         "#]],
@@ -183,6 +187,44 @@
     )
 }
 
+#[test]
+fn in_trait_only_param() {
+    check(
+        r#"
+trait A {
+    fn foo(file_id: usize) {}
+    fn new($0) {}
+}
+"#,
+        expect![[r#"
+            bn &mut self
+            bn &self
+            bn file_id: usize
+            bn mut self
+            bn self
+            kw mut
+            kw ref
+        "#]],
+    )
+}
+
+#[test]
+fn in_trait_after_self() {
+    check(
+        r#"
+trait A {
+    fn foo(file_id: usize) {}
+    fn new(self, $0) {}
+}
+"#,
+        expect![[r#"
+            bn file_id: usize
+            kw mut
+            kw ref
+        "#]],
+    )
+}
+
 // doesn't complete qux due to there being no expression after
 // see source_analyzer::adjust comment
 #[test]