aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/lower.rs
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2019-09-17 22:16:28 +0100
committerGitHub <[email protected]>2019-09-17 22:16:28 +0100
commit54379ec6f8f82a470a275771e70825634d3d553b (patch)
tree498719aafe633f9eb9cb65ba65932076981e4632 /crates/ra_hir/src/ty/lower.rs
parentd505ee968b2a99eed65dfe7be27940ad9b2647c1 (diff)
parentc2f9558e1af8dbf73ff86eeffcb9ea6940947dd6 (diff)
Merge #1862
1862: Assoc item resolution refactoring (again) r=flodiebold a=flodiebold This is #1849, with the associated type selection code removed for now. Handling cycles there will need some more thought. 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.rs159
1 files changed, 103 insertions, 56 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 6ead3846a..a83842b0f 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -86,78 +86,125 @@ impl Ty {
86 } 86 }
87 } 87 }
88 88
89 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty { 89 pub(crate) fn from_type_relative_path(
90 // Resolve the path (in type namespace) 90 db: &impl HirDatabase,
91 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) { 91 resolver: &Resolver,
92 Some(it) => it, 92 ty: Ty,
93 None => return Ty::Unknown, 93 remaining_segments: &[PathSegment],
94 }; 94 ) -> Ty {
95 if remaining_segments.len() == 1 {
96 // resolve unselected assoc types
97 let segment = &remaining_segments[0];
98 Ty::select_associated_type(db, resolver, ty, segment)
99 } else if remaining_segments.len() > 1 {
100 // FIXME report error (ambiguous associated type)
101 Ty::Unknown
102 } else {
103 ty
104 }
105 }
95 106
96 let typable: TypableDef = match resolution { 107 pub(crate) fn from_partly_resolved_hir_path(
108 db: &impl HirDatabase,
109 resolver: &Resolver,
110 resolution: TypeNs,
111 resolved_segment: &PathSegment,
112 remaining_segments: &[PathSegment],
113 ) -> Ty {
114 let ty = match resolution {
97 TypeNs::Trait(trait_) => { 115 TypeNs::Trait(trait_) => {
98 let segment = match remaining_index { 116 let trait_ref =
99 None => path.segments.last().expect("resolved path has at least one element"), 117 TraitRef::from_resolved_path(db, resolver, trait_, resolved_segment, None);
100 Some(i) => &path.segments[i - 1], 118 return if remaining_segments.len() == 1 {
101 }; 119 let segment = &remaining_segments[0];
102 let trait_ref = TraitRef::from_resolved_path(db, resolver, trait_, segment, None); 120 match trait_ref
103 return if let Some(remaining_index) = remaining_index { 121 .trait_
104 if remaining_index == path.segments.len() - 1 { 122 .associated_type_by_name_including_super_traits(db, &segment.name)
105 let segment = &path.segments[remaining_index]; 123 {
106 match trait_ref 124 Some(associated_ty) => {
107 .trait_ 125 // FIXME handle type parameters on the segment
108 .associated_type_by_name_including_super_traits(db, &segment.name) 126 Ty::Projection(ProjectionTy {
109 { 127 associated_ty,
110 Some(associated_ty) => { 128 parameters: trait_ref.substs,
111 // FIXME handle type parameters on the segment 129 })
112 Ty::Projection(ProjectionTy { 130 }
113 associated_ty, 131 None => {
114 parameters: trait_ref.substs, 132 // FIXME: report error (associated type not found)
115 }) 133 Ty::Unknown
116 }
117 None => {
118 // associated type not found
119 Ty::Unknown
120 }
121 } 134 }
122 } else {
123 // FIXME more than one segment remaining, is this possible?
124 Ty::Unknown
125 } 135 }
136 } else if remaining_segments.len() > 1 {
137 // FIXME report error (ambiguous associated type)
138 Ty::Unknown
126 } else { 139 } else {
127 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) 140 Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)]))
128 }; 141 };
129 } 142 }
130 TypeNs::GenericParam(idx) => { 143 TypeNs::GenericParam(idx) => {
131 if remaining_index.is_some() { 144 // FIXME: maybe return name in resolution?
132 // e.g. T::Item 145 let name = resolved_segment.name.clone();
133 return Ty::Unknown; 146 Ty::Param { idx, name }
134 }
135 return Ty::Param {
136 idx,
137 // FIXME: maybe return name in resolution?
138 name: path
139 .as_ident()
140 .expect("generic param should be single-segment path")
141 .clone(),
142 };
143 }
144 TypeNs::SelfType(impl_block) => {
145 if remaining_index.is_some() {
146 // e.g. Self::Item
147 return Ty::Unknown;
148 }
149 return impl_block.target_ty(db);
150 } 147 }
148 TypeNs::SelfType(impl_block) => impl_block.target_ty(db),
151 149
152 TypeNs::Adt(it) => it.into(), 150 TypeNs::Adt(it) => Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into()),
153 TypeNs::BuiltinType(it) => it.into(), 151 TypeNs::BuiltinType(it) => {
154 TypeNs::TypeAlias(it) => it.into(), 152 Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into())
153 }
154 TypeNs::TypeAlias(it) => {
155 Ty::from_hir_path_inner(db, resolver, resolved_segment, it.into())
156 }
155 // FIXME: report error 157 // FIXME: report error
156 TypeNs::EnumVariant(_) => return Ty::Unknown, 158 TypeNs::EnumVariant(_) => return Ty::Unknown,
157 }; 159 };
158 160
161 Ty::from_type_relative_path(db, resolver, ty, remaining_segments)
162 }
163
164 pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Ty {
165 // Resolve the path (in type namespace)
166 if let crate::PathKind::Type(type_ref) = &path.kind {
167 let ty = Ty::from_hir(db, resolver, &type_ref);
168 let remaining_segments = &path.segments[..];
169 return Ty::from_type_relative_path(db, resolver, ty, remaining_segments);
170 }
171 let (resolution, remaining_index) = match resolver.resolve_path_in_type_ns(db, path) {
172 Some(it) => it,
173 None => return Ty::Unknown,
174 };
175 let (resolved_segment, remaining_segments) = match remaining_index {
176 None => (
177 path.segments.last().expect("resolved path has at least one element"),
178 &[] as &[PathSegment],
179 ),
180 Some(i) => (&path.segments[i - 1], &path.segments[i..]),
181 };
182 Ty::from_partly_resolved_hir_path(
183 db,
184 resolver,
185 resolution,
186 resolved_segment,
187 remaining_segments,
188 )
189 }
190
191 fn select_associated_type(
192 _db: &impl HirDatabase,
193 _resolver: &Resolver,
194 _self_ty: Ty,
195 _segment: &PathSegment,
196 ) -> Ty {
197 Ty::Unknown
198 }
199
200 fn from_hir_path_inner(
201 db: &impl HirDatabase,
202 resolver: &Resolver,
203 segment: &PathSegment,
204 typable: TypableDef,
205 ) -> Ty {
159 let ty = db.type_for_def(typable, Namespace::Types); 206 let ty = db.type_for_def(typable, Namespace::Types);
160 let substs = Ty::substs_from_path(db, resolver, path, typable); 207 let substs = Ty::substs_from_path_segment(db, resolver, segment, typable);
161 ty.subst(&substs) 208 ty.subst(&substs)
162 } 209 }
163 210