aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2020-01-31 14:57:44 +0000
committerFlorian Diebold <[email protected]>2020-02-07 17:28:10 +0000
commit33aa2f8e4f2b9c7c3a6b28427cb6d6f2aef7b802 (patch)
tree4d6186c81d4d99ca610d52ce9abf62bd0bed4f75 /crates
parent4a8279a21ad75ae2cb6d96746b8a880038ec0455 (diff)
Fix assoc type selection
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_ty/src/lower.rs69
-rw-r--r--crates/ra_hir_ty/src/tests/traits.rs6
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
11use hir_def::{ 11use 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)]
66pub enum ImplTraitLoweringMode { 66pub 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)]
82pub enum TypeParamLoweringMode { 82pub 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> {
784fn type_for_type_alias(db: &impl HirDatabase, t: TypeAliasId) -> Binders<Ty> { 795fn 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 "###