aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorLukas Wirth <[email protected]>2021-04-02 01:09:12 +0100
committerLukas Wirth <[email protected]>2021-04-02 15:40:31 +0100
commitc24753ae5d06edcb798d17ed8713ef02a3c3b164 (patch)
treeb644e1556eb480de912981acbfcaa4a9709c8675 /crates
parent5ef0c7a21387c219478754393bf9ac1b1cebf0d4 (diff)
Don't allocate in `associated_type_shorthand_candidates`
Diffstat (limited to 'crates')
-rw-r--r--crates/hir_ty/src/lower.rs69
1 files changed, 33 insertions, 36 deletions
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 14f34d73c..018621131 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -821,24 +821,38 @@ pub fn associated_type_shorthand_candidates<R>(
821 res: TypeNs, 821 res: TypeNs,
822 mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>, 822 mut cb: impl FnMut(&Name, &TraitRef, TypeAliasId) -> Option<R>,
823) -> Option<R> { 823) -> Option<R> {
824 let traits_from_env: Vec<_> = match res { 824 let mut search = |t| {
825 TypeNs::SelfType(impl_id) => match db.impl_trait(impl_id) { 825 for t in all_super_trait_refs(db, t) {
826 None => vec![], 826 let data = db.trait_data(t.hir_trait_id());
827 // FIXME: how to correctly handle higher-ranked bounds here? 827
828 Some(trait_ref) => vec![trait_ref.value.shift_bound_vars_out(DebruijnIndex::ONE)], 828 for (name, assoc_id) in &data.items {
829 }, 829 if let AssocItemId::TypeAliasId(alias) = assoc_id {
830 if let Some(result) = cb(name, &t, *alias) {
831 return Some(result);
832 }
833 }
834 }
835 }
836 None
837 };
838
839 match res {
840 // FIXME: how to correctly handle higher-ranked bounds here?
841 TypeNs::SelfType(impl_id) => {
842 search(db.impl_trait(impl_id)?.value.shift_bound_vars_out(DebruijnIndex::ONE))
843 }
830 TypeNs::GenericParam(param_id) => { 844 TypeNs::GenericParam(param_id) => {
831 let predicates = db.generic_predicates_for_param(param_id); 845 let predicates = db.generic_predicates_for_param(param_id);
832 let mut traits_: Vec<_> = predicates 846 let res = predicates.iter().find_map(|pred| match &pred.value.value {
833 .iter() 847 // FIXME: how to correctly handle higher-ranked bounds here?
834 .filter_map(|pred| match &pred.value.value { 848 WhereClause::Implemented(tr) => {
835 // FIXME: how to correctly handle higher-ranked bounds here? 849 search(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE))
836 WhereClause::Implemented(tr) => { 850 }
837 Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 851 _ => None,
838 } 852 });
839 _ => None, 853 if let res @ Some(_) = res {
840 }) 854 return res;
841 .collect(); 855 }
842 // Handle `Self::Type` referring to own associated type in trait definitions 856 // Handle `Self::Type` referring to own associated type in trait definitions
843 if let GenericDefId::TraitId(trait_id) = param_id.parent { 857 if let GenericDefId::TraitId(trait_id) = param_id.parent {
844 let generics = generics(db.upcast(), trait_id.into()); 858 let generics = generics(db.upcast(), trait_id.into());
@@ -849,30 +863,13 @@ pub fn associated_type_shorthand_candidates<R>(
849 trait_id: to_chalk_trait_id(trait_id), 863 trait_id: to_chalk_trait_id(trait_id),
850 substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), 864 substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST),
851 }; 865 };
852 traits_.push(trait_ref); 866 return search(trait_ref);
853 } 867 }
854 } 868 }
855 traits_ 869 None
856 }
857 _ => vec![],
858 };
859
860 for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) {
861 let data = db.trait_data(t.hir_trait_id());
862
863 for (name, assoc_id) in &data.items {
864 match assoc_id {
865 AssocItemId::TypeAliasId(alias) => {
866 if let Some(result) = cb(name, &t, *alias) {
867 return Some(result);
868 }
869 }
870 AssocItemId::FunctionId(_) | AssocItemId::ConstId(_) => {}
871 }
872 } 870 }
871 _ => None,
873 } 872 }
874
875 None
876} 873}
877 874
878/// Build the type of all specific fields of a struct or enum variant. 875/// Build the type of all specific fields of a struct or enum variant.