]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve-0.80.0/src/logging_db/id_collector.rs
New upstream version 1.66.0+dfsg1
[rustc.git] / vendor / chalk-solve-0.80.0 / src / logging_db / id_collector.rs
CommitLineData
3dfed10e
XL
1use super::RecordedItemId;
2use crate::RustIrDatabase;
3use chalk_ir::{
4 interner::Interner,
a2a8927a 5 visit::Visitor,
3dfed10e 6 visit::{SuperVisit, Visit},
29967ef6 7 AliasTy, DebruijnIndex, TyKind, WhereClause,
3dfed10e 8};
a2a8927a 9use std::ops::ControlFlow;
3dfed10e 10
5099ac24
FG
11use indexmap::IndexSet;
12
3dfed10e
XL
13/// Collects the identifiers needed to resolve all the names for a given
14/// set of identifers, excluding identifiers we already have.
15///
16/// When recording identifiers to print, the `LoggingRustIrDatabase` only
17/// records identifiers the solver uses. But the solver assumes well-formedness,
18/// and thus skips over many names referenced in the definitions.
19///
20/// For instance, if we have:
21///
22/// ```rust,ignore
23/// struct S {}
24///
25/// trait Parent {}
26/// trait Child where Self: Parent {}
27/// impl Parent for S {}
28/// impl Child for S {}
29/// ```
30///
31/// And our goal is `S: Child`, we will only render `S`, `impl Child for S`, and
32/// `trait Child`. This will not parse because the `Child` trait's definition
33/// references parent. IdCollector solves this by collecting all of the directly
34/// related identifiers, allowing those to be rendered as well, ensuring name
35/// resolution is successful.
5e7ed085
FG
36pub fn collect_unrecorded_ids<I: Interner, DB: RustIrDatabase<I>>(
37 db: &DB,
5099ac24
FG
38 identifiers: &'_ IndexSet<RecordedItemId<I>>,
39) -> IndexSet<RecordedItemId<I>> {
3dfed10e
XL
40 let mut collector = IdCollector {
41 db,
5099ac24 42 found_identifiers: IndexSet::new(),
3dfed10e
XL
43 };
44 for id in identifiers {
45 match *id {
46 RecordedItemId::Adt(adt_id) => {
47 collector
48 .db
49 .adt_datum(adt_id)
50 .visit_with(&mut collector, DebruijnIndex::INNERMOST);
51 }
52 RecordedItemId::FnDef(fn_def) => {
53 collector
54 .db
55 .fn_def_datum(fn_def)
56 .visit_with(&mut collector, DebruijnIndex::INNERMOST);
57 }
29967ef6 58 RecordedItemId::Generator(_generator_id) => unimplemented!(),
3dfed10e
XL
59 RecordedItemId::Trait(trait_id) => {
60 let trait_datum = collector.db.trait_datum(trait_id);
61
62 trait_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
63 for assoc_ty_id in &trait_datum.associated_ty_ids {
64 let assoc_ty_datum = collector.db.associated_ty_data(*assoc_ty_id);
65 assoc_ty_datum
66 .bounds_on_self(collector.db.interner())
67 .visit_with(&mut collector, DebruijnIndex::INNERMOST);
5869c6ff 68 assoc_ty_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
3dfed10e
XL
69 }
70 }
71 RecordedItemId::OpaqueTy(opaque_id) => {
72 collector
73 .db
74 .opaque_ty_data(opaque_id)
75 .visit_with(&mut collector, DebruijnIndex::INNERMOST);
76 collector
77 .db
78 .hidden_opaque_type(opaque_id)
79 .visit_with(&mut collector, DebruijnIndex::INNERMOST);
80 }
81 RecordedItemId::Impl(impl_id) => {
82 let impl_datum = collector.db.impl_datum(impl_id);
83 for id in &impl_datum.associated_ty_value_ids {
84 let assoc_ty_value = collector.db.associated_ty_value(*id);
85 assoc_ty_value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
86 }
87 impl_datum.visit_with(&mut collector, DebruijnIndex::INNERMOST);
88 }
89 }
90 }
91 collector
92 .found_identifiers
93 .difference(identifiers)
94 .copied()
95 .collect()
96}
97
98struct IdCollector<'i, I: Interner, DB: RustIrDatabase<I>> {
99 db: &'i DB,
5099ac24 100 found_identifiers: IndexSet<RecordedItemId<I>>,
3dfed10e
XL
101}
102
103impl<'i, I: Interner, DB: RustIrDatabase<I>> IdCollector<'i, I, DB> {
104 fn record(&mut self, id: impl Into<RecordedItemId<I>>) {
105 self.found_identifiers.insert(id.into());
106 }
a2a8927a
XL
107
108 fn visit_alias(&mut self, alias: &AliasTy<I>) {
109 match alias {
110 AliasTy::Projection(projection_ty) => {
111 let assoc_ty_datum = self.db.associated_ty_data(projection_ty.associated_ty_id);
112 self.record(assoc_ty_datum.trait_id)
113 }
114 AliasTy::Opaque(opaque_ty) => self.record(opaque_ty.opaque_ty_id),
115 }
116 }
3dfed10e
XL
117}
118
a2a8927a 119impl<'i, I: Interner, DB: RustIrDatabase<I>> Visitor<I> for IdCollector<'i, I, DB> {
5869c6ff
XL
120 type BreakTy = ();
121
a2a8927a 122 fn as_dyn(&mut self) -> &mut dyn Visitor<I, BreakTy = Self::BreakTy> {
3dfed10e
XL
123 self
124 }
a2a8927a 125 fn interner(&self) -> I {
3dfed10e
XL
126 self.db.interner()
127 }
128
129 fn visit_ty(
130 &mut self,
131 ty: &chalk_ir::Ty<I>,
132 outer_binder: chalk_ir::DebruijnIndex,
5869c6ff 133 ) -> ControlFlow<()> {
29967ef6
XL
134 match ty.kind(self.db.interner()) {
135 TyKind::Adt(adt, _) => self.record(*adt),
136 TyKind::FnDef(fn_def, _) => self.record(*fn_def),
137 TyKind::OpaqueType(opaque, _) => self.record(*opaque),
5e7ed085 138 TyKind::Alias(alias) => self.visit_alias(alias),
29967ef6
XL
139 TyKind::BoundVar(..) => (),
140 TyKind::Dyn(..) => (),
141 TyKind::Function(..) => (),
142 TyKind::InferenceVar(..) => (),
143 TyKind::Placeholder(..) => (),
144 _ => {}
3dfed10e
XL
145 }
146 ty.super_visit_with(self, outer_binder)
147 }
148
149 fn visit_where_clause(
150 &mut self,
151 where_clause: &WhereClause<I>,
152 outer_binder: DebruijnIndex,
5869c6ff 153 ) -> ControlFlow<()> {
3dfed10e
XL
154 match where_clause {
155 WhereClause::Implemented(trait_ref) => self.record(trait_ref.trait_id),
a2a8927a 156 WhereClause::AliasEq(alias_eq) => self.visit_alias(&alias_eq.alias),
3dfed10e
XL
157 WhereClause::LifetimeOutlives(_lifetime_outlives) => (),
158 WhereClause::TypeOutlives(_type_outlives) => (),
159 }
160 where_clause.super_visit_with(self.as_dyn(), outer_binder)
161 }
162}