diff options
author | Lukas Wirth <[email protected]> | 2021-04-02 01:09:12 +0100 |
---|---|---|
committer | Lukas Wirth <[email protected]> | 2021-04-02 15:40:31 +0100 |
commit | c24753ae5d06edcb798d17ed8713ef02a3c3b164 (patch) | |
tree | b644e1556eb480de912981acbfcaa4a9709c8675 /crates | |
parent | 5ef0c7a21387c219478754393bf9ac1b1cebf0d4 (diff) |
Don't allocate in `associated_type_shorthand_candidates`
Diffstat (limited to 'crates')
-rw-r--r-- | crates/hir_ty/src/lower.rs | 69 |
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. |