diff options
Diffstat (limited to 'crates/ra_hir_ty/src/lower.rs')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 108 |
1 files changed, 59 insertions, 49 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index 88d962b47..d60b59433 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -30,7 +30,7 @@ use crate::{ | |||
30 | Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, | 30 | Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, |
31 | TraitEnvironment, TraitRef, Ty, TypeCtor, | 31 | TraitEnvironment, TraitRef, Ty, TypeCtor, |
32 | }; | 32 | }; |
33 | use hir_expand::name::Name; | 33 | use hir_def::TypeParamId; |
34 | 34 | ||
35 | #[derive(Debug)] | 35 | #[derive(Debug)] |
36 | pub struct TyLoweringContext<'a, DB: HirDatabase> { | 36 | pub struct TyLoweringContext<'a, DB: HirDatabase> { |
@@ -145,7 +145,16 @@ impl Ty { | |||
145 | ImplTraitLoweringMode::Param => { | 145 | ImplTraitLoweringMode::Param => { |
146 | let idx = ctx.impl_trait_counter.get(); | 146 | let idx = ctx.impl_trait_counter.get(); |
147 | ctx.impl_trait_counter.set(idx + 1); | 147 | ctx.impl_trait_counter.set(idx + 1); |
148 | Ty::Param { idx: idx as u32, name: Name::missing() } | 148 | if let Some(def) = ctx.resolver.generic_def() { |
149 | let generics = generics(ctx.db, def); | ||
150 | let param = generics | ||
151 | .iter() | ||
152 | .nth(idx as usize) | ||
153 | .map_or(Ty::Unknown, |(id, _)| Ty::Param(id)); | ||
154 | param | ||
155 | } else { | ||
156 | Ty::Unknown | ||
157 | } | ||
149 | } | 158 | } |
150 | ImplTraitLoweringMode::Variable => { | 159 | ImplTraitLoweringMode::Variable => { |
151 | let idx = ctx.impl_trait_counter.get(); | 160 | let idx = ctx.impl_trait_counter.get(); |
@@ -176,7 +185,7 @@ impl Ty { | |||
176 | fn from_hir_only_param( | 185 | fn from_hir_only_param( |
177 | ctx: &TyLoweringContext<'_, impl HirDatabase>, | 186 | ctx: &TyLoweringContext<'_, impl HirDatabase>, |
178 | type_ref: &TypeRef, | 187 | type_ref: &TypeRef, |
179 | ) -> Option<u32> { | 188 | ) -> Option<TypeParamId> { |
180 | let path = match type_ref { | 189 | let path = match type_ref { |
181 | TypeRef::Path(path) => path, | 190 | TypeRef::Path(path) => path, |
182 | _ => return None, | 191 | _ => return None, |
@@ -192,9 +201,7 @@ impl Ty { | |||
192 | _ => return None, | 201 | _ => return None, |
193 | }; | 202 | }; |
194 | if let TypeNs::GenericParam(param_id) = resolution { | 203 | if let TypeNs::GenericParam(param_id) = resolution { |
195 | let generics = generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); | 204 | Some(param_id) |
196 | let idx = generics.param_idx(param_id); | ||
197 | Some(idx) | ||
198 | } else { | 205 | } else { |
199 | None | 206 | None |
200 | } | 207 | } |
@@ -256,20 +263,18 @@ impl Ty { | |||
256 | TypeNs::GenericParam(param_id) => { | 263 | TypeNs::GenericParam(param_id) => { |
257 | let generics = | 264 | let generics = |
258 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); | 265 | generics(ctx.db, ctx.resolver.generic_def().expect("generics in scope")); |
259 | let idx = generics.param_idx(param_id); | ||
260 | match ctx.type_param_mode { | 266 | match ctx.type_param_mode { |
261 | TypeParamLoweringMode::Placeholder => { | 267 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), |
262 | // FIXME: maybe return name in resolution? | 268 | TypeParamLoweringMode::Variable => { |
263 | let name = generics.param_name(param_id); | 269 | let idx = generics.param_idx(param_id).expect("matching generics"); |
264 | Ty::Param { idx, name } | 270 | Ty::Bound(idx) |
265 | } | 271 | } |
266 | TypeParamLoweringMode::Variable => Ty::Bound(idx), | ||
267 | } | 272 | } |
268 | } | 273 | } |
269 | TypeNs::SelfType(impl_id) => { | 274 | TypeNs::SelfType(impl_id) => { |
270 | let generics = generics(ctx.db, impl_id.into()); | 275 | let generics = generics(ctx.db, impl_id.into()); |
271 | let substs = match ctx.type_param_mode { | 276 | let substs = match ctx.type_param_mode { |
272 | TypeParamLoweringMode::Placeholder => Substs::identity(&generics), | 277 | TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), |
273 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 278 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), |
274 | }; | 279 | }; |
275 | ctx.db.impl_self_ty(impl_id).subst(&substs) | 280 | ctx.db.impl_self_ty(impl_id).subst(&substs) |
@@ -277,7 +282,7 @@ impl Ty { | |||
277 | TypeNs::AdtSelfType(adt) => { | 282 | TypeNs::AdtSelfType(adt) => { |
278 | let generics = generics(ctx.db, adt.into()); | 283 | let generics = generics(ctx.db, adt.into()); |
279 | let substs = match ctx.type_param_mode { | 284 | let substs = match ctx.type_param_mode { |
280 | TypeParamLoweringMode::Placeholder => Substs::identity(&generics), | 285 | TypeParamLoweringMode::Placeholder => Substs::type_params(&generics), |
281 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 286 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), |
282 | }; | 287 | }; |
283 | ctx.db.ty(adt.into()).subst(&substs) | 288 | ctx.db.ty(adt.into()).subst(&substs) |
@@ -319,20 +324,28 @@ impl Ty { | |||
319 | self_ty: Ty, | 324 | self_ty: Ty, |
320 | segment: PathSegment<'_>, | 325 | segment: PathSegment<'_>, |
321 | ) -> Ty { | 326 | ) -> Ty { |
322 | let param_idx = match self_ty { | ||
323 | Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx, | ||
324 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx, | ||
325 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
326 | }; | ||
327 | let def = match ctx.resolver.generic_def() { | 327 | let def = match ctx.resolver.generic_def() { |
328 | Some(def) => def, | 328 | Some(def) => def, |
329 | None => return Ty::Unknown, // this can't actually happen | 329 | None => return Ty::Unknown, // this can't actually happen |
330 | }; | 330 | }; |
331 | let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); | 331 | let param_id = match self_ty { |
332 | Ty::Param(id) if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => id, | ||
333 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => { | ||
334 | let generics = generics(ctx.db, def); | ||
335 | let param_id = if let Some((id, _)) = generics.iter().nth(idx as usize) { | ||
336 | id | ||
337 | } else { | ||
338 | return Ty::Unknown; | ||
339 | }; | ||
340 | param_id | ||
341 | }, | ||
342 | _ => return Ty::Unknown, // Error: Ambiguous associated type | ||
343 | }; | ||
344 | let predicates = ctx.db.generic_predicates_for_param(param_id); | ||
332 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { | 345 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { |
333 | GenericPredicate::Implemented(tr) => { | 346 | GenericPredicate::Implemented(tr) => { |
334 | if let Ty::Param { idx, .. } = tr.self_ty() { | 347 | if let Ty::Param(id) = tr.self_ty() { |
335 | if *idx == param_idx { | 348 | if *id == param_id { |
336 | return Some(tr.trait_); | 349 | return Some(tr.trait_); |
337 | } | 350 | } |
338 | } | 351 | } |
@@ -530,13 +543,12 @@ impl GenericPredicate { | |||
530 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); | 543 | let generic_def = ctx.resolver.generic_def().expect("generics in scope"); |
531 | let generics = generics(ctx.db, generic_def); | 544 | let generics = generics(ctx.db, generic_def); |
532 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; | 545 | let param_id = hir_def::TypeParamId { parent: generic_def, local_id: *param_id }; |
533 | let idx = generics.param_idx(param_id); | ||
534 | match ctx.type_param_mode { | 546 | match ctx.type_param_mode { |
535 | TypeParamLoweringMode::Placeholder => { | 547 | TypeParamLoweringMode::Placeholder => Ty::Param(param_id), |
536 | let name = generics.param_name(param_id); | 548 | TypeParamLoweringMode::Variable => { |
537 | Ty::Param { idx, name } | 549 | let idx = generics.param_idx(param_id).expect("matching generics"); |
550 | Ty::Bound(idx) | ||
538 | } | 551 | } |
539 | TypeParamLoweringMode::Variable => Ty::Bound(idx), | ||
540 | } | 552 | } |
541 | } | 553 | } |
542 | }; | 554 | }; |
@@ -599,17 +611,19 @@ pub fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> PolyFnSig { | |||
599 | pub(crate) fn field_types_query( | 611 | pub(crate) fn field_types_query( |
600 | db: &impl HirDatabase, | 612 | db: &impl HirDatabase, |
601 | variant_id: VariantId, | 613 | variant_id: VariantId, |
602 | ) -> Arc<ArenaMap<LocalStructFieldId, Ty>> { | 614 | ) -> Arc<ArenaMap<LocalStructFieldId, Binders<Ty>>> { |
603 | let var_data = variant_data(db, variant_id); | 615 | let var_data = variant_data(db, variant_id); |
604 | let resolver = match variant_id { | 616 | let (resolver, def): (_, GenericDefId) = match variant_id { |
605 | VariantId::StructId(it) => it.resolver(db), | 617 | VariantId::StructId(it) => (it.resolver(db), it.into()), |
606 | VariantId::UnionId(it) => it.resolver(db), | 618 | VariantId::UnionId(it) => (it.resolver(db), it.into()), |
607 | VariantId::EnumVariantId(it) => it.parent.resolver(db), | 619 | VariantId::EnumVariantId(it) => (it.parent.resolver(db), it.parent.into()), |
608 | }; | 620 | }; |
621 | let generics = generics(db, def); | ||
609 | let mut res = ArenaMap::default(); | 622 | let mut res = ArenaMap::default(); |
610 | let ctx = TyLoweringContext::new(db, &resolver); | 623 | let ctx = TyLoweringContext::new(db, &resolver) |
624 | .with_type_param_mode(TypeParamLoweringMode::Variable); | ||
611 | for (field_id, field_data) in var_data.fields().iter() { | 625 | for (field_id, field_data) in var_data.fields().iter() { |
612 | res.insert(field_id, Ty::from_hir(&ctx, &field_data.type_ref)) | 626 | res.insert(field_id, Binders::new(generics.len(), Ty::from_hir(&ctx, &field_data.type_ref))) |
613 | } | 627 | } |
614 | Arc::new(res) | 628 | Arc::new(res) |
615 | } | 629 | } |
@@ -624,23 +638,20 @@ pub(crate) fn field_types_query( | |||
624 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. | 638 | /// these are fine: `T: Foo<U::Item>, U: Foo<()>`. |
625 | pub(crate) fn generic_predicates_for_param_query( | 639 | pub(crate) fn generic_predicates_for_param_query( |
626 | db: &impl HirDatabase, | 640 | db: &impl HirDatabase, |
627 | def: GenericDefId, | 641 | param_id: TypeParamId, |
628 | param_idx: u32, | ||
629 | ) -> Arc<[GenericPredicate]> { | 642 | ) -> Arc<[GenericPredicate]> { |
630 | let resolver = def.resolver(db); | 643 | let resolver = param_id.parent.resolver(db); |
631 | let ctx = TyLoweringContext::new(db, &resolver); | 644 | let ctx = TyLoweringContext::new(db, &resolver); |
632 | let generics = generics(db, def); | 645 | // let generics = generics(db, def); |
633 | resolver | 646 | resolver |
634 | .where_predicates_in_scope() | 647 | .where_predicates_in_scope() |
635 | // we have to filter out all other predicates *first*, before attempting to lower them | 648 | // we have to filter out all other predicates *first*, before attempting to lower them |
636 | .filter(|pred| match &pred.target { | 649 | .filter(|pred| match &pred.target { |
637 | WherePredicateTarget::TypeRef(type_ref) => { | 650 | WherePredicateTarget::TypeRef(type_ref) => { |
638 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx) | 651 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_id) |
639 | } | 652 | } |
640 | WherePredicateTarget::TypeParam(local_id) => { | 653 | WherePredicateTarget::TypeParam(local_id) => { |
641 | let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; | 654 | *local_id == param_id.local_id |
642 | let idx = generics.param_idx(param_id); | ||
643 | idx == param_idx | ||
644 | } | 655 | } |
645 | }) | 656 | }) |
646 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) | 657 | .flat_map(|pred| GenericPredicate::from_where_predicate(&ctx, pred)) |
@@ -650,8 +661,7 @@ pub(crate) fn generic_predicates_for_param_query( | |||
650 | pub(crate) fn generic_predicates_for_param_recover( | 661 | pub(crate) fn generic_predicates_for_param_recover( |
651 | _db: &impl HirDatabase, | 662 | _db: &impl HirDatabase, |
652 | _cycle: &[String], | 663 | _cycle: &[String], |
653 | _def: &GenericDefId, | 664 | _param_id: &TypeParamId, |
654 | _param_idx: &u32, | ||
655 | ) -> Arc<[GenericPredicate]> { | 665 | ) -> Arc<[GenericPredicate]> { |
656 | Arc::new([]) | 666 | Arc::new([]) |
657 | } | 667 | } |
@@ -905,12 +915,12 @@ pub(crate) fn impl_self_ty_recover( | |||
905 | Binders::new(generics.len(), Ty::Unknown) | 915 | Binders::new(generics.len(), Ty::Unknown) |
906 | } | 916 | } |
907 | 917 | ||
908 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<TraitRef> { | 918 | pub(crate) fn impl_trait_query(db: &impl HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { |
909 | let impl_data = db.impl_data(impl_id); | 919 | let impl_data = db.impl_data(impl_id); |
910 | let resolver = impl_id.resolver(db); | 920 | let resolver = impl_id.resolver(db); |
911 | let generics = generics(db, impl_id.into()); | 921 | let ctx = TyLoweringContext::new(db, &resolver) |
912 | let ctx = TyLoweringContext::new(db, &resolver); | 922 | .with_type_param_mode(TypeParamLoweringMode::Variable); |
913 | let self_ty = db.impl_self_ty(impl_id).subst(&Substs::identity(&generics)); | 923 | let self_ty = db.impl_self_ty(impl_id); |
914 | let target_trait = impl_data.target_trait.as_ref()?; | 924 | let target_trait = impl_data.target_trait.as_ref()?; |
915 | TraitRef::from_hir(&ctx, target_trait, Some(self_ty.clone())) | 925 | Some(Binders::new(self_ty.num_binders, TraitRef::from_hir(&ctx, target_trait, Some(self_ty.value.clone()))?)) |
916 | } | 926 | } |