aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2020-07-17 18:02:28 +0100
committerGitHub <[email protected]>2020-07-17 18:02:28 +0100
commit2777f8c2950f3d204b7ecbf40785fe8fc3523fc1 (patch)
tree86399ce1b6a1a7c190e2817cf942f021ee0af581
parentde8c5fc09bdc94dde72ac24c19c8b80a438f0101 (diff)
parentcab360fe3105264f483c4f2b1a33f3d9010e3436 (diff)
Merge #5423
5423: Correctly resolve assoc. types in path bindings r=matklad a=jonas-schievink Previously invoking goto def on `impl Iterator<Item<|> = ()>` would go to `Iterator`, not `Item`. This fixes that. Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r--crates/ra_ide/src/goto_definition.rs80
-rw-r--r--crates/ra_ide_db/src/defs.rs22
2 files changed, 102 insertions, 0 deletions
diff --git a/crates/ra_ide/src/goto_definition.rs b/crates/ra_ide/src/goto_definition.rs
index db6d20a37..4e3f428fa 100644
--- a/crates/ra_ide/src/goto_definition.rs
+++ b/crates/ra_ide/src/goto_definition.rs
@@ -884,4 +884,84 @@ pub mod module {
884"#, 884"#,
885 ); 885 );
886 } 886 }
887
888 #[test]
889 fn goto_def_for_assoc_ty_in_path() {
890 check(
891 r#"
892trait Iterator {
893 type Item;
894 //^^^^
895}
896
897fn f() -> impl Iterator<Item<|> = u8> {}
898"#,
899 );
900 }
901
902 #[test]
903 fn goto_def_for_assoc_ty_in_path_multiple() {
904 check(
905 r#"
906trait Iterator {
907 type A;
908 //^
909 type B;
910}
911
912fn f() -> impl Iterator<A<|> = u8, B = ()> {}
913"#,
914 );
915 check(
916 r#"
917trait Iterator {
918 type A;
919 type B;
920 //^
921}
922
923fn f() -> impl Iterator<A = u8, B<|> = ()> {}
924"#,
925 );
926 }
927
928 #[test]
929 fn goto_def_for_assoc_ty_ufcs() {
930 check(
931 r#"
932trait Iterator {
933 type Item;
934 //^^^^
935}
936
937fn g() -> <() as Iterator<Item<|> = ()>>::Item {}
938"#,
939 );
940 }
941
942 #[test]
943 fn goto_def_for_assoc_ty_ufcs_multiple() {
944 check(
945 r#"
946trait Iterator {
947 type A;
948 //^
949 type B;
950}
951
952fn g() -> <() as Iterator<A<|> = (), B = u8>>::B {}
953"#,
954 );
955 check(
956 r#"
957trait Iterator {
958 type A;
959 type B;
960 //^
961}
962
963fn g() -> <() as Iterator<A = (), B<|> = u8>>::A {}
964"#,
965 );
966 }
887} 967}
diff --git a/crates/ra_ide_db/src/defs.rs b/crates/ra_ide_db/src/defs.rs
index bcaabca92..e06b189a0 100644
--- a/crates/ra_ide_db/src/defs.rs
+++ b/crates/ra_ide_db/src/defs.rs
@@ -254,6 +254,28 @@ pub fn classify_name_ref(
254 } 254 }
255 } 255 }
256 256
257 if ast::AssocTypeArg::cast(parent.clone()).is_some() {
258 // `Trait<Assoc = Ty>`
259 // ^^^^^
260 let path = name_ref.syntax().ancestors().find_map(ast::Path::cast)?;
261 let resolved = sema.resolve_path(&path)?;
262 if let PathResolution::Def(ModuleDef::Trait(tr)) = resolved {
263 if let Some(ty) = tr
264 .items(sema.db)
265 .iter()
266 .filter_map(|assoc| match assoc {
267 hir::AssocItem::TypeAlias(it) => Some(*it),
268 _ => None,
269 })
270 .find(|alias| alias.name(sema.db).to_string() == **name_ref.text())
271 {
272 return Some(NameRefClass::Definition(Definition::ModuleDef(
273 ModuleDef::TypeAlias(ty),
274 )));
275 }
276 }
277 }
278
257 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) { 279 if let Some(macro_call) = parent.ancestors().find_map(ast::MacroCall::cast) {
258 if let Some(path) = macro_call.path() { 280 if let Some(path) = macro_call.path() {
259 if path.qualifier().is_none() { 281 if path.qualifier().is_none() {