aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/lower.rs
diff options
context:
space:
mode:
authorbors[bot] <bors[bot]@users.noreply.github.com>2019-02-24 06:45:08 +0000
committerbors[bot] <bors[bot]@users.noreply.github.com>2019-02-24 06:45:08 +0000
commitc5e74cebdcbade069c0e1e81e298ab7d729e4cd5 (patch)
tree574d01f1f7532574ed22610341b3ac79da59d93f /crates/ra_hir/src/ty/lower.rs
parent1eef9fbefe44e919f6ddc7ce1c44625ffde6be1c (diff)
parent82fe7b77a3b4f49540ae1fc319bdd38afd73c877 (diff)
Merge #886
886: Associated method generics r=matklad a=flodiebold Refactor associated method resolution a bit and make it work with generics. Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r--crates/ra_hir/src/ty/lower.rs67
1 files changed, 41 insertions, 26 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index cc9e0fd40..63e13a30e 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -16,7 +16,7 @@ use crate::{
16 name::KnownName, 16 name::KnownName,
17 nameres::Namespace, 17 nameres::Namespace,
18 resolve::{Resolver, Resolution}, 18 resolve::{Resolver, Resolution},
19 path::GenericArg, 19 path::{ PathSegment, GenericArg},
20 generics::GenericParams, 20 generics::GenericParams,
21 adt::VariantDef, 21 adt::VariantDef,
22}; 22};
@@ -112,36 +112,18 @@ impl Ty {
112 ty.apply_substs(substs) 112 ty.apply_substs(substs)
113 } 113 }
114 114
115 /// Collect generic arguments from a path into a `Substs`. See also 115 pub(super) fn substs_from_path_segment(
116 /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
117 pub(super) fn substs_from_path(
118 db: &impl HirDatabase, 116 db: &impl HirDatabase,
119 resolver: &Resolver, 117 resolver: &Resolver,
120 path: &Path, 118 segment: &PathSegment,
121 resolved: TypableDef, 119 resolved: TypableDef,
122 ) -> Substs { 120 ) -> Substs {
123 let mut substs = Vec::new(); 121 let mut substs = Vec::new();
124 let last = path.segments.last().expect("path should have at least one segment"); 122 let def_generics = match resolved {
125 let (def_generics, segment) = match resolved { 123 TypableDef::Function(func) => func.generic_params(db),
126 TypableDef::Function(func) => (func.generic_params(db), last), 124 TypableDef::Struct(s) => s.generic_params(db),
127 TypableDef::Struct(s) => (s.generic_params(db), last), 125 TypableDef::Enum(e) => e.generic_params(db),
128 TypableDef::Enum(e) => (e.generic_params(db), last), 126 TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db),
129 TypableDef::EnumVariant(var) => {
130 // the generic args for an enum variant may be either specified
131 // on the segment referring to the enum, or on the segment
132 // referring to the variant. So `Option::<T>::None` and
133 // `Option::None::<T>` are both allowed (though the former is
134 // preferred). See also `def_ids_for_path_segments` in rustc.
135 let len = path.segments.len();
136 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
137 // Option::<T>::None
138 &path.segments[len - 2]
139 } else {
140 // Option::None::<T>
141 last
142 };
143 (var.parent_enum(db).generic_params(db), segment)
144 }
145 }; 127 };
146 let parent_param_count = def_generics.count_parent_params(); 128 let parent_param_count = def_generics.count_parent_params();
147 substs.extend((0..parent_param_count).map(|_| Ty::Unknown)); 129 substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
@@ -166,6 +148,39 @@ impl Ty {
166 assert_eq!(substs.len(), def_generics.count_params_including_parent()); 148 assert_eq!(substs.len(), def_generics.count_params_including_parent());
167 Substs(substs.into()) 149 Substs(substs.into())
168 } 150 }
151
152 /// Collect generic arguments from a path into a `Substs`. See also
153 /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
154 pub(super) fn substs_from_path(
155 db: &impl HirDatabase,
156 resolver: &Resolver,
157 path: &Path,
158 resolved: TypableDef,
159 ) -> Substs {
160 let last = path.segments.last().expect("path should have at least one segment");
161 let segment = match resolved {
162 TypableDef::Function(_) => last,
163 TypableDef::Struct(_) => last,
164 TypableDef::Enum(_) => last,
165 TypableDef::EnumVariant(_) => {
166 // the generic args for an enum variant may be either specified
167 // on the segment referring to the enum, or on the segment
168 // referring to the variant. So `Option::<T>::None` and
169 // `Option::None::<T>` are both allowed (though the former is
170 // preferred). See also `def_ids_for_path_segments` in rustc.
171 let len = path.segments.len();
172 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
173 // Option::<T>::None
174 &path.segments[len - 2]
175 } else {
176 // Option::None::<T>
177 last
178 };
179 segment
180 }
181 };
182 Ty::substs_from_path_segment(db, resolver, segment, resolved)
183 }
169} 184}
170 185
171/// Build the declared type of an item. This depends on the namespace; e.g. for 186/// Build the declared type of an item. This depends on the namespace; e.g. for