aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2019-05-11 15:49:55 +0100
committerFlorian Diebold <[email protected]>2019-05-11 15:56:36 +0100
commitcbe75676b90d93e5b0ac461dce2d916cef4c0476 (patch)
tree50999df2191aa13204ca05f255ebe2b2105a1832 /crates/ra_hir
parentd6dc75f9f22b73faf8c526be69ca43e52d6db1bf (diff)
Add support for inline bounds
E.g. impl<T: Clone> Foo for T.
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/generics.rs43
-rw-r--r--crates/ra_hir/src/ty/tests.rs33
2 files changed, 60 insertions, 16 deletions
diff --git a/crates/ra_hir/src/generics.rs b/crates/ra_hir/src/generics.rs
index 826117ba5..c29b96f50 100644
--- a/crates/ra_hir/src/generics.rs
+++ b/crates/ra_hir/src/generics.rs
@@ -90,8 +90,17 @@ impl GenericParams {
90 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) { 90 fn fill_params(&mut self, params: &ast::TypeParamList, start: u32) {
91 for (idx, type_param) in params.type_params().enumerate() { 91 for (idx, type_param) in params.type_params().enumerate() {
92 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing); 92 let name = type_param.name().map(AsName::as_name).unwrap_or_else(Name::missing);
93 let param = GenericParam { idx: idx as u32 + start, name }; 93 let param = GenericParam { idx: idx as u32 + start, name: name.clone() };
94 self.params.push(param); 94 self.params.push(param);
95
96 let type_ref = TypeRef::Path(name.into());
97 for bound in type_param
98 .type_bound_list()
99 .iter()
100 .flat_map(|type_bound_list| type_bound_list.bounds())
101 {
102 self.add_where_predicate_from_bound(bound, type_ref.clone());
103 }
95 } 104 }
96 } 105 }
97 106
@@ -101,26 +110,28 @@ impl GenericParams {
101 Some(type_ref) => type_ref, 110 Some(type_ref) => type_ref,
102 None => continue, 111 None => continue,
103 }; 112 };
113 let type_ref = TypeRef::from_ast(type_ref);
104 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) { 114 for bound in pred.type_bound_list().iter().flat_map(|l| l.bounds()) {
105 let path = bound 115 self.add_where_predicate_from_bound(bound, type_ref.clone());
106 .type_ref()
107 .and_then(|tr| match tr.kind() {
108 ast::TypeRefKind::PathType(path) => path.path(),
109 _ => None,
110 })
111 .and_then(Path::from_ast);
112 let path = match path {
113 Some(p) => p,
114 None => continue,
115 };
116 self.where_predicates.push(WherePredicate {
117 type_ref: TypeRef::from_ast(type_ref),
118 trait_ref: path,
119 });
120 } 116 }
121 } 117 }
122 } 118 }
123 119
120 fn add_where_predicate_from_bound(&mut self, bound: &ast::TypeBound, type_ref: TypeRef) {
121 let path = bound
122 .type_ref()
123 .and_then(|tr| match tr.kind() {
124 ast::TypeRefKind::PathType(path) => path.path(),
125 _ => None,
126 })
127 .and_then(Path::from_ast);
128 let path = match path {
129 Some(p) => p,
130 None => return,
131 };
132 self.where_predicates.push(WherePredicate { type_ref, trait_ref: path });
133 }
134
124 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> { 135 pub(crate) fn find_by_name(&self, name: &Name) -> Option<&GenericParam> {
125 self.params.iter().find(|p| &p.name == name) 136 self.params.iter().find(|p| &p.name == name)
126 } 137 }
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index 6f8d8fa49..59c85daed 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2536,6 +2536,22 @@ fn test() { (&S).foo()<|>; }
2536} 2536}
2537 2537
2538#[test] 2538#[test]
2539fn method_resolution_where_clause_inline_not_met() {
2540 // The blanket impl shouldn't apply because we can't prove S: Clone
2541 let t = type_at(
2542 r#"
2543//- /main.rs
2544trait Clone {}
2545trait Trait { fn foo(self) -> u128; }
2546struct S;
2547impl<T: Clone> Trait for T {}
2548fn test() { (&S).foo()<|>; }
2549"#,
2550 );
2551 assert_eq!(t, "{unknown}");
2552}
2553
2554#[test]
2539fn method_resolution_where_clause_1() { 2555fn method_resolution_where_clause_1() {
2540 let t = type_at( 2556 let t = type_at(
2541 r#" 2557 r#"
@@ -2569,6 +2585,23 @@ fn test() { S2.into()<|>; }
2569} 2585}
2570 2586
2571#[test] 2587#[test]
2588fn method_resolution_where_clause_inline() {
2589 let t = type_at(
2590 r#"
2591//- /main.rs
2592trait Into<T> { fn into(self) -> T; }
2593trait From<T> { fn from(other: T) -> Self; }
2594struct S1;
2595struct S2;
2596impl From<S2> for S1 {};
2597impl<T, U: From<T>> Into<U> for T {}
2598fn test() { S2.into()<|>; }
2599"#,
2600 );
2601 assert_eq!(t, "S1");
2602}
2603
2604#[test]
2572fn method_resolution_encountering_fn_type() { 2605fn method_resolution_encountering_fn_type() {
2573 covers!(trait_resolution_on_fn_type); 2606 covers!(trait_resolution_on_fn_type);
2574 type_at( 2607 type_at(