aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_ty/src/infer.rs5
-rw-r--r--crates/hir_ty/src/tests/traits.rs37
-rw-r--r--crates/ide/src/goto_implementation.rs46
3 files changed, 86 insertions, 2 deletions
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index db3c937ff..edb65622f 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -580,7 +580,10 @@ impl<'a> InferenceContext<'a> {
580 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> { 580 fn resolve_ops_try_ok(&self) -> Option<TypeAliasId> {
581 let path = path![core::ops::Try]; 581 let path = path![core::ops::Try];
582 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?; 582 let trait_ = self.resolver.resolve_known_trait(self.db.upcast(), &path)?;
583 self.db.trait_data(trait_).associated_type_by_name(&name![Ok]) 583 let trait_data = self.db.trait_data(trait_);
584 trait_data
585 .associated_type_by_name(&name![Ok])
586 .or_else(|| trait_data.associated_type_by_name(&name![Output]))
584 } 587 }
585 588
586 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> { 589 fn resolve_ops_neg_output(&self) -> Option<TypeAliasId> {
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index eea98fd4f..6cd8786ea 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -161,6 +161,43 @@ mod result {
161} 161}
162 162
163#[test] 163#[test]
164fn infer_tryv2() {
165 check_types(
166 r#"
167//- /main.rs crate:main deps:core
168fn test() {
169 let r: Result<i32, u64> = Result::Ok(1);
170 let v = r?;
171 v;
172} //^ i32
173
174//- /core.rs crate:core
175#[prelude_import] use ops::*;
176mod ops {
177 trait Try {
178 type Output;
179 type Residual;
180 }
181}
182
183#[prelude_import] use result::*;
184mod result {
185 enum Infallible {}
186 enum Result<O, E> {
187 Ok(O),
188 Err(E)
189 }
190
191 impl<O, E> crate::ops::Try for Result<O, E> {
192 type Output = O;
193 type Error = Result<Infallible, E>;
194 }
195}
196"#,
197 );
198}
199
200#[test]
164fn infer_for_loop() { 201fn infer_for_loop() {
165 check_types( 202 check_types(
166 r#" 203 r#"
diff --git a/crates/ide/src/goto_implementation.rs b/crates/ide/src/goto_implementation.rs
index 05130a237..5a8d3c3f9 100644
--- a/crates/ide/src/goto_implementation.rs
+++ b/crates/ide/src/goto_implementation.rs
@@ -1,4 +1,4 @@
1use hir::{Impl, Semantics}; 1use hir::{AsAssocItem, Impl, Semantics};
2use ide_db::{ 2use ide_db::{
3 defs::{Definition, NameClass, NameRefClass}, 3 defs::{Definition, NameClass, NameRefClass},
4 RootDatabase, 4 RootDatabase,
@@ -36,6 +36,7 @@ pub(crate) fn goto_implementation(
36 } 36 }
37 ast::NameLike::Lifetime(_) => None, 37 ast::NameLike::Lifetime(_) => None,
38 }?; 38 }?;
39
39 let def = match def { 40 let def = match def {
40 Definition::ModuleDef(def) => def, 41 Definition::ModuleDef(def) => def,
41 _ => return None, 42 _ => return None,
@@ -48,6 +49,12 @@ pub(crate) fn goto_implementation(
48 let module = sema.to_module_def(position.file_id)?; 49 let module = sema.to_module_def(position.file_id)?;
49 impls_for_ty(&sema, builtin.ty(sema.db, module)) 50 impls_for_ty(&sema, builtin.ty(sema.db, module))
50 } 51 }
52 hir::ModuleDef::Function(f) => {
53 let assoc = f.as_assoc_item(sema.db)?;
54 let name = assoc.name(sema.db)?;
55 let trait_ = assoc.containing_trait(sema.db)?;
56 impls_for_trait_fn(&sema, trait_, name)
57 }
51 _ => return None, 58 _ => return None,
52 }; 59 };
53 Some(RangeInfo { range: node.syntax().text_range(), info: navs }) 60 Some(RangeInfo { range: node.syntax().text_range(), info: navs })
@@ -64,6 +71,23 @@ fn impls_for_trait(sema: &Semantics<RootDatabase>, trait_: hir::Trait) -> Vec<Na
64 .collect() 71 .collect()
65} 72}
66 73
74fn impls_for_trait_fn(
75 sema: &Semantics<RootDatabase>,
76 trait_: hir::Trait,
77 fun_name: hir::Name,
78) -> Vec<NavigationTarget> {
79 Impl::all_for_trait(sema.db, trait_)
80 .into_iter()
81 .filter_map(|imp| {
82 let item = imp.items(sema.db).iter().find_map(|itm| {
83 let itm_name = itm.name(sema.db)?;
84 (itm_name == fun_name).then(|| itm.clone())
85 })?;
86 item.try_to_nav(sema.db)
87 })
88 .collect()
89}
90
67#[cfg(test)] 91#[cfg(test)]
68mod tests { 92mod tests {
69 use ide_db::base_db::FileRange; 93 use ide_db::base_db::FileRange;
@@ -262,4 +286,24 @@ impl bool {}
262"#, 286"#,
263 ); 287 );
264 } 288 }
289
290 #[test]
291 fn goto_implementation_trait_functions() {
292 check(
293 r#"
294trait Tr {
295 fn f$0();
296}
297
298struct S;
299
300impl Tr for S {
301 fn f() {
302 //^
303 println!("Hello, world!");
304 }
305}
306"#,
307 );
308 }
265} 309}