diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 86 |
1 files changed, 50 insertions, 36 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 092977e93..b96dc126c 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -91,7 +91,14 @@ pub enum TypeParamLoweringMode { | |||
91 | 91 | ||
92 | impl Ty { | 92 | impl Ty { |
93 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { | 93 | pub fn from_hir(ctx: &TyLoweringContext<'_, impl HirDatabase>, type_ref: &TypeRef) -> Self { |
94 | match type_ref { | 94 | Ty::from_hir_ext(ctx, type_ref).0 |
95 | } | ||
96 | pub fn from_hir_ext( | ||
97 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | ||
98 | type_ref: &TypeRef, | ||
99 | ) -> (Self, Option<TypeNs>) { | ||
100 | let mut res = None; | ||
101 | let ty = match type_ref { | ||
95 | TypeRef::Never => Ty::simple(TypeCtor::Never), | 102 | TypeRef::Never => Ty::simple(TypeCtor::Never), |
96 | TypeRef::Tuple(inner) => { | 103 | TypeRef::Tuple(inner) => { |
97 | let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); | 104 | let inner_tys: Arc<[Ty]> = inner.iter().map(|tr| Ty::from_hir(ctx, tr)).collect(); |
@@ -100,7 +107,11 @@ impl Ty { | |||
100 | Substs(inner_tys), | 107 | Substs(inner_tys), |
101 | ) | 108 | ) |
102 | } | 109 | } |
103 | TypeRef::Path(path) => Ty::from_hir_path(ctx, path), | 110 | TypeRef::Path(path) => { |
111 | let (ty, res_) = Ty::from_hir_path(ctx, path); | ||
112 | res = res_; | ||
113 | ty | ||
114 | } | ||
104 | TypeRef::RawPtr(inner, mutability) => { | 115 | TypeRef::RawPtr(inner, mutability) => { |
105 | let inner_ty = Ty::from_hir(ctx, inner); | 116 | let inner_ty = Ty::from_hir(ctx, inner); |
106 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) | 117 | Ty::apply_one(TypeCtor::RawPtr(*mutability), inner_ty) |
@@ -183,7 +194,8 @@ impl Ty { | |||
183 | } | 194 | } |
184 | } | 195 | } |
185 | TypeRef::Error => Ty::Unknown, | 196 | TypeRef::Error => Ty::Unknown, |
186 | } | 197 | }; |
198 | (ty, res) | ||
187 | } | 199 | } |
188 | 200 | ||
189 | /// This is only for `generic_predicates_for_param`, where we can't just | 201 | /// This is only for `generic_predicates_for_param`, where we can't just |
@@ -217,17 +229,19 @@ impl Ty { | |||
217 | pub(crate) fn from_type_relative_path( | 229 | pub(crate) fn from_type_relative_path( |
218 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | 230 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
219 | ty: Ty, | 231 | ty: Ty, |
232 | // We need the original resolution to lower `Self::AssocTy` correctly | ||
233 | res: Option<TypeNs>, | ||
220 | remaining_segments: PathSegments<'_>, | 234 | remaining_segments: PathSegments<'_>, |
221 | ) -> Ty { | 235 | ) -> (Ty, Option<TypeNs>) { |
222 | if remaining_segments.len() == 1 { | 236 | if remaining_segments.len() == 1 { |
223 | // resolve unselected assoc types | 237 | // resolve unselected assoc types |
224 | let segment = remaining_segments.first().unwrap(); | 238 | let segment = remaining_segments.first().unwrap(); |
225 | Ty::select_associated_type(ctx, ty, segment) | 239 | (Ty::select_associated_type(ctx, ty, res, segment), None) |
226 | } else if remaining_segments.len() > 1 { | 240 | } else if remaining_segments.len() > 1 { |
227 | // FIXME report error (ambiguous associated type) | 241 | // FIXME report error (ambiguous associated type) |
228 | Ty::Unknown | 242 | (Ty::Unknown, None) |
229 | } else { | 243 | } else { |
230 | ty | 244 | (ty, res) |
231 | } | 245 | } |
232 | } | 246 | } |
233 | 247 | ||
@@ -236,14 +250,14 @@ impl Ty { | |||
236 | resolution: TypeNs, | 250 | resolution: TypeNs, |
237 | resolved_segment: PathSegment<'_>, | 251 | resolved_segment: PathSegment<'_>, |
238 | remaining_segments: PathSegments<'_>, | 252 | remaining_segments: PathSegments<'_>, |
239 | ) -> Ty { | 253 | ) -> (Ty, Option<TypeNs>) { |
240 | let ty = match resolution { | 254 | let ty = match resolution { |
241 | TypeNs::TraitId(trait_) => { | 255 | TypeNs::TraitId(trait_) => { |
242 | // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there | 256 | // if this is a bare dyn Trait, we'll directly put the required ^0 for the self type in there |
243 | let self_ty = if remaining_segments.len() == 0 { Some(Ty::Bound(0)) } else { None }; | 257 | let self_ty = if remaining_segments.len() == 0 { Some(Ty::Bound(0)) } else { None }; |
244 | let trait_ref = | 258 | let trait_ref = |
245 | TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); | 259 | TraitRef::from_resolved_path(ctx, trait_, resolved_segment, self_ty); |
246 | return if remaining_segments.len() == 1 { | 260 | let ty = if remaining_segments.len() == 1 { |
247 | let segment = remaining_segments.first().unwrap(); | 261 | let segment = remaining_segments.first().unwrap(); |
248 | let associated_ty = associated_type_by_name_including_super_traits( | 262 | let associated_ty = associated_type_by_name_including_super_traits( |
249 | ctx.db, | 263 | ctx.db, |
@@ -269,6 +283,7 @@ impl Ty { | |||
269 | } else { | 283 | } else { |
270 | Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) | 284 | Ty::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) |
271 | }; | 285 | }; |
286 | return (ty, None); | ||
272 | } | 287 | } |
273 | TypeNs::GenericParam(param_id) => { | 288 | TypeNs::GenericParam(param_id) => { |
274 | let generics = | 289 | let generics = |
@@ -306,22 +321,25 @@ impl Ty { | |||
306 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 321 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
307 | TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 322 | TypeNs::TypeAliasId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
308 | // FIXME: report error | 323 | // FIXME: report error |
309 | TypeNs::EnumVariantId(_) => return Ty::Unknown, | 324 | TypeNs::EnumVariantId(_) => return (Ty::Unknown, None), |
310 | }; | 325 | }; |
311 | 326 | ||
312 | Ty::from_type_relative_path(ctx, ty, remaining_segments) | 327 | Ty::from_type_relative_path(ctx, ty, Some(resolution), remaining_segments) |
313 | } | 328 | } |
314 | 329 | ||
315 | pub(crate) fn from_hir_path(ctx: &TyLoweringContext<'_, impl HirDatabase>, path: &Path) -> Ty { | 330 | pub(crate) fn from_hir_path( |
331 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | ||
332 | path: &Path, | ||
333 | ) -> (Ty, Option<TypeNs>) { | ||
316 | // Resolve the path (in type namespace) | 334 | // Resolve the path (in type namespace) |
317 | if let Some(type_ref) = path.type_anchor() { | 335 | if let Some(type_ref) = path.type_anchor() { |
318 | let ty = Ty::from_hir(ctx, &type_ref); | 336 | let (ty, res) = Ty::from_hir_ext(ctx, &type_ref); |
319 | return Ty::from_type_relative_path(ctx, ty, path.segments()); | 337 | return Ty::from_type_relative_path(ctx, ty, res, path.segments()); |
320 | } | 338 | } |
321 | let (resolution, remaining_index) = | 339 | let (resolution, remaining_index) = |
322 | match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { | 340 | match ctx.resolver.resolve_path_in_type_ns(ctx.db, path.mod_path()) { |
323 | Some(it) => it, | 341 | Some(it) => it, |
324 | None => return Ty::Unknown, | 342 | None => return (Ty::Unknown, None), |
325 | }; | 343 | }; |
326 | let (resolved_segment, remaining_segments) = match remaining_index { | 344 | let (resolved_segment, remaining_segments) = match remaining_index { |
327 | None => ( | 345 | None => ( |
@@ -336,31 +354,27 @@ impl Ty { | |||
336 | fn select_associated_type( | 354 | fn select_associated_type( |
337 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | 355 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
338 | self_ty: Ty, | 356 | self_ty: Ty, |
357 | res: Option<TypeNs>, | ||
339 | segment: PathSegment<'_>, | 358 | segment: PathSegment<'_>, |
340 | ) -> Ty { | 359 | ) -> Ty { |
341 | let def = match ctx.resolver.generic_def() { | 360 | let traits_from_env: Vec<_> = match res { |
342 | Some(def) => def, | 361 | Some(TypeNs::SelfType(impl_id)) => match ctx.db.impl_trait(impl_id) { |
343 | None => return Ty::Unknown, // this can't actually happen | 362 | None => return Ty::Unknown, |
344 | }; | 363 | Some(trait_ref) => vec![trait_ref.value.trait_], |
345 | let param_id = match self_ty { | 364 | }, |
346 | Ty::Placeholder(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id, | 365 | Some(TypeNs::GenericParam(param_id)) => { |
347 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => { | 366 | let predicates = ctx.db.generic_predicates_for_param(param_id); |
348 | let generics = generics(ctx.db, def); | 367 | predicates |
349 | let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) { | 368 | .iter() |
350 | id | 369 | .filter_map(|pred| match &pred.value { |
351 | } else { | 370 | GenericPredicate::Implemented(tr) => Some(tr.trait_), |
352 | return Ty::Unknown; | 371 | _ => None, |
353 | }; | 372 | }) |
354 | param_id | 373 | .collect() |
355 | } | 374 | } |
356 | _ => return Ty::Unknown, // Error: Ambiguous associated type | 375 | _ => return Ty::Unknown, |
357 | }; | 376 | }; |
358 | let predicates = ctx.db.generic_predicates_for_param(param_id); | 377 | let traits = traits_from_env.into_iter().flat_map(|t| all_super_traits(ctx.db, t)); |
359 | let traits_from_env = predicates.iter().filter_map(|pred| match &pred.value { | ||
360 | GenericPredicate::Implemented(tr) => Some(tr.trait_), | ||
361 | _ => None, | ||
362 | }); | ||
363 | let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); | ||
364 | for t in traits { | 378 | for t in traits { |
365 | if let Some(associated_ty) = ctx.db.trait_data(t).associated_type_by_name(&segment.name) | 379 | if let Some(associated_ty) = ctx.db.trait_data(t).associated_type_by_name(&segment.name) |
366 | { | 380 | { |