diff options
author | Florian Diebold <[email protected]> | 2020-01-31 14:57:44 +0000 |
---|---|---|
committer | Florian Diebold <[email protected]> | 2020-02-07 17:28:10 +0000 |
commit | 33aa2f8e4f2b9c7c3a6b28427cb6d6f2aef7b802 (patch) | |
tree | 4d6186c81d4d99ca610d52ce9abf62bd0bed4f75 /crates/ra_hir_ty | |
parent | 4a8279a21ad75ae2cb6d96746b8a880038ec0455 (diff) |
Fix assoc type selection
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/lower.rs | 69 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/traits.rs | 6 |
2 files changed, 43 insertions, 32 deletions
diff --git a/crates/ra_hir_ty/src/lower.rs b/crates/ra_hir_ty/src/lower.rs index f1a11e073..5138019c7 100644 --- a/crates/ra_hir_ty/src/lower.rs +++ b/crates/ra_hir_ty/src/lower.rs | |||
@@ -10,7 +10,7 @@ use std::sync::Arc; | |||
10 | 10 | ||
11 | use hir_def::{ | 11 | use hir_def::{ |
12 | builtin_type::BuiltinType, | 12 | builtin_type::BuiltinType, |
13 | generics::{WherePredicateTarget, WherePredicate}, | 13 | generics::{WherePredicate, WherePredicateTarget}, |
14 | path::{GenericArg, Path, PathSegment, PathSegments}, | 14 | path::{GenericArg, Path, PathSegment, PathSegments}, |
15 | resolver::{HasResolver, Resolver, TypeNs}, | 15 | resolver::{HasResolver, Resolver, TypeNs}, |
16 | type_ref::{TypeBound, TypeRef}, | 16 | type_ref::{TypeBound, TypeRef}, |
@@ -27,8 +27,8 @@ use crate::{ | |||
27 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, | 27 | all_super_traits, associated_type_by_name_including_super_traits, generics, make_mut_slice, |
28 | variant_data, | 28 | variant_data, |
29 | }, | 29 | }, |
30 | FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitEnvironment, TraitRef, | 30 | Binders, FnSig, GenericPredicate, PolyFnSig, ProjectionPredicate, ProjectionTy, Substs, |
31 | Ty, TypeCtor, PolyFnSig, Binders, | 31 | TraitEnvironment, TraitRef, Ty, TypeCtor, |
32 | }; | 32 | }; |
33 | 33 | ||
34 | #[derive(Debug)] | 34 | #[derive(Debug)] |
@@ -62,7 +62,7 @@ impl<'a, DB: HirDatabase> TyLoweringContext<'a, DB> { | |||
62 | } | 62 | } |
63 | } | 63 | } |
64 | 64 | ||
65 | #[derive(Copy, Clone, Debug)] | 65 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
66 | pub enum ImplTraitLoweringMode { | 66 | pub enum ImplTraitLoweringMode { |
67 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with | 67 | /// `impl Trait` gets lowered into an opaque type that doesn't unify with |
68 | /// anything except itself. This is used in places where values flow 'out', | 68 | /// anything except itself. This is used in places where values flow 'out', |
@@ -78,7 +78,7 @@ pub enum ImplTraitLoweringMode { | |||
78 | Disallowed, | 78 | Disallowed, |
79 | } | 79 | } |
80 | 80 | ||
81 | #[derive(Copy, Clone, Debug)] | 81 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] |
82 | pub enum TypeParamLoweringMode { | 82 | pub enum TypeParamLoweringMode { |
83 | Placeholder, | 83 | Placeholder, |
84 | Variable, | 84 | Variable, |
@@ -140,12 +140,13 @@ impl Ty { | |||
140 | ImplTraitLoweringMode::Variable => { | 140 | ImplTraitLoweringMode::Variable => { |
141 | let idx = ctx.impl_trait_counter.get(); | 141 | let idx = ctx.impl_trait_counter.get(); |
142 | ctx.impl_trait_counter.set(idx + 1); | 142 | ctx.impl_trait_counter.set(idx + 1); |
143 | let (self_params, list_params, _impl_trait_params) = if let Some(def) = ctx.resolver.generic_def() { | 143 | let (self_params, list_params, _impl_trait_params) = |
144 | let generics = generics(ctx.db, def); | 144 | if let Some(def) = ctx.resolver.generic_def() { |
145 | generics.provenance_split() | 145 | let generics = generics(ctx.db, def); |
146 | } else { | 146 | generics.provenance_split() |
147 | (0, 0, 0) | 147 | } else { |
148 | }; | 148 | (0, 0, 0) |
149 | }; | ||
149 | // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait | 150 | // assert!((idx as usize) < impl_trait_params); // TODO return position impl trait |
150 | Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) | 151 | Ty::Bound(idx as u32 + self_params as u32 + list_params as u32) |
151 | } | 152 | } |
@@ -251,7 +252,7 @@ impl Ty { | |||
251 | // FIXME: maybe return name in resolution? | 252 | // FIXME: maybe return name in resolution? |
252 | let name = generics.param_name(param_id); | 253 | let name = generics.param_name(param_id); |
253 | Ty::Param { idx, name } | 254 | Ty::Param { idx, name } |
254 | }, | 255 | } |
255 | TypeParamLoweringMode::Variable => Ty::Bound(idx), | 256 | TypeParamLoweringMode::Variable => Ty::Bound(idx), |
256 | } | 257 | } |
257 | } | 258 | } |
@@ -262,7 +263,7 @@ impl Ty { | |||
262 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 263 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), |
263 | }; | 264 | }; |
264 | ctx.db.impl_self_ty(impl_id).subst(&substs) | 265 | ctx.db.impl_self_ty(impl_id).subst(&substs) |
265 | }, | 266 | } |
266 | TypeNs::AdtSelfType(adt) => { | 267 | TypeNs::AdtSelfType(adt) => { |
267 | let generics = generics(ctx.db, adt.into()); | 268 | let generics = generics(ctx.db, adt.into()); |
268 | let substs = match ctx.type_param_mode { | 269 | let substs = match ctx.type_param_mode { |
@@ -270,7 +271,7 @@ impl Ty { | |||
270 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), | 271 | TypeParamLoweringMode::Variable => Substs::bound_vars(&generics), |
271 | }; | 272 | }; |
272 | ctx.db.ty(adt.into()).subst(&substs) | 273 | ctx.db.ty(adt.into()).subst(&substs) |
273 | }, | 274 | } |
274 | 275 | ||
275 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 276 | TypeNs::AdtId(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
276 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), | 277 | TypeNs::BuiltinType(it) => Ty::from_hir_path_inner(ctx, resolved_segment, it.into()), |
@@ -309,7 +310,8 @@ impl Ty { | |||
309 | segment: PathSegment<'_>, | 310 | segment: PathSegment<'_>, |
310 | ) -> Ty { | 311 | ) -> Ty { |
311 | let param_idx = match self_ty { | 312 | let param_idx = match self_ty { |
312 | Ty::Param { idx, .. } => idx, | 313 | Ty::Param { idx, .. } if ctx.type_param_mode == TypeParamLoweringMode::Placeholder => idx, |
314 | Ty::Bound(idx) if ctx.type_param_mode == TypeParamLoweringMode::Variable => idx, | ||
313 | _ => return Ty::Unknown, // Error: Ambiguous associated type | 315 | _ => return Ty::Unknown, // Error: Ambiguous associated type |
314 | }; | 316 | }; |
315 | let def = match ctx.resolver.generic_def() { | 317 | let def = match ctx.resolver.generic_def() { |
@@ -318,7 +320,14 @@ impl Ty { | |||
318 | }; | 320 | }; |
319 | let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); | 321 | let predicates = ctx.db.generic_predicates_for_param(def.into(), param_idx); |
320 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { | 322 | let traits_from_env = predicates.iter().filter_map(|pred| match pred { |
321 | GenericPredicate::Implemented(tr) if tr.self_ty() == &self_ty => Some(tr.trait_), | 323 | GenericPredicate::Implemented(tr) => { |
324 | if let Ty::Param { idx, .. } = tr.self_ty() { | ||
325 | if *idx == param_idx { | ||
326 | return Some(tr.trait_); | ||
327 | } | ||
328 | } | ||
329 | None | ||
330 | } | ||
322 | _ => None, | 331 | _ => None, |
323 | }); | 332 | }); |
324 | let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); | 333 | let traits = traits_from_env.flat_map(|t| all_super_traits(ctx.db, t)); |
@@ -516,10 +525,10 @@ impl GenericPredicate { | |||
516 | TypeParamLoweringMode::Placeholder => { | 525 | TypeParamLoweringMode::Placeholder => { |
517 | let name = generics.param_name(param_id); | 526 | let name = generics.param_name(param_id); |
518 | Ty::Param { idx, name } | 527 | Ty::Param { idx, name } |
519 | }, | 528 | } |
520 | TypeParamLoweringMode::Variable => Ty::Bound(idx), | 529 | TypeParamLoweringMode::Variable => Ty::Bound(idx), |
521 | } | 530 | } |
522 | }, | 531 | } |
523 | }; | 532 | }; |
524 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) | 533 | GenericPredicate::from_type_bound(ctx, &where_predicate.bound, self_ty) |
525 | } | 534 | } |
@@ -615,7 +624,9 @@ pub(crate) fn generic_predicates_for_param_query( | |||
615 | .where_predicates_in_scope() | 624 | .where_predicates_in_scope() |
616 | // we have to filter out all other predicates *first*, before attempting to lower them | 625 | // we have to filter out all other predicates *first*, before attempting to lower them |
617 | .filter(|pred| match &pred.target { | 626 | .filter(|pred| match &pred.target { |
618 | WherePredicateTarget::TypeRef(type_ref) => Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx), | 627 | WherePredicateTarget::TypeRef(type_ref) => { |
628 | Ty::from_hir_only_param(&ctx, type_ref) == Some(param_idx) | ||
629 | } | ||
619 | WherePredicateTarget::TypeParam(local_id) => { | 630 | WherePredicateTarget::TypeParam(local_id) => { |
620 | let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; | 631 | let param_id = hir_def::TypeParamId { parent: def, local_id: *local_id }; |
621 | let idx = generics.param_idx(param_id); | 632 | let idx = generics.param_idx(param_id); |
@@ -701,8 +712,8 @@ fn type_for_const(db: &impl HirDatabase, def: ConstId) -> Binders<Ty> { | |||
701 | let data = db.const_data(def); | 712 | let data = db.const_data(def); |
702 | let generics = generics(db, def.into()); | 713 | let generics = generics(db, def.into()); |
703 | let resolver = def.resolver(db); | 714 | let resolver = def.resolver(db); |
704 | let ctx = TyLoweringContext::new(db, &resolver) | 715 | let ctx = |
705 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 716 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
706 | 717 | ||
707 | Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) | 718 | Binders::new(generics.len(), Ty::from_hir(&ctx, &data.type_ref)) |
708 | } | 719 | } |
@@ -731,8 +742,8 @@ fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: StructId) -> PolyFn | |||
731 | let struct_data = db.struct_data(def.into()); | 742 | let struct_data = db.struct_data(def.into()); |
732 | let fields = struct_data.variant_data.fields(); | 743 | let fields = struct_data.variant_data.fields(); |
733 | let resolver = def.resolver(db); | 744 | let resolver = def.resolver(db); |
734 | let ctx = TyLoweringContext::new(db, &resolver) | 745 | let ctx = |
735 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 746 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
736 | let params = | 747 | let params = |
737 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 748 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
738 | let ret = type_for_adt(db, def.into()); | 749 | let ret = type_for_adt(db, def.into()); |
@@ -755,8 +766,8 @@ fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariantId | |||
755 | let var_data = &enum_data.variants[def.local_id]; | 766 | let var_data = &enum_data.variants[def.local_id]; |
756 | let fields = var_data.variant_data.fields(); | 767 | let fields = var_data.variant_data.fields(); |
757 | let resolver = def.parent.resolver(db); | 768 | let resolver = def.parent.resolver(db); |
758 | let ctx = TyLoweringContext::new(db, &resolver) | 769 | let ctx = |
759 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 770 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
760 | let params = | 771 | let params = |
761 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); | 772 | fields.iter().map(|(_, field)| Ty::from_hir(&ctx, &field.type_ref)).collect::<Vec<_>>(); |
762 | let ret = type_for_adt(db, def.parent.into()); | 773 | let ret = type_for_adt(db, def.parent.into()); |
@@ -784,8 +795,8 @@ fn type_for_adt(db: &impl HirDatabase, adt: AdtId) -> Binders<Ty> { | |||
784 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { | 795 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
785 | let generics = generics(db, t.into()); | 796 | let generics = generics(db, t.into()); |
786 | let resolver = t.resolver(db); | 797 | let resolver = t.resolver(db); |
787 | let ctx = TyLoweringContext::new(db, &resolver) | 798 | let ctx = |
788 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 799 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
789 | let type_ref = &db.type_alias_data(t).type_ref; | 800 | let type_ref = &db.type_alias_data(t).type_ref; |
790 | let substs = Substs::bound_vars(&generics); | 801 | let substs = Substs::bound_vars(&generics); |
791 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); | 802 | let inner = Ty::from_hir(&ctx, type_ref.as_ref().unwrap_or(&TypeRef::Error)); |
@@ -870,8 +881,8 @@ pub(crate) fn impl_self_ty_query(db: &impl HirDatabase, impl_id: ImplId) -> Bind | |||
870 | let impl_data = db.impl_data(impl_id); | 881 | let impl_data = db.impl_data(impl_id); |
871 | let resolver = impl_id.resolver(db); | 882 | let resolver = impl_id.resolver(db); |
872 | let generics = generics(db, impl_id.into()); | 883 | let generics = generics(db, impl_id.into()); |
873 | let ctx = TyLoweringContext::new(db, &resolver) | 884 | let ctx = |
874 | .with_type_param_mode(TypeParamLoweringMode::Variable); | 885 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
875 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) | 886 | Binders::new(generics.len(), Ty::from_hir(&ctx, &impl_data.target_type)) |
876 | } | 887 | } |
877 | 888 | ||
diff --git a/crates/ra_hir_ty/src/tests/traits.rs b/crates/ra_hir_ty/src/tests/traits.rs index 9ff396ad5..e2351ca98 100644 --- a/crates/ra_hir_ty/src/tests/traits.rs +++ b/crates/ra_hir_ty/src/tests/traits.rs | |||
@@ -358,15 +358,15 @@ fn test() { | |||
358 | [221; 223) '{}': () | 358 | [221; 223) '{}': () |
359 | [234; 300) '{ ...(S); }': () | 359 | [234; 300) '{ ...(S); }': () |
360 | [244; 245) 'x': u32 | 360 | [244; 245) 'x': u32 |
361 | [248; 252) 'foo1': fn foo1<S>(T) -> <T as Iterable>::Item | 361 | [248; 252) 'foo1': fn foo1<S>(S) -> <S as Iterable>::Item |
362 | [248; 255) 'foo1(S)': u32 | 362 | [248; 255) 'foo1(S)': u32 |
363 | [253; 254) 'S': S | 363 | [253; 254) 'S': S |
364 | [265; 266) 'y': u32 | 364 | [265; 266) 'y': u32 |
365 | [269; 273) 'foo2': fn foo2<S>(T) -> <T as Iterable>::Item | 365 | [269; 273) 'foo2': fn foo2<S>(S) -> <S as Iterable>::Item |
366 | [269; 276) 'foo2(S)': u32 | 366 | [269; 276) 'foo2(S)': u32 |
367 | [274; 275) 'S': S | 367 | [274; 275) 'S': S |
368 | [286; 287) 'z': u32 | 368 | [286; 287) 'z': u32 |
369 | [290; 294) 'foo3': fn foo3<S>(T) -> <T as Iterable>::Item | 369 | [290; 294) 'foo3': fn foo3<S>(S) -> <S as Iterable>::Item |
370 | [290; 297) 'foo3(S)': u32 | 370 | [290; 297) 'foo3(S)': u32 |
371 | [295; 296) 'S': S | 371 | [295; 296) 'S': S |
372 | "### | 372 | "### |