]> git.proxmox.com Git - rustc.git/blame - vendor/chalk-solve/src/display.rs
New upstream version 1.51.0+dfsg1
[rustc.git] / vendor / chalk-solve / src / display.rs
CommitLineData
3dfed10e
XL
1use std::{
2 borrow::Borrow,
3 fmt::{Display, Result},
4 sync::Arc,
5};
6
7use crate::rust_ir::*;
8use chalk_ir::{interner::Interner, *};
9use itertools::Itertools;
10
11use crate::{logging_db::RecordedItemId, split::Split, RustIrDatabase};
12
13#[macro_use]
14mod utils;
15
16mod bounds;
17mod identifiers;
18mod items;
19mod render_trait;
20mod state;
21mod stub;
22mod ty;
23
24use self::render_trait::*;
25pub use self::state::*;
26pub use self::utils::sanitize_debug_name;
27
28use self::utils::as_display;
29
30fn write_item<F, I, T>(f: &mut F, ws: &InternalWriterState<'_, I>, v: &T) -> Result
31where
32 F: std::fmt::Write + ?Sized,
33 I: Interner,
34 T: RenderAsRust<I>,
35{
36 writeln!(f, "{}", v.display(ws))
37}
38
39/// Writes stubs for items which were referenced by name, but for which we
40/// didn't directly access. For instance, traits mentioned in where bounds which
41/// are only usually checked during well-formedness, when we weren't recording
42/// well-formedness.
43///
44/// The "stub" nature of this means it writes output with the right names and
45/// the right number of generics, but nothing else. Where clauses, bounds, and
46/// fields are skipped. Associated types are ???? skipped.
47///
48/// `RecordedItemId::Impl` is not supported.
49pub fn write_stub_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result
50where
51 F: std::fmt::Write + ?Sized,
52 I: Interner,
53 DB: RustIrDatabase<I>,
54 P: Borrow<DB>,
55 T: IntoIterator<Item = RecordedItemId<I>>,
56{
57 let wrapped_db = &ws.wrap_db_ref(|db| stub::StubWrapper::new(db.borrow()));
58
59 write_items(f, wrapped_db, ids)
60}
61
62/// Writes out each item recorded by a [`LoggingRustIrDatabase`].
63///
64/// [`LoggingRustIrDatabase`]: crate::logging_db::LoggingRustIrDatabase
65pub fn write_items<F, I, DB, P, T>(f: &mut F, ws: &WriterState<I, DB, P>, ids: T) -> Result
66where
67 F: std::fmt::Write + ?Sized,
68 I: Interner,
69 DB: RustIrDatabase<I>,
70 P: Borrow<DB>,
71 T: IntoIterator<Item = RecordedItemId<I>>,
72{
73 for id in ids {
74 match id {
75 RecordedItemId::Impl(id) => {
76 let v = ws.db().impl_datum(id);
77 write_item(f, &InternalWriterState::new(ws), &*v)?;
78 }
79 RecordedItemId::Adt(id) => {
80 let v = ws.db().adt_datum(id);
81 write_item(f, &InternalWriterState::new(ws), &*v)?;
82 }
83 RecordedItemId::Trait(id) => {
84 let v = ws.db().trait_datum(id);
85 write_item(f, &InternalWriterState::new(ws), &*v)?;
86 }
87 RecordedItemId::OpaqueTy(id) => {
88 let v = ws.db().opaque_ty_data(id);
89 write_item(f, &InternalWriterState::new(ws), &*v)?;
90 }
91 RecordedItemId::FnDef(id) => {
92 let v = ws.db().fn_def_datum(id);
93 write_item(f, &InternalWriterState::new(ws), &*v)?;
94 }
29967ef6
XL
95 RecordedItemId::Generator(id) => {
96 let generator = ws.db().generator_datum(id);
97 let witness = ws.db().generator_witness_datum(id);
98 write_item(f, &InternalWriterState::new(ws), &(&*generator, &*witness))?;
99 }
3dfed10e
XL
100 }
101 }
102 Ok(())
103}
104
105/// Displays a set of bounds, all targeting `Self`, as just the trait names,
106/// separated by `+`.
107///
108/// For example, a list of quantified where clauses which would normally be
109/// displayed as:
110///
111/// ```notrust
112/// Self: A, Self: B, Self: C
113/// ```
114///
115/// Is instead displayed by this function as:
116///
117/// ```notrust
118/// A + B + C
119/// ```
120///
121/// Shared between the `Trait` in `dyn Trait` and [`OpaqueTyDatum`] bounds.
122fn display_self_where_clauses_as_bounds<'a, I: Interner>(
123 s: &'a InternalWriterState<'a, I>,
124 bounds: &'a [QuantifiedWhereClause<I>],
125) -> impl Display + 'a {
126 as_display(move |f| {
127 let interner = s.db().interner();
128 write!(
129 f,
130 "{}",
131 bounds
132 .iter()
133 .map(|bound| {
134 as_display(|f| {
135 // each individual trait can have a forall
136 let s = &s.add_debrujin_index(None);
137 if !bound.binders.is_empty(interner) {
138 write!(
139 f,
140 "forall<{}> ",
141 s.binder_var_display(&bound.binders)
142 .collect::<Vec<_>>()
143 .join(", ")
144 )?;
145 }
146 match &bound.skip_binders() {
147 WhereClause::Implemented(trait_ref) => display_type_with_generics(
148 s,
149 trait_ref.trait_id,
150 &trait_ref.substitution.as_slice(interner)[1..],
151 )
152 .fmt(f),
153 WhereClause::AliasEq(alias_eq) => match &alias_eq.alias {
154 AliasTy::Projection(projection_ty) => {
155 let (assoc_ty_datum, trait_params, assoc_type_params) =
156 s.db().split_projection(&projection_ty);
157 display_trait_with_assoc_ty_value(
158 s,
159 assoc_ty_datum,
160 &trait_params[1..],
161 assoc_type_params,
162 &alias_eq.ty,
163 )
164 .fmt(f)
165 }
166 AliasTy::Opaque(_opaque) => todo!("opaque type AliasTy"),
167 },
168 WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f),
169 WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f),
170 }
171 })
172 .to_string()
173 })
174 .format(" + ")
175 )
176 })
177}
178
179/// Displays a type with its parameters - something like `AsRef<T>`,
180/// OpaqueTyName<U>, or `AdtName<Value>`.
181///
182/// This is shared between where bounds, OpaqueTy, & dyn Trait.
183fn display_type_with_generics<'a, I: Interner>(
184 s: &'a InternalWriterState<'a, I>,
185 trait_name: impl RenderAsRust<I> + 'a,
186 trait_params: impl IntoIterator<Item = &'a GenericArg<I>> + 'a,
187) -> impl Display + 'a {
188 use std::fmt::Write;
189 let trait_params = trait_params.into_iter().map(|param| param.display(s));
190 let mut trait_params_str = String::new();
191 write_joined_non_empty_list!(trait_params_str, "<{}>", trait_params, ", ").unwrap();
192 as_display(move |f| write!(f, "{}{}", trait_name.display(s), trait_params_str))
193}
194
195/// Displays a trait with its parameters and a single associated type -
196/// something like `IntoIterator<Item=T>`.
197///
198/// This is shared between where bounds & dyn Trait.
199fn display_trait_with_assoc_ty_value<'a, I: Interner>(
200 s: &'a InternalWriterState<'a, I>,
201 assoc_ty_datum: Arc<AssociatedTyDatum<I>>,
202 trait_params: &'a [GenericArg<I>],
203 assoc_ty_params: &'a [GenericArg<I>],
204 assoc_ty_value: &'a Ty<I>,
205) -> impl Display + 'a {
206 as_display(move |f| {
207 write!(f, "{}<", assoc_ty_datum.trait_id.display(s))?;
208 write_joined_non_empty_list!(
209 f,
210 "{}, ",
211 trait_params.iter().map(|param| param.display(s)),
212 ", "
213 )?;
214 write!(f, "{}", assoc_ty_datum.id.display(s))?;
215 write_joined_non_empty_list!(
216 f,
217 "<{}>",
218 assoc_ty_params.iter().map(|param| param.display(s)),
219 ", "
220 )?;
221 write!(f, "={}>", assoc_ty_value.display(s))?;
222 Ok(())
223 })
224}