diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/Cargo.toml | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/code_model.rs | 54 | ||||
-rw-r--r-- | crates/ra_hir/src/generics.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/name.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 27 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/type_ref.rs | 7 |
10 files changed, 101 insertions, 38 deletions
diff --git a/crates/ra_hir/Cargo.toml b/crates/ra_hir/Cargo.toml index d9bed4dda..e89b97daf 100644 --- a/crates/ra_hir/Cargo.toml +++ b/crates/ra_hir/Cargo.toml | |||
@@ -12,6 +12,7 @@ rustc-hash = "1.0" | |||
12 | parking_lot = "0.9.0" | 12 | parking_lot = "0.9.0" |
13 | ena = "0.13" | 13 | ena = "0.13" |
14 | once_cell = "1.0.1" | 14 | once_cell = "1.0.1" |
15 | itertools = "0.8.0" | ||
15 | 16 | ||
16 | ra_syntax = { path = "../ra_syntax" } | 17 | ra_syntax = { path = "../ra_syntax" } |
17 | ra_arena = { path = "../ra_arena" } | 18 | ra_arena = { path = "../ra_arena" } |
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index f7efc1b66..4739246cb 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs | |||
@@ -1,8 +1,11 @@ | |||
1 | pub(crate) mod src; | 1 | pub(crate) mod src; |
2 | pub(crate) mod docs; | 2 | pub(crate) mod docs; |
3 | 3 | ||
4 | use std::iter; | ||
4 | use std::sync::Arc; | 5 | use std::sync::Arc; |
5 | 6 | ||
7 | use itertools::Itertools; | ||
8 | |||
6 | use ra_db::{CrateId, Edition, FileId, SourceRootId}; | 9 | use ra_db::{CrateId, Edition, FileId, SourceRootId}; |
7 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; | 10 | use ra_syntax::ast::{self, NameOwner, TypeAscriptionOwner}; |
8 | 11 | ||
@@ -820,7 +823,43 @@ impl Trait { | |||
820 | self.trait_data(db).items().to_vec() | 823 | self.trait_data(db).items().to_vec() |
821 | } | 824 | } |
822 | 825 | ||
823 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: Name) -> Option<TypeAlias> { | 826 | fn direct_super_traits(self, db: &impl HirDatabase) -> Vec<Trait> { |
827 | let resolver = self.resolver(db); | ||
828 | // returning the iterator directly doesn't easily work because of | ||
829 | // lifetime problems, but since there usually shouldn't be more than a | ||
830 | // few direct traits this should be fine (we could even use some kind of | ||
831 | // SmallVec if performance is a concern) | ||
832 | self.generic_params(db) | ||
833 | .where_predicates | ||
834 | .iter() | ||
835 | .filter_map(|pred| match &pred.type_ref { | ||
836 | TypeRef::Path(p) if p.as_ident() == Some(&crate::name::SELF_TYPE) => { | ||
837 | pred.bound.as_path() | ||
838 | } | ||
839 | _ => None, | ||
840 | }) | ||
841 | .filter_map(|path| { | ||
842 | match resolver.resolve_path_without_assoc_items(db, path).take_types() { | ||
843 | Some(crate::Resolution::Def(ModuleDef::Trait(t))) => Some(t), | ||
844 | _ => None, | ||
845 | } | ||
846 | }) | ||
847 | .collect() | ||
848 | } | ||
849 | |||
850 | /// Returns an iterator over the whole super trait hierarchy (not including | ||
851 | /// the trait itself). (This iterator may be infinite in case of circular | ||
852 | /// super trait dependencies, which are possible in malformed code.) | ||
853 | pub fn all_super_traits<'a>( | ||
854 | self, | ||
855 | db: &'a impl HirDatabase, | ||
856 | ) -> impl Iterator<Item = Trait> + 'a { | ||
857 | self.direct_super_traits(db).into_iter().flat_map(move |t| { | ||
858 | iter::once(t).chain(Box::new(t.all_super_traits(db)) as Box<dyn Iterator<Item = Trait>>) | ||
859 | }) | ||
860 | } | ||
861 | |||
862 | pub fn associated_type_by_name(self, db: &impl DefDatabase, name: &Name) -> Option<TypeAlias> { | ||
824 | let trait_data = self.trait_data(db); | 863 | let trait_data = self.trait_data(db); |
825 | trait_data | 864 | trait_data |
826 | .items() | 865 | .items() |
@@ -829,7 +868,18 @@ impl Trait { | |||
829 | TraitItem::TypeAlias(t) => Some(*t), | 868 | TraitItem::TypeAlias(t) => Some(*t), |
830 | _ => None, | 869 | _ => None, |
831 | }) | 870 | }) |
832 | .find(|t| t.name(db) == name) | 871 | .find(|t| &t.name(db) == name) |
872 | } | ||
873 | |||
874 | pub fn associated_type_by_name_including_super_traits( | ||
875 | self, | ||
876 | db: &impl HirDatabase, | ||
877 | name: &Name, | ||
878 | ) -> Option<TypeAlias> { | ||
879 | iter::once(self) | ||
880 | .chain(self.all_super_traits(db)) | ||
881 | .unique() | ||
882 | .find_map(|t| t.associated_type_by_name(db, name)) | ||
833 | } | 883 | } |
834 | 884 | ||
835 | pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { | 885 | pub(crate) fn trait_data(self, db: &impl DefDatabase) -> Arc<TraitData> { |
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs index d6728cc9f..c76df0698 100644 --- a/crates/ra_hir/src/generics.rs +++ b/crates/ra_hir/src/generics.rs | |||
@@ -87,11 +87,15 @@ impl GenericParams { | |||
87 | // traits get the Self type as an implicit first type parameter | 87 | // traits get the Self type as an implicit first type parameter |
88 | generics.params.push(GenericParam { idx: start, name: SELF_TYPE, default: None }); | 88 | generics.params.push(GenericParam { idx: start, name: SELF_TYPE, default: None }); |
89 | generics.fill(&it.source(db).ast, start + 1); | 89 | generics.fill(&it.source(db).ast, start + 1); |
90 | // add super traits as bounds on Self | ||
91 | // i.e., trait Foo: Bar is equivalent to trait Foo where Self: Bar | ||
92 | let self_param = TypeRef::Path(SELF_TYPE.into()); | ||
93 | generics.fill_bounds(&it.source(db).ast, self_param); | ||
90 | } | 94 | } |
91 | GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start), | 95 | GenericDef::TypeAlias(it) => generics.fill(&it.source(db).ast, start), |
92 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a | 96 | // Note that we don't add `Self` here: in `impl`s, `Self` is not a |
93 | // type-parameter, but rather is a type-alias for impl's target | 97 | // type-parameter, but rather is a type-alias for impl's target |
94 | // type, so this is handled by the resovler. | 98 | // type, so this is handled by the resolver. |
95 | GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start), | 99 | GenericDef::ImplBlock(it) => generics.fill(&it.source(db).ast, start), |
96 | GenericDef::EnumVariant(_) => {} | 100 | GenericDef::EnumVariant(_) => {} |
97 | } | 101 | } |
@@ -108,6 +112,14 @@ impl GenericParams { | |||
108 | } | 112 | } |
109 | } | 113 | } |
110 | 114 | ||
115 | fn fill_bounds(&mut self, node: &impl ast::TypeBoundsOwner, type_ref: TypeRef) { | ||
116 | for bound in | ||
117 | node.type_bound_list().iter().flat_map(|type_bound_list| type_bound_list.bounds()) | ||
118 | { | ||
119 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
120 | } | ||
121 | } | ||
122 | |||
111 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { | 123 | fn fill_params(&mut self, params: ast::TypeParamList, start: u32) { |
112 | for (idx, type_param) in params.type_params().enumerate() { | 124 | for (idx, type_param) in params.type_params().enumerate() { |
113 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 125 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
@@ -117,13 +129,7 @@ impl GenericParams { | |||
117 | self.params.push(param); | 129 | self.params.push(param); |
118 | 130 | ||
119 | let type_ref = TypeRef::Path(name.into()); | 131 | let type_ref = TypeRef::Path(name.into()); |
120 | for bound in type_param | 132 | self.fill_bounds(&type_param, type_ref); |
121 | .type_bound_list() | ||
122 | .iter() | ||
123 | .flat_map(|type_bound_list| type_bound_list.bounds()) | ||
124 | { | ||
125 | self.add_where_predicate_from_bound(bound, type_ref.clone()); | ||
126 | } | ||
127 | } | 133 | } |
128 | } | 134 | } |
129 | 135 | ||
diff --git a/crates/ra_hir/src/name.rs b/crates/ra_hir/src/name.rs index 9c4822d91..13bc901bc 100644 --- a/crates/ra_hir/src/name.rs +++ b/crates/ra_hir/src/name.rs | |||
@@ -38,11 +38,6 @@ impl Name { | |||
38 | Name::new(idx.to_string().into()) | 38 | Name::new(idx.to_string().into()) |
39 | } | 39 | } |
40 | 40 | ||
41 | // Needed for Deref | ||
42 | pub(crate) fn target() -> Name { | ||
43 | Name::new("Target".into()) | ||
44 | } | ||
45 | |||
46 | // There's should be no way to extract a string out of `Name`: `Name` in the | 41 | // There's should be no way to extract a string out of `Name`: `Name` in the |
47 | // future, `Name` will include hygiene information, and you can't encode | 42 | // future, `Name` will include hygiene information, and you can't encode |
48 | // hygiene into a String. | 43 | // hygiene into a String. |
@@ -123,6 +118,7 @@ pub(crate) const FUTURE_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, | |||
123 | pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); | 118 | pub(crate) const RESULT_MOD: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"result")); |
124 | pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); | 119 | pub(crate) const RESULT_TYPE: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Result")); |
125 | pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); | 120 | pub(crate) const OUTPUT: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Output")); |
121 | pub(crate) const TARGET: Name = Name::new(SmolStr::new_inline_from_ascii(6, b"Target")); | ||
126 | 122 | ||
127 | fn resolve_name(text: &SmolStr) -> SmolStr { | 123 | fn resolve_name(text: &SmolStr) -> SmolStr { |
128 | let raw_start = "r#"; | 124 | let raw_start = "r#"; |
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index 08f52a53b..caa17f64e 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -8,7 +8,7 @@ use std::iter::successors; | |||
8 | use log::{info, warn}; | 8 | use log::{info, warn}; |
9 | 9 | ||
10 | use super::{traits::Solution, Canonical, Ty, TypeWalk}; | 10 | use super::{traits::Solution, Canonical, Ty, TypeWalk}; |
11 | use crate::{HasGenericParams, HirDatabase, Name, Resolver}; | 11 | use crate::{name, HasGenericParams, HirDatabase, Resolver}; |
12 | 12 | ||
13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
14 | 14 | ||
@@ -42,7 +42,7 @@ fn deref_by_trait( | |||
42 | crate::lang_item::LangItemTarget::Trait(t) => t, | 42 | crate::lang_item::LangItemTarget::Trait(t) => t, |
43 | _ => return None, | 43 | _ => return None, |
44 | }; | 44 | }; |
45 | let target = deref_trait.associated_type_by_name(db, Name::target())?; | 45 | let target = deref_trait.associated_type_by_name(db, &name::TARGET)?; |
46 | 46 | ||
47 | if target.generic_params(db).count_params_including_parent() != 1 { | 47 | if target.generic_params(db).count_params_including_parent() != 1 { |
48 | // the Target type + Deref trait should only have one generic parameter, | 48 | // the Target type + Deref trait should only have one generic parameter, |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index ec3b7ffef..0e6ebd365 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -1453,7 +1453,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1453 | 1453 | ||
1454 | match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() { | 1454 | match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() { |
1455 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | 1455 | PerNs { types: Some(Def(Trait(trait_))), .. } => { |
1456 | Some(trait_.associated_type_by_name(self.db, name::ITEM)?) | 1456 | Some(trait_.associated_type_by_name(self.db, &name::ITEM)?) |
1457 | } | 1457 | } |
1458 | _ => None, | 1458 | _ => None, |
1459 | } | 1459 | } |
@@ -1471,7 +1471,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1471 | 1471 | ||
1472 | match self.resolver.resolve_path_segments(self.db, &ops_try_path).into_fully_resolved() { | 1472 | match self.resolver.resolve_path_segments(self.db, &ops_try_path).into_fully_resolved() { |
1473 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | 1473 | PerNs { types: Some(Def(Trait(trait_))), .. } => { |
1474 | Some(trait_.associated_type_by_name(self.db, name::OK)?) | 1474 | Some(trait_.associated_type_by_name(self.db, &name::OK)?) |
1475 | } | 1475 | } |
1476 | _ => None, | 1476 | _ => None, |
1477 | } | 1477 | } |
@@ -1493,7 +1493,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1493 | .into_fully_resolved() | 1493 | .into_fully_resolved() |
1494 | { | 1494 | { |
1495 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | 1495 | PerNs { types: Some(Def(Trait(trait_))), .. } => { |
1496 | Some(trait_.associated_type_by_name(self.db, name::OUTPUT)?) | 1496 | Some(trait_.associated_type_by_name(self.db, &name::OUTPUT)?) |
1497 | } | 1497 | } |
1498 | _ => None, | 1498 | _ => None, |
1499 | } | 1499 | } |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index f6f0137cf..480bae740 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -132,14 +132,16 @@ impl Ty { | |||
132 | if let Some(remaining_index) = remaining_index { | 132 | if let Some(remaining_index) = remaining_index { |
133 | if remaining_index == path.segments.len() - 1 { | 133 | if remaining_index == path.segments.len() - 1 { |
134 | let segment = &path.segments[remaining_index]; | 134 | let segment = &path.segments[remaining_index]; |
135 | let associated_ty = | 135 | let associated_ty = match trait_ref |
136 | match trait_ref.trait_.associated_type_by_name(db, segment.name.clone()) { | 136 | .trait_ |
137 | Some(t) => t, | 137 | .associated_type_by_name_including_super_traits(db, &segment.name) |
138 | None => { | 138 | { |
139 | // associated type not found | 139 | Some(t) => t, |
140 | return Ty::Unknown; | 140 | None => { |
141 | } | 141 | // associated type not found |
142 | }; | 142 | return Ty::Unknown; |
143 | } | ||
144 | }; | ||
143 | // FIXME handle type parameters on the segment | 145 | // FIXME handle type parameters on the segment |
144 | Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs }) | 146 | Ty::Projection(ProjectionTy { associated_ty, parameters: trait_ref.substs }) |
145 | } else { | 147 | } else { |
@@ -387,10 +389,11 @@ fn assoc_type_bindings_from_type_bound<'a>( | |||
387 | .flat_map(|segment| segment.args_and_bindings.iter()) | 389 | .flat_map(|segment| segment.args_and_bindings.iter()) |
388 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) | 390 | .flat_map(|args_and_bindings| args_and_bindings.bindings.iter()) |
389 | .map(move |(name, type_ref)| { | 391 | .map(move |(name, type_ref)| { |
390 | let associated_ty = match trait_ref.trait_.associated_type_by_name(db, name.clone()) { | 392 | let associated_ty = |
391 | None => return GenericPredicate::Error, | 393 | match trait_ref.trait_.associated_type_by_name_including_super_traits(db, &name) { |
392 | Some(t) => t, | 394 | None => return GenericPredicate::Error, |
393 | }; | 395 | Some(t) => t, |
396 | }; | ||
394 | let projection_ty = | 397 | let projection_ty = |
395 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; | 398 | ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() }; |
396 | let ty = Ty::from_hir(db, resolver, type_ref); | 399 | let ty = Ty::from_hir(db, resolver, type_ref); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index cb5540cb6..17c4e3556 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3720,11 +3720,11 @@ fn test() { | |||
3720 | [157; 160) '{t}': T | 3720 | [157; 160) '{t}': T |
3721 | [158; 159) 't': T | 3721 | [158; 159) 't': T |
3722 | [259; 280) '{ ...S)); }': () | 3722 | [259; 280) '{ ...S)); }': () |
3723 | [265; 269) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U | 3723 | [265; 269) 'get2': fn get2<u64, S<u64>>(T) -> U |
3724 | [265; 277) 'get2(set(S))': {unknown} | 3724 | [265; 277) 'get2(set(S))': u64 |
3725 | [270; 273) 'set': fn set<S<{unknown}>>(T) -> T | 3725 | [270; 273) 'set': fn set<S<u64>>(T) -> T |
3726 | [270; 276) 'set(S)': S<{unknown}> | 3726 | [270; 276) 'set(S)': S<u64> |
3727 | [274; 275) 'S': S<{unknown}> | 3727 | [274; 275) 'S': S<u64> |
3728 | "### | 3728 | "### |
3729 | ); | 3729 | ); |
3730 | } | 3730 | } |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index c201c5e50..cfe0cab16 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -636,7 +636,7 @@ pub(crate) fn impl_datum_query( | |||
636 | _ => None, | 636 | _ => None, |
637 | }) | 637 | }) |
638 | .filter_map(|t| { | 638 | .filter_map(|t| { |
639 | let assoc_ty = trait_.associated_type_by_name(db, t.name(db))?; | 639 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; |
640 | let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars); | 640 | let ty = db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars); |
641 | Some(chalk_rust_ir::AssociatedTyValue { | 641 | Some(chalk_rust_ir::AssociatedTyValue { |
642 | impl_id, | 642 | impl_id, |
diff --git a/crates/ra_hir/src/type_ref.rs b/crates/ra_hir/src/type_ref.rs index fa91bfb22..bc8acc7ee 100644 --- a/crates/ra_hir/src/type_ref.rs +++ b/crates/ra_hir/src/type_ref.rs | |||
@@ -150,4 +150,11 @@ impl TypeBound { | |||
150 | ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error, | 150 | ast::TypeBoundKind::ForType(_) | ast::TypeBoundKind::Lifetime(_) => TypeBound::Error, |
151 | } | 151 | } |
152 | } | 152 | } |
153 | |||
154 | pub fn as_path(&self) -> Option<&Path> { | ||
155 | match self { | ||
156 | TypeBound::Path(p) => Some(p), | ||
157 | _ => None, | ||
158 | } | ||
159 | } | ||
153 | } | 160 | } |