aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorvsrs <[email protected]>2020-06-11 21:06:58 +0100
committervsrs <[email protected]>2020-06-18 08:15:43 +0100
commit022fbefffad0d7c402ac5607457f2828decb2188 (patch)
tree295bf5d6dfbec9b8eb3edbfce90e7c3748dd8f40
parent4b07c1e77515ae9198aae6275700aacd43181b50 (diff)
Apply suggestions from code review
-rw-r--r--crates/ra_hir/src/code_model.rs85
-rw-r--r--crates/ra_hir_ty/src/lib.rs53
-rw-r--r--crates/ra_ide/src/hover.rs255
3 files changed, 328 insertions, 65 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index d0a8199a6..ffd5278ec 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -26,8 +26,8 @@ use hir_ty::{
26 autoderef, 26 autoderef,
27 display::{HirDisplayError, HirFormatter}, 27 display::{HirDisplayError, HirFormatter},
28 expr::ExprValidator, 28 expr::ExprValidator,
29 method_resolution, ApplicationTy, Canonical, InEnvironment, Substs, TraitEnvironment, TraitRef, 29 method_resolution, ApplicationTy, Canonical, GenericPredicate, InEnvironment, Substs,
30 Ty, TyDefId, TypeCtor, 30 TraitEnvironment, Ty, TyDefId, TypeCtor,
31}; 31};
32use ra_db::{CrateId, CrateName, Edition, FileId}; 32use ra_db::{CrateId, CrateName, Edition, FileId};
33use ra_prof::profile; 33use ra_prof::profile;
@@ -1379,8 +1379,17 @@ impl Type {
1379 self.ty.value.dyn_trait().map(Into::into) 1379 self.ty.value.dyn_trait().map(Into::into)
1380 } 1380 }
1381 1381
1382 pub fn as_impl_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { 1382 pub fn as_impl_traits(&self, db: &dyn HirDatabase) -> Option<Vec<Trait>> {
1383 self.ty.value.impl_trait_ref(db).map(|it| it.trait_.into()) 1383 self.ty.value.impl_trait_bounds(db).map(|it| {
1384 it.into_iter()
1385 .filter_map(|pred| match pred {
1386 hir_ty::GenericPredicate::Implemented(trait_ref) => {
1387 Some(Trait::from(trait_ref.trait_))
1388 }
1389 _ => None,
1390 })
1391 .collect()
1392 })
1384 } 1393 }
1385 1394
1386 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> { 1395 pub fn as_associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<Trait> {
@@ -1410,71 +1419,77 @@ impl Type {
1410 } 1419 }
1411 1420
1412 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) { 1421 pub fn walk(&self, db: &dyn HirDatabase, mut cb: impl FnMut(Type)) {
1413 // TypeWalk::walk does not preserve items order! 1422 // TypeWalk::walk for a Ty at first visits parameters and only after that the Ty itself.
1414 fn walk_substs(db: &dyn HirDatabase, substs: &Substs, cb: &mut impl FnMut(Type)) { 1423 // We need a different order here.
1424
1425 fn walk_substs(
1426 db: &dyn HirDatabase,
1427 type_: &Type,
1428 substs: &Substs,
1429 cb: &mut impl FnMut(Type),
1430 ) {
1415 for ty in substs.iter() { 1431 for ty in substs.iter() {
1416 walk_ty(db, ty, cb); 1432 walk_type(db, &type_.derived(ty.clone()), cb);
1417 } 1433 }
1418 } 1434 }
1419 1435
1420 fn walk_trait( 1436 fn walk_bounds(
1421 db: &dyn HirDatabase, 1437 db: &dyn HirDatabase,
1422 ty: Ty, 1438 type_: &Type,
1423 trait_ref: &TraitRef, 1439 bounds: &[GenericPredicate],
1424 cb: &mut impl FnMut(Type), 1440 cb: &mut impl FnMut(Type),
1425 ) { 1441 ) {
1426 let def_db: &dyn DefDatabase = db.upcast(); 1442 for pred in bounds {
1427 let resolver = trait_ref.trait_.resolver(def_db); 1443 match pred {
1428 let krate = trait_ref.trait_.lookup(def_db).container.module(def_db).krate; 1444 GenericPredicate::Implemented(trait_ref) => {
1429 cb(Type::new_with_resolver_inner(db, krate, &resolver, ty)); 1445 cb(type_.clone());
1430 walk_substs(db, &trait_ref.substs, cb); 1446 walk_substs(db, type_, &trait_ref.substs, cb);
1447 }
1448 _ => (),
1449 }
1450 }
1431 } 1451 }
1432 1452
1433 fn walk_ty(db: &dyn HirDatabase, ty: &Ty, cb: &mut impl FnMut(Type)) { 1453 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
1434 let def_db: &dyn DefDatabase = db.upcast(); 1454 let ty = type_.ty.value.strip_references();
1435 let ty = ty.strip_references();
1436 match ty { 1455 match ty {
1437 Ty::Apply(ApplicationTy { ctor, parameters }) => { 1456 Ty::Apply(ApplicationTy { ctor, parameters }) => {
1438 match ctor { 1457 match ctor {
1439 TypeCtor::Adt(adt) => { 1458 TypeCtor::Adt(_) => {
1440 cb(Type::from_def(db, adt.module(def_db).krate, *adt)); 1459 cb(type_.derived(ty.clone()));
1441 } 1460 }
1442 TypeCtor::AssociatedType(_) => { 1461 TypeCtor::AssociatedType(_) => {
1443 if let Some(trait_id) = ty.associated_type_parent_trait(db) { 1462 if let Some(_) = ty.associated_type_parent_trait(db) {
1444 let resolver = trait_id.resolver(def_db); 1463 cb(type_.derived(ty.clone()));
1445 let krate = trait_id.lookup(def_db).container.module(def_db).krate;
1446 cb(Type::new_with_resolver_inner(db, krate, &resolver, ty.clone()));
1447 } 1464 }
1448 } 1465 }
1449 _ => (), 1466 _ => (),
1450 } 1467 }
1451 1468
1452 // adt params, tuples, etc... 1469 // adt params, tuples, etc...
1453 walk_substs(db, parameters, cb); 1470 walk_substs(db, type_, parameters, cb);
1454 } 1471 }
1455 Ty::Opaque(opaque_ty) => { 1472 Ty::Opaque(opaque_ty) => {
1456 if let Some(trait_ref) = ty.impl_trait_ref(db) { 1473 if let Some(bounds) = ty.impl_trait_bounds(db) {
1457 walk_trait(db, ty.clone(), &trait_ref, cb); 1474 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1458 } 1475 }
1459 1476
1460 walk_substs(db, &opaque_ty.parameters, cb); 1477 walk_substs(db, type_, &opaque_ty.parameters, cb);
1461 } 1478 }
1462 Ty::Placeholder(_) => { 1479 Ty::Placeholder(_) => {
1463 if let Some(trait_ref) = ty.impl_trait_ref(db) { 1480 if let Some(bounds) = ty.impl_trait_bounds(db) {
1464 walk_trait(db, ty.clone(), &trait_ref, cb); 1481 walk_bounds(db, &type_.derived(ty.clone()), &bounds, cb);
1465 } 1482 }
1466 } 1483 }
1467 Ty::Dyn(_) => { 1484 Ty::Dyn(bounds) => {
1468 if let Some(trait_ref) = ty.dyn_trait_ref() { 1485 walk_bounds(db, &type_.derived(ty.clone()), bounds.as_ref(), cb);
1469 walk_trait(db, ty.clone(), trait_ref, cb);
1470 }
1471 } 1486 }
1472 1487
1473 _ => (), 1488 _ => (),
1474 } 1489 }
1475 } 1490 }
1476 1491
1477 walk_ty(db, &self.ty.value, &mut cb); 1492 walk_type(db, self, &mut cb);
1478 } 1493 }
1479} 1494}
1480 1495
diff --git a/crates/ra_hir_ty/src/lib.rs b/crates/ra_hir_ty/src/lib.rs
index 25ab9d872..f22232324 100644
--- a/crates/ra_hir_ty/src/lib.rs
+++ b/crates/ra_hir_ty/src/lib.rs
@@ -73,6 +73,7 @@ pub use lower::{
73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 73pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment};
74 74
75pub use chalk_ir::{BoundVar, DebruijnIndex}; 75pub use chalk_ir::{BoundVar, DebruijnIndex};
76use itertools::Itertools;
76 77
77/// A type constructor or type name: this might be something like the primitive 78/// A type constructor or type name: this might be something like the primitive
78/// type `bool`, a struct like `Vec`, or things like function pointers or 79/// type `bool`, a struct like `Vec`, or things like function pointers or
@@ -815,6 +816,11 @@ impl Ty {
815 } 816 }
816 } 817 }
817 818
819 /// If this is a `dyn Trait`, returns that trait.
820 pub fn dyn_trait(&self) -> Option<TraitId> {
821 self.dyn_trait_ref().map(|it| it.trait_)
822 }
823
818 fn builtin_deref(&self) -> Option<Ty> { 824 fn builtin_deref(&self) -> Option<Ty> {
819 match self { 825 match self {
820 Ty::Apply(a_ty) => match a_ty.ctor { 826 Ty::Apply(a_ty) => match a_ty.ctor {
@@ -867,18 +873,7 @@ impl Ty {
867 } 873 }
868 } 874 }
869 875
870 /// If this is a `dyn Trait`, returns that trait. 876 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> {
871 pub fn dyn_trait(&self) -> Option<TraitId> {
872 match self {
873 Ty::Dyn(predicates) => predicates.iter().find_map(|pred| match pred {
874 GenericPredicate::Implemented(tr) => Some(tr.trait_),
875 _ => None,
876 }),
877 _ => None,
878 }
879 }
880
881 pub fn impl_trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
882 match self { 877 match self {
883 Ty::Opaque(opaque_ty) => { 878 Ty::Opaque(opaque_ty) => {
884 let predicates = match opaque_ty.opaque_ty_id { 879 let predicates = match opaque_ty.opaque_ty_id {
@@ -892,25 +887,21 @@ impl Ty {
892 } 887 }
893 }; 888 };
894 889
895 predicates.and_then(|it| { 890 predicates.map(|it| it.value)
896 it.value.iter().find_map(|pred| match pred {
897 GenericPredicate::Implemented(tr) => Some(tr.clone()),
898 _ => None,
899 })
900 })
901 } 891 }
902 Ty::Placeholder(id) => { 892 Ty::Placeholder(id) => {
903 let generic_params = db.generic_params(id.parent); 893 let generic_params = db.generic_params(id.parent);
904 let param_data = &generic_params.types[id.local_id]; 894 let param_data = &generic_params.types[id.local_id];
905 match param_data.provenance { 895 match param_data.provenance {
906 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => db 896 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
907 .generic_predicates_for_param(*id) 897 let predicates = db
908 .into_iter() 898 .generic_predicates_for_param(*id)
909 .map(|pred| pred.value.clone()) 899 .into_iter()
910 .find_map(|pred| match pred { 900 .map(|pred| pred.value.clone())
911 GenericPredicate::Implemented(tr) => Some(tr.clone()), 901 .collect_vec();
912 _ => None, 902
913 }), 903 Some(predicates)
904 }
914 _ => None, 905 _ => None,
915 } 906 }
916 } 907 }
@@ -926,6 +917,12 @@ impl Ty {
926 _ => None, 917 _ => None,
927 } 918 }
928 } 919 }
920 Ty::Projection(projection_ty) => {
921 match projection_ty.associated_ty.lookup(db.upcast()).container {
922 AssocContainerId::TraitId(trait_id) => Some(trait_id),
923 _ => None,
924 }
925 }
929 _ => None, 926 _ => None,
930 } 927 }
931 } 928 }
@@ -1104,10 +1101,10 @@ pub enum OpaqueTyId {
1104 1101
1105#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1102#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1106pub struct ReturnTypeImplTraits { 1103pub struct ReturnTypeImplTraits {
1107 pub impl_traits: Vec<ReturnTypeImplTrait>, 1104 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
1108} 1105}
1109 1106
1110#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1107#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1111pub struct ReturnTypeImplTrait { 1108pub(crate) struct ReturnTypeImplTrait {
1112 pub bounds: Binders<Vec<GenericPredicate>>, 1109 pub bounds: Binders<Vec<GenericPredicate>>,
1113} 1110}
diff --git a/crates/ra_ide/src/hover.rs b/crates/ra_ide/src/hover.rs
index c2909e200..d870e4cbc 100644
--- a/crates/ra_ide/src/hover.rs
+++ b/crates/ra_ide/src/hover.rs
@@ -248,8 +248,8 @@ fn goto_type_action(db: &RootDatabase, def: Definition) -> Option<HoverAction> {
248 push_new_def(adt.into()); 248 push_new_def(adt.into());
249 } else if let Some(trait_) = t.as_dyn_trait() { 249 } else if let Some(trait_) = t.as_dyn_trait() {
250 push_new_def(trait_.into()); 250 push_new_def(trait_.into());
251 } else if let Some(trait_) = t.as_impl_trait(db) { 251 } else if let Some(traits) = t.as_impl_traits(db) {
252 push_new_def(trait_.into()); 252 traits.into_iter().for_each(|it| push_new_def(it.into()));
253 } else if let Some(trait_) = t.as_associated_type_parent_trait(db) { 253 } else if let Some(trait_) = t.as_associated_type_parent_trait(db) {
254 push_new_def(trait_.into()); 254 push_new_def(trait_.into());
255 } 255 }
@@ -1735,6 +1735,176 @@ fn func(foo: i32) { if true { <|>foo; }; }
1735 } 1735 }
1736 1736
1737 #[test] 1737 #[test]
1738 fn test_hover_return_impl_traits_has_goto_type_action() {
1739 let (_, actions) = check_hover_result(
1740 "
1741 //- /main.rs
1742 trait Foo {}
1743 trait Bar {}
1744
1745 fn foo() -> impl Foo + Bar {}
1746
1747 fn main() {
1748 let s<|>t = foo();
1749 }
1750 ",
1751 &["impl Foo + Bar"],
1752 );
1753 assert_debug_snapshot!(actions,
1754 @r###"
1755 [
1756 GoToType(
1757 [
1758 HoverGotoTypeData {
1759 mod_path: "Foo",
1760 nav: NavigationTarget {
1761 file_id: FileId(
1762 1,
1763 ),
1764 full_range: 0..12,
1765 name: "Foo",
1766 kind: TRAIT_DEF,
1767 focus_range: Some(
1768 6..9,
1769 ),
1770 container_name: None,
1771 description: Some(
1772 "trait Foo",
1773 ),
1774 docs: None,
1775 },
1776 },
1777 HoverGotoTypeData {
1778 mod_path: "Bar",
1779 nav: NavigationTarget {
1780 file_id: FileId(
1781 1,
1782 ),
1783 full_range: 13..25,
1784 name: "Bar",
1785 kind: TRAIT_DEF,
1786 focus_range: Some(
1787 19..22,
1788 ),
1789 container_name: None,
1790 description: Some(
1791 "trait Bar",
1792 ),
1793 docs: None,
1794 },
1795 },
1796 ],
1797 ),
1798 ]
1799 "###);
1800 }
1801
1802 #[test]
1803 fn test_hover_generic_return_impl_traits_has_goto_type_action() {
1804 let (_, actions) = check_hover_result(
1805 "
1806 //- /main.rs
1807 trait Foo<T> {}
1808 trait Bar<T> {}
1809 struct S1 {}
1810 struct S2 {}
1811
1812 fn foo() -> impl Foo<S1> + Bar<S2> {}
1813
1814 fn main() {
1815 let s<|>t = foo();
1816 }
1817 ",
1818 &["impl Foo<S1> + Bar<S2>"],
1819 );
1820 assert_debug_snapshot!(actions,
1821 @r###"
1822 [
1823 GoToType(
1824 [
1825 HoverGotoTypeData {
1826 mod_path: "Foo",
1827 nav: NavigationTarget {
1828 file_id: FileId(
1829 1,
1830 ),
1831 full_range: 0..15,
1832 name: "Foo",
1833 kind: TRAIT_DEF,
1834 focus_range: Some(
1835 6..9,
1836 ),
1837 container_name: None,
1838 description: Some(
1839 "trait Foo",
1840 ),
1841 docs: None,
1842 },
1843 },
1844 HoverGotoTypeData {
1845 mod_path: "Bar",
1846 nav: NavigationTarget {
1847 file_id: FileId(
1848 1,
1849 ),
1850 full_range: 16..31,
1851 name: "Bar",
1852 kind: TRAIT_DEF,
1853 focus_range: Some(
1854 22..25,
1855 ),
1856 container_name: None,
1857 description: Some(
1858 "trait Bar",
1859 ),
1860 docs: None,
1861 },
1862 },
1863 HoverGotoTypeData {
1864 mod_path: "S1",
1865 nav: NavigationTarget {
1866 file_id: FileId(
1867 1,
1868 ),
1869 full_range: 32..44,
1870 name: "S1",
1871 kind: STRUCT_DEF,
1872 focus_range: Some(
1873 39..41,
1874 ),
1875 container_name: None,
1876 description: Some(
1877 "struct S1",
1878 ),
1879 docs: None,
1880 },
1881 },
1882 HoverGotoTypeData {
1883 mod_path: "S2",
1884 nav: NavigationTarget {
1885 file_id: FileId(
1886 1,
1887 ),
1888 full_range: 45..57,
1889 name: "S2",
1890 kind: STRUCT_DEF,
1891 focus_range: Some(
1892 52..54,
1893 ),
1894 container_name: None,
1895 description: Some(
1896 "struct S2",
1897 ),
1898 docs: None,
1899 },
1900 },
1901 ],
1902 ),
1903 ]
1904 "###);
1905 }
1906
1907 #[test]
1738 fn test_hover_arg_impl_trait_has_goto_type_action() { 1908 fn test_hover_arg_impl_trait_has_goto_type_action() {
1739 let (_, actions) = check_hover_result( 1909 let (_, actions) = check_hover_result(
1740 " 1910 "
@@ -1775,6 +1945,87 @@ fn func(foo: i32) { if true { <|>foo; }; }
1775 } 1945 }
1776 1946
1777 #[test] 1947 #[test]
1948 fn test_hover_arg_impl_traits_has_goto_type_action() {
1949 let (_, actions) = check_hover_result(
1950 "
1951 //- /lib.rs
1952 trait Foo {}
1953 trait Bar<T> {}
1954 struct S{}
1955
1956 fn foo(ar<|>g: &impl Foo + Bar<S>) {}
1957 ",
1958 &["&impl Foo + Bar<S>"],
1959 );
1960 assert_debug_snapshot!(actions,
1961 @r###"
1962 [
1963 GoToType(
1964 [
1965 HoverGotoTypeData {
1966 mod_path: "Foo",
1967 nav: NavigationTarget {
1968 file_id: FileId(
1969 1,
1970 ),
1971 full_range: 0..12,
1972 name: "Foo",
1973 kind: TRAIT_DEF,
1974 focus_range: Some(
1975 6..9,
1976 ),
1977 container_name: None,
1978 description: Some(
1979 "trait Foo",
1980 ),
1981 docs: None,
1982 },
1983 },
1984 HoverGotoTypeData {
1985 mod_path: "Bar",
1986 nav: NavigationTarget {
1987 file_id: FileId(
1988 1,
1989 ),
1990 full_range: 13..28,
1991 name: "Bar",
1992 kind: TRAIT_DEF,
1993 focus_range: Some(
1994 19..22,
1995 ),
1996 container_name: None,
1997 description: Some(
1998 "trait Bar",
1999 ),
2000 docs: None,
2001 },
2002 },
2003 HoverGotoTypeData {
2004 mod_path: "S",
2005 nav: NavigationTarget {
2006 file_id: FileId(
2007 1,
2008 ),
2009 full_range: 29..39,
2010 name: "S",
2011 kind: STRUCT_DEF,
2012 focus_range: Some(
2013 36..37,
2014 ),
2015 container_name: None,
2016 description: Some(
2017 "struct S",
2018 ),
2019 docs: None,
2020 },
2021 },
2022 ],
2023 ),
2024 ]
2025 "###);
2026 }
2027
2028 #[test]
1778 fn test_hover_arg_generic_impl_trait_has_goto_type_action() { 2029 fn test_hover_arg_generic_impl_trait_has_goto_type_action() {
1779 let (_, actions) = check_hover_result( 2030 let (_, actions) = check_hover_result(
1780 " 2031 "