diff options
Diffstat (limited to 'crates/ra_hir_ty')
-rw-r--r-- | crates/ra_hir_ty/src/db.rs | 13 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/diagnostics.rs | 10 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/method_resolution.rs | 203 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/traits/chalk.rs | 10 |
5 files changed, 140 insertions, 120 deletions
diff --git a/crates/ra_hir_ty/src/db.rs b/crates/ra_hir_ty/src/db.rs index cad553273..dc06c0ee7 100644 --- a/crates/ra_hir_ty/src/db.rs +++ b/crates/ra_hir_ty/src/db.rs | |||
@@ -11,7 +11,7 @@ use ra_db::{impl_intern_key, salsa, CrateId, Upcast}; | |||
11 | use ra_prof::profile; | 11 | use ra_prof::profile; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{ |
14 | method_resolution::CrateImplDefs, | 14 | method_resolution::{InherentImpls, TraitImpls}, |
15 | traits::{chalk, AssocTyValue, Impl}, | 15 | traits::{chalk, AssocTyValue, Impl}, |
16 | Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, | 16 | Binders, CallableDef, GenericPredicate, InferenceResult, OpaqueTyId, PolyFnSig, |
17 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, | 17 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, TypeCtor, ValueTyDefId, |
@@ -67,11 +67,14 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
67 | #[salsa::invoke(crate::lower::generic_defaults_query)] | 67 | #[salsa::invoke(crate::lower::generic_defaults_query)] |
68 | fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; | 68 | fn generic_defaults(&self, def: GenericDefId) -> Arc<[Binders<Ty>]>; |
69 | 69 | ||
70 | #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_in_crate_query)] | 70 | #[salsa::invoke(InherentImpls::inherent_impls_in_crate_query)] |
71 | fn impls_in_crate(&self, krate: CrateId) -> Arc<CrateImplDefs>; | 71 | fn inherent_impls_in_crate(&self, krate: CrateId) -> Arc<InherentImpls>; |
72 | 72 | ||
73 | #[salsa::invoke(crate::method_resolution::CrateImplDefs::impls_from_deps_query)] | 73 | #[salsa::invoke(TraitImpls::trait_impls_in_crate_query)] |
74 | fn impls_from_deps(&self, krate: CrateId) -> Arc<CrateImplDefs>; | 74 | fn trait_impls_in_crate(&self, krate: CrateId) -> Arc<TraitImpls>; |
75 | |||
76 | #[salsa::invoke(TraitImpls::trait_impls_in_deps_query)] | ||
77 | fn trait_impls_in_deps(&self, krate: CrateId) -> Arc<TraitImpls>; | ||
75 | 78 | ||
76 | // Interned IDs for Chalk integration | 79 | // Interned IDs for Chalk integration |
77 | #[salsa::interned] | 80 | #[salsa::interned] |
diff --git a/crates/ra_hir_ty/src/diagnostics.rs b/crates/ra_hir_ty/src/diagnostics.rs index a59efb347..0289911de 100644 --- a/crates/ra_hir_ty/src/diagnostics.rs +++ b/crates/ra_hir_ty/src/diagnostics.rs | |||
@@ -32,7 +32,7 @@ impl Diagnostic for NoSuchField { | |||
32 | impl AstDiagnostic for NoSuchField { | 32 | impl AstDiagnostic for NoSuchField { |
33 | type AST = ast::RecordField; | 33 | type AST = ast::RecordField; |
34 | 34 | ||
35 | fn ast(&self, db: &impl AstDatabase) -> Self::AST { | 35 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { |
36 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | 36 | let root = db.parse_or_expand(self.source().file_id).unwrap(); |
37 | let node = self.source().value.to_node(&root); | 37 | let node = self.source().value.to_node(&root); |
38 | ast::RecordField::cast(node).unwrap() | 38 | ast::RecordField::cast(node).unwrap() |
@@ -65,7 +65,7 @@ impl Diagnostic for MissingFields { | |||
65 | impl AstDiagnostic for MissingFields { | 65 | impl AstDiagnostic for MissingFields { |
66 | type AST = ast::RecordFieldList; | 66 | type AST = ast::RecordFieldList; |
67 | 67 | ||
68 | fn ast(&self, db: &impl AstDatabase) -> Self::AST { | 68 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { |
69 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | 69 | let root = db.parse_or_expand(self.source().file_id).unwrap(); |
70 | let node = self.source().value.to_node(&root); | 70 | let node = self.source().value.to_node(&root); |
71 | ast::RecordFieldList::cast(node).unwrap() | 71 | ast::RecordFieldList::cast(node).unwrap() |
@@ -135,7 +135,7 @@ impl Diagnostic for MissingOkInTailExpr { | |||
135 | impl AstDiagnostic for MissingOkInTailExpr { | 135 | impl AstDiagnostic for MissingOkInTailExpr { |
136 | type AST = ast::Expr; | 136 | type AST = ast::Expr; |
137 | 137 | ||
138 | fn ast(&self, db: &impl AstDatabase) -> Self::AST { | 138 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { |
139 | let root = db.parse_or_expand(self.file).unwrap(); | 139 | let root = db.parse_or_expand(self.file).unwrap(); |
140 | let node = self.source().value.to_node(&root); | 140 | let node = self.source().value.to_node(&root); |
141 | ast::Expr::cast(node).unwrap() | 141 | ast::Expr::cast(node).unwrap() |
@@ -163,7 +163,7 @@ impl Diagnostic for BreakOutsideOfLoop { | |||
163 | impl AstDiagnostic for BreakOutsideOfLoop { | 163 | impl AstDiagnostic for BreakOutsideOfLoop { |
164 | type AST = ast::Expr; | 164 | type AST = ast::Expr; |
165 | 165 | ||
166 | fn ast(&self, db: &impl AstDatabase) -> Self::AST { | 166 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { |
167 | let root = db.parse_or_expand(self.file).unwrap(); | 167 | let root = db.parse_or_expand(self.file).unwrap(); |
168 | let node = self.source().value.to_node(&root); | 168 | let node = self.source().value.to_node(&root); |
169 | ast::Expr::cast(node).unwrap() | 169 | ast::Expr::cast(node).unwrap() |
@@ -191,7 +191,7 @@ impl Diagnostic for MissingUnsafe { | |||
191 | impl AstDiagnostic for MissingUnsafe { | 191 | impl AstDiagnostic for MissingUnsafe { |
192 | type AST = ast::Expr; | 192 | type AST = ast::Expr; |
193 | 193 | ||
194 | fn ast(&self, db: &impl AstDatabase) -> Self::AST { | 194 | fn ast(&self, db: &dyn AstDatabase) -> Self::AST { |
195 | let root = db.parse_or_expand(self.source().file_id).unwrap(); | 195 | let root = db.parse_or_expand(self.source().file_id).unwrap(); |
196 | let node = self.source().value.to_node(&root); | 196 | let node = self.source().value.to_node(&root); |
197 | ast::Expr::cast(node).unwrap() | 197 | ast::Expr::cast(node).unwrap() |
diff --git a/crates/ra_hir_ty/src/method_resolution.rs b/crates/ra_hir_ty/src/method_resolution.rs index c3edd6885..a45febbf7 100644 --- a/crates/ra_hir_ty/src/method_resolution.rs +++ b/crates/ra_hir_ty/src/method_resolution.rs | |||
@@ -39,136 +39,131 @@ impl TyFingerprint { | |||
39 | } | 39 | } |
40 | } | 40 | } |
41 | 41 | ||
42 | /// A queryable and mergeable collection of impls. | 42 | /// Trait impls defined or available in some crate. |
43 | #[derive(Debug, PartialEq, Eq)] | 43 | #[derive(Debug, Eq, PartialEq)] |
44 | pub struct CrateImplDefs { | 44 | pub struct TraitImpls { |
45 | inherent_impls: FxHashMap<TyFingerprint, Vec<ImplId>>, | 45 | // If the `Option<TyFingerprint>` is `None`, the impl may apply to any self type. |
46 | impls_by_trait: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, | 46 | map: FxHashMap<TraitId, FxHashMap<Option<TyFingerprint>, Vec<ImplId>>>, |
47 | } | 47 | } |
48 | 48 | ||
49 | impl CrateImplDefs { | 49 | impl TraitImpls { |
50 | pub(crate) fn impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<CrateImplDefs> { | 50 | pub(crate) fn trait_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
51 | let _p = profile("impls_in_crate_query"); | 51 | let _p = profile("trait_impls_in_crate_query"); |
52 | let mut res = CrateImplDefs { | 52 | let mut impls = Self { map: FxHashMap::default() }; |
53 | inherent_impls: FxHashMap::default(), | ||
54 | impls_by_trait: FxHashMap::default(), | ||
55 | }; | ||
56 | res.fill(db, krate); | ||
57 | 53 | ||
58 | Arc::new(res) | 54 | let crate_def_map = db.crate_def_map(krate); |
55 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
56 | for impl_id in module_data.scope.impls() { | ||
57 | let target_trait = match db.impl_trait(impl_id) { | ||
58 | Some(tr) => tr.value.trait_, | ||
59 | None => continue, | ||
60 | }; | ||
61 | let self_ty = db.impl_self_ty(impl_id); | ||
62 | let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); | ||
63 | impls | ||
64 | .map | ||
65 | .entry(target_trait) | ||
66 | .or_default() | ||
67 | .entry(self_ty_fp) | ||
68 | .or_default() | ||
69 | .push(impl_id); | ||
70 | } | ||
71 | } | ||
72 | |||
73 | Arc::new(impls) | ||
59 | } | 74 | } |
60 | 75 | ||
61 | /// Collects all impls from transitive dependencies of `krate` that may be used by `krate`. | 76 | pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { |
62 | /// | 77 | let _p = profile("trait_impls_in_deps_query"); |
63 | /// The full set of impls that can be used by `krate` is the returned map plus all the impls | ||
64 | /// from `krate` itself. | ||
65 | pub(crate) fn impls_from_deps_query( | ||
66 | db: &dyn HirDatabase, | ||
67 | krate: CrateId, | ||
68 | ) -> Arc<CrateImplDefs> { | ||
69 | let _p = profile("impls_from_deps_query"); | ||
70 | let crate_graph = db.crate_graph(); | 78 | let crate_graph = db.crate_graph(); |
71 | let mut res = CrateImplDefs { | 79 | let mut res = Self { map: FxHashMap::default() }; |
72 | inherent_impls: FxHashMap::default(), | ||
73 | impls_by_trait: FxHashMap::default(), | ||
74 | }; | ||
75 | 80 | ||
76 | // For each dependency, calculate `impls_from_deps` recursively, then add its own | 81 | for krate in crate_graph.transitive_deps(krate) { |
77 | // `impls_in_crate`. | 82 | res.merge(&db.trait_impls_in_crate(krate)); |
78 | // As we might visit crates multiple times, `merge` has to deduplicate impls to avoid | ||
79 | // wasting memory. | ||
80 | for dep in &crate_graph[krate].dependencies { | ||
81 | res.merge(&db.impls_from_deps(dep.crate_id)); | ||
82 | res.merge(&db.impls_in_crate(dep.crate_id)); | ||
83 | } | 83 | } |
84 | 84 | ||
85 | Arc::new(res) | 85 | Arc::new(res) |
86 | } | 86 | } |
87 | 87 | ||
88 | fn fill(&mut self, db: &dyn HirDatabase, krate: CrateId) { | ||
89 | let crate_def_map = db.crate_def_map(krate); | ||
90 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
91 | for impl_id in module_data.scope.impls() { | ||
92 | match db.impl_trait(impl_id) { | ||
93 | Some(tr) => { | ||
94 | let self_ty = db.impl_self_ty(impl_id); | ||
95 | let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); | ||
96 | self.impls_by_trait | ||
97 | .entry(tr.value.trait_) | ||
98 | .or_default() | ||
99 | .entry(self_ty_fp) | ||
100 | .or_default() | ||
101 | .push(impl_id); | ||
102 | } | ||
103 | None => { | ||
104 | let self_ty = db.impl_self_ty(impl_id); | ||
105 | if let Some(self_ty_fp) = TyFingerprint::for_impl(&self_ty.value) { | ||
106 | self.inherent_impls.entry(self_ty_fp).or_default().push(impl_id); | ||
107 | } | ||
108 | } | ||
109 | } | ||
110 | } | ||
111 | } | ||
112 | } | ||
113 | |||
114 | fn merge(&mut self, other: &Self) { | 88 | fn merge(&mut self, other: &Self) { |
115 | for (fp, impls) in &other.inherent_impls { | 89 | for (trait_, other_map) in &other.map { |
116 | let vec = self.inherent_impls.entry(*fp).or_default(); | 90 | let map = self.map.entry(*trait_).or_default(); |
117 | vec.extend(impls); | ||
118 | vec.sort(); | ||
119 | vec.dedup(); | ||
120 | } | ||
121 | |||
122 | for (trait_, other_map) in &other.impls_by_trait { | ||
123 | let map = self.impls_by_trait.entry(*trait_).or_default(); | ||
124 | for (fp, impls) in other_map { | 91 | for (fp, impls) in other_map { |
125 | let vec = map.entry(*fp).or_default(); | 92 | let vec = map.entry(*fp).or_default(); |
126 | vec.extend(impls); | 93 | vec.extend(impls); |
127 | vec.sort(); | ||
128 | vec.dedup(); | ||
129 | } | 94 | } |
130 | } | 95 | } |
131 | } | 96 | } |
132 | 97 | ||
133 | pub fn lookup_impl_defs(&self, ty: &Ty) -> impl Iterator<Item = ImplId> + '_ { | 98 | /// Queries all impls of the given trait. |
134 | let fingerprint = TyFingerprint::for_impl(ty); | 99 | pub fn for_trait(&self, trait_: TraitId) -> impl Iterator<Item = ImplId> + '_ { |
135 | fingerprint.and_then(|f| self.inherent_impls.get(&f)).into_iter().flatten().copied() | 100 | self.map |
136 | } | 101 | .get(&trait_) |
137 | |||
138 | pub fn lookup_impl_defs_for_trait(&self, tr: TraitId) -> impl Iterator<Item = ImplId> + '_ { | ||
139 | self.impls_by_trait | ||
140 | .get(&tr) | ||
141 | .into_iter() | 102 | .into_iter() |
142 | .flat_map(|m| m.values().flat_map(|v| v.iter().copied())) | 103 | .flat_map(|map| map.values().flat_map(|v| v.iter().copied())) |
143 | } | 104 | } |
144 | 105 | ||
145 | pub fn lookup_impl_defs_for_trait_and_ty( | 106 | /// Queries all impls of `trait_` that may apply to `self_ty`. |
107 | pub fn for_trait_and_self_ty( | ||
146 | &self, | 108 | &self, |
147 | tr: TraitId, | 109 | trait_: TraitId, |
148 | fp: TyFingerprint, | 110 | self_ty: TyFingerprint, |
149 | ) -> impl Iterator<Item = ImplId> + '_ { | 111 | ) -> impl Iterator<Item = ImplId> + '_ { |
150 | self.impls_by_trait | 112 | self.map |
151 | .get(&tr) | 113 | .get(&trait_) |
152 | .and_then(|m| m.get(&Some(fp))) | ||
153 | .into_iter() | 114 | .into_iter() |
154 | .flatten() | 115 | .flat_map(move |map| map.get(&None).into_iter().chain(map.get(&Some(self_ty)))) |
155 | .copied() | 116 | .flat_map(|v| v.iter().copied()) |
156 | .chain( | 117 | } |
157 | self.impls_by_trait | 118 | |
158 | .get(&tr) | 119 | pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ { |
159 | .and_then(|m| m.get(&None)) | 120 | self.map.values().flat_map(|map| map.values().flat_map(|v| v.iter().copied())) |
160 | .into_iter() | 121 | } |
161 | .flatten() | 122 | } |
162 | .copied(), | 123 | |
163 | ) | 124 | /// Inherent impls defined in some crate. |
125 | /// | ||
126 | /// Inherent impls can only be defined in the crate that also defines the self type of the impl | ||
127 | /// (note that some primitives are considered to be defined by both libcore and liballoc). | ||
128 | /// | ||
129 | /// This makes inherent impl lookup easier than trait impl lookup since we only have to consider a | ||
130 | /// single crate. | ||
131 | #[derive(Debug, Eq, PartialEq)] | ||
132 | pub struct InherentImpls { | ||
133 | map: FxHashMap<TyFingerprint, Vec<ImplId>>, | ||
134 | } | ||
135 | |||
136 | impl InherentImpls { | ||
137 | pub(crate) fn inherent_impls_in_crate_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { | ||
138 | let mut map: FxHashMap<_, Vec<_>> = FxHashMap::default(); | ||
139 | |||
140 | let crate_def_map = db.crate_def_map(krate); | ||
141 | for (_module_id, module_data) in crate_def_map.modules.iter() { | ||
142 | for impl_id in module_data.scope.impls() { | ||
143 | let data = db.impl_data(impl_id); | ||
144 | if data.target_trait.is_some() { | ||
145 | continue; | ||
146 | } | ||
147 | |||
148 | let self_ty = db.impl_self_ty(impl_id); | ||
149 | if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) { | ||
150 | map.entry(fp).or_default().push(impl_id); | ||
151 | } | ||
152 | } | ||
153 | } | ||
154 | |||
155 | Arc::new(Self { map }) | ||
156 | } | ||
157 | |||
158 | pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { | ||
159 | match TyFingerprint::for_impl(self_ty) { | ||
160 | Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), | ||
161 | None => &[], | ||
162 | } | ||
164 | } | 163 | } |
165 | 164 | ||
166 | pub fn all_impls<'a>(&'a self) -> impl Iterator<Item = ImplId> + 'a { | 165 | pub fn all_impls(&self) -> impl Iterator<Item = ImplId> + '_ { |
167 | self.inherent_impls | 166 | self.map.values().flat_map(|v| v.iter().copied()) |
168 | .values() | ||
169 | .chain(self.impls_by_trait.values().flat_map(|m| m.values())) | ||
170 | .flatten() | ||
171 | .copied() | ||
172 | } | 167 | } |
173 | } | 168 | } |
174 | 169 | ||
@@ -525,9 +520,9 @@ fn iterate_inherent_methods( | |||
525 | None => return false, | 520 | None => return false, |
526 | }; | 521 | }; |
527 | for krate in def_crates { | 522 | for krate in def_crates { |
528 | let impls = db.impls_in_crate(krate); | 523 | let impls = db.inherent_impls_in_crate(krate); |
529 | 524 | ||
530 | for impl_def in impls.lookup_impl_defs(&self_ty.value) { | 525 | for &impl_def in impls.for_self_ty(&self_ty.value) { |
531 | for &item in db.impl_data(impl_def).items.iter() { | 526 | for &item in db.impl_data(impl_def).items.iter() { |
532 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { | 527 | if !is_valid_candidate(db, name, receiver_ty, item, self_ty) { |
533 | continue; | 528 | continue; |
diff --git a/crates/ra_hir_ty/src/tests.rs b/crates/ra_hir_ty/src/tests.rs index 9084c3bed..eeac34d14 100644 --- a/crates/ra_hir_ty/src/tests.rs +++ b/crates/ra_hir_ty/src/tests.rs | |||
@@ -508,6 +508,30 @@ fn no_such_field_with_feature_flag_diagnostics_on_struct_fields() { | |||
508 | } | 508 | } |
509 | 509 | ||
510 | #[test] | 510 | #[test] |
511 | fn no_such_field_with_type_macro() { | ||
512 | let diagnostics = TestDB::with_files( | ||
513 | r" | ||
514 | macro_rules! Type { | ||
515 | () => { u32 }; | ||
516 | } | ||
517 | |||
518 | struct Foo { | ||
519 | bar: Type![], | ||
520 | } | ||
521 | impl Foo { | ||
522 | fn new() -> Self { | ||
523 | Foo { bar: 0 } | ||
524 | } | ||
525 | } | ||
526 | ", | ||
527 | ) | ||
528 | .diagnostics() | ||
529 | .0; | ||
530 | |||
531 | assert_snapshot!(diagnostics, @r###""###); | ||
532 | } | ||
533 | |||
534 | #[test] | ||
511 | fn missing_record_pat_field_diagnostic() { | 535 | fn missing_record_pat_field_diagnostic() { |
512 | let diagnostics = TestDB::with_files( | 536 | let diagnostics = TestDB::with_files( |
513 | r" | 537 | r" |
diff --git a/crates/ra_hir_ty/src/traits/chalk.rs b/crates/ra_hir_ty/src/traits/chalk.rs index 8ef4941c0..c97b81d57 100644 --- a/crates/ra_hir_ty/src/traits/chalk.rs +++ b/crates/ra_hir_ty/src/traits/chalk.rs | |||
@@ -77,8 +77,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
77 | // Note: Since we're using impls_for_trait, only impls where the trait | 77 | // Note: Since we're using impls_for_trait, only impls where the trait |
78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that | 78 | // can be resolved should ever reach Chalk. `impl_datum` relies on that |
79 | // and will panic if the trait can't be resolved. | 79 | // and will panic if the trait can't be resolved. |
80 | let in_deps = self.db.impls_from_deps(self.krate); | 80 | let in_deps = self.db.trait_impls_in_deps(self.krate); |
81 | let in_self = self.db.impls_in_crate(self.krate); | 81 | let in_self = self.db.trait_impls_in_crate(self.krate); |
82 | let impl_maps = [in_deps, in_self]; | 82 | let impl_maps = [in_deps, in_self]; |
83 | 83 | ||
84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); | 84 | let id_to_chalk = |id: hir_def::ImplId| Impl::ImplDef(id).to_chalk(self.db); |
@@ -87,14 +87,12 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
87 | Some(fp) => impl_maps | 87 | Some(fp) => impl_maps |
88 | .iter() | 88 | .iter() |
89 | .flat_map(|crate_impl_defs| { | 89 | .flat_map(|crate_impl_defs| { |
90 | crate_impl_defs.lookup_impl_defs_for_trait_and_ty(trait_, fp).map(id_to_chalk) | 90 | crate_impl_defs.for_trait_and_self_ty(trait_, fp).map(id_to_chalk) |
91 | }) | 91 | }) |
92 | .collect(), | 92 | .collect(), |
93 | None => impl_maps | 93 | None => impl_maps |
94 | .iter() | 94 | .iter() |
95 | .flat_map(|crate_impl_defs| { | 95 | .flat_map(|crate_impl_defs| crate_impl_defs.for_trait(trait_).map(id_to_chalk)) |
96 | crate_impl_defs.lookup_impl_defs_for_trait(trait_).map(id_to_chalk) | ||
97 | }) | ||
98 | .collect(), | 96 | .collect(), |
99 | }; | 97 | }; |
100 | 98 | ||