]>
Commit | Line | Data |
---|---|---|
3dfed10e XL |
1 | //! Writer logic for types. |
2 | //! | |
29967ef6 | 3 | //! Contains the highly-recursive logic for writing `TyKind` and its variants. |
3dfed10e XL |
4 | use std::fmt::{Formatter, Result}; |
5 | ||
6 | use crate::split::Split; | |
7 | use chalk_ir::{interner::Interner, *}; | |
8 | use itertools::Itertools; | |
9 | ||
10 | use super::{ | |
11 | display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust, | |
12 | state::InternalWriterState, | |
13 | }; | |
14 | ||
29967ef6 | 15 | impl<I: Interner> RenderAsRust<I> for TyKind<I> { |
3dfed10e XL |
16 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { |
17 | let interner = s.db().interner(); | |
18 | match self { | |
29967ef6 XL |
19 | TyKind::Adt(sid, substitution) => { |
20 | write!(f, "{}", sid.display(s))?; | |
21 | let parameters = substitution.as_slice(interner); | |
22 | let parameters = parameters.iter().map(|param| param.display(s)); | |
23 | write_joined_non_empty_list!(f, "<{}>", parameters, ", ") | |
24 | } | |
25 | TyKind::AssociatedType(assoc_type_id, substitution) => { | |
26 | // (Iterator::Item)(x) | |
27 | // should be written in Rust as <X as Iterator>::Item | |
28 | let datum = s.db().associated_ty_data(*assoc_type_id); | |
29 | assert!( | |
30 | substitution | |
31 | .iter(interner) | |
32 | .filter_map(move |p| p.ty(interner)) | |
33 | .count() | |
34 | >= 1, | |
35 | "AssociatedType should have at least 1 parameter" | |
36 | ); | |
37 | write!( | |
38 | f, | |
39 | "<{} as {}>::{}", | |
40 | substitution | |
41 | .iter(interner) | |
42 | .filter_map(move |p| p.ty(interner)) | |
43 | .next() | |
44 | .unwrap() | |
45 | .display(s), | |
46 | datum.trait_id.display(s), | |
47 | datum.id.display(s), | |
48 | )?; | |
49 | let params = substitution.as_slice(interner); | |
50 | write_joined_non_empty_list!( | |
51 | f, | |
52 | "<{}>", | |
53 | params[1..].iter().map(|ty| ty.display(s)), | |
54 | "," | |
55 | ) | |
56 | } | |
57 | TyKind::Scalar(scalar) => write!(f, "{}", scalar.display(s)), | |
58 | TyKind::Tuple(arity, substitution) => { | |
59 | write!( | |
60 | f, | |
61 | "({}{})", | |
62 | substitution | |
63 | .as_slice(interner) | |
64 | .iter() | |
65 | .map(|p| p.display(s)) | |
66 | .format(", "), | |
67 | if *arity == 1 { | |
68 | // need trailing single comma | |
69 | "," | |
70 | } else { | |
71 | "" | |
72 | } | |
73 | ) | |
74 | } | |
75 | TyKind::OpaqueType(opaque_ty_id, substitution) => write!( | |
76 | f, | |
77 | "{}", | |
78 | display_type_with_generics(s, *opaque_ty_id, substitution.as_slice(interner)) | |
79 | ), | |
80 | TyKind::Raw(mutability, ty) => match mutability { | |
81 | Mutability::Mut => write!(f, "*mut {}", ty.display(s)), | |
82 | Mutability::Not => write!(f, "*const {}", ty.display(s)), | |
83 | }, | |
84 | TyKind::Ref(mutability, lifetime, ty) => match mutability { | |
85 | Mutability::Mut => write!(f, "&{} mut {}", lifetime.display(s), ty.display(s)), | |
86 | Mutability::Not => write!(f, "&{} {}", lifetime.display(s), ty.display(s)), | |
87 | }, | |
88 | TyKind::Str => write!(f, "str"), | |
89 | TyKind::Slice(ty) => write!(f, "[{}]", ty.display(s)), | |
90 | TyKind::Error => write!(f, "{{error}}"), | |
91 | TyKind::Never => write!(f, "!"), | |
92 | ||
93 | // FIXME: write out valid types for these variants | |
94 | TyKind::FnDef(..) => write!(f, "<fn_def>"), | |
95 | TyKind::Closure(..) => write!(f, "<closure>"), | |
96 | TyKind::Foreign(..) => write!(f, "<foreign>"), | |
97 | TyKind::Generator(..) => write!(f, "<generator>"), | |
98 | TyKind::GeneratorWitness(..) => write!(f, "<generator_witness>"), | |
99 | ||
100 | TyKind::Array(ty, const_) => write!(f, "[{}; {}]", ty.display(s), const_.display(s),), | |
101 | TyKind::Dyn(dyn_ty) => { | |
3dfed10e XL |
102 | // the lifetime needs to be outside of the bounds, so we |
103 | // introduce a new scope for the bounds | |
104 | { | |
105 | let s = &s.add_debrujin_index(None); | |
106 | // dyn_ty.bounds.binders creates a Self binding for the trait | |
107 | let bounds = dyn_ty.bounds.skip_binders(); | |
108 | ||
109 | write!( | |
110 | f, | |
111 | "dyn {}", | |
112 | display_self_where_clauses_as_bounds(s, bounds.as_slice(interner)), | |
113 | )?; | |
114 | } | |
115 | ||
116 | write!(f, " + {}", dyn_ty.lifetime.display(s))?; | |
117 | Ok(()) | |
118 | } | |
29967ef6 XL |
119 | TyKind::BoundVar(bound_var) => write!(f, "{}", s.display_bound_var(bound_var)), |
120 | TyKind::InferenceVar(_, _) => write!(f, "_"), | |
121 | TyKind::Alias(alias_ty) => alias_ty.fmt(s, f), | |
122 | TyKind::Function(func) => func.fmt(s, f), | |
123 | TyKind::Placeholder(_) => write!(f, "<placeholder>"), | |
3dfed10e XL |
124 | } |
125 | } | |
126 | } | |
127 | ||
128 | impl<I: Interner> RenderAsRust<I> for AliasTy<I> { | |
129 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
130 | match self { | |
131 | AliasTy::Projection(projection_ty) => projection_ty.fmt(s, f), | |
132 | AliasTy::Opaque(opaque_ty) => opaque_ty.fmt(s, f), | |
133 | } | |
134 | } | |
135 | } | |
136 | ||
137 | impl<I: Interner> RenderAsRust<I> for ProjectionTy<I> { | |
138 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
139 | // <X as Y<A1, A2, A3>>::Z<B1, B2, B3> | |
140 | ||
141 | // Now, we split out A*, Y/Z and B*: | |
142 | // trait_params is X, A1, A2, A3, | |
143 | // assoc_type_params is B1, B2, B3, | |
144 | // assoc_ty_datum stores info about Y and Z. | |
145 | let (assoc_ty_datum, trait_params, assoc_type_params) = s.db().split_projection(&self); | |
146 | write!( | |
147 | f, | |
148 | "<{} as {}>::{}", | |
149 | trait_params[0].display(s), | |
150 | display_type_with_generics(s, assoc_ty_datum.trait_id, &trait_params[1..]), | |
151 | assoc_ty_datum.id.display(s), | |
152 | )?; | |
153 | write_joined_non_empty_list!( | |
154 | f, | |
155 | "<{}>", | |
156 | assoc_type_params.iter().map(|param| param.display(s)), | |
157 | ", " | |
158 | )?; | |
159 | Ok(()) | |
160 | } | |
161 | } | |
162 | ||
163 | impl<I: Interner> RenderAsRust<I> for OpaqueTy<I> { | |
164 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
165 | let interner = s.db().interner(); | |
166 | write!( | |
167 | f, | |
168 | "{}", | |
169 | display_type_with_generics(s, self.opaque_ty_id, self.substitution.as_slice(interner),) | |
170 | ) | |
171 | } | |
172 | } | |
173 | ||
174 | impl<I: Interner> RenderAsRust<I> for FnPointer<I> { | |
175 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
176 | let interner = s.db().interner(); | |
177 | let s = &s.add_debrujin_index(None); | |
178 | if self.num_binders > 0 { | |
179 | write!( | |
180 | f, | |
181 | "for<{}> ", | |
182 | (0..self.num_binders) | |
183 | .map(|n| format!("'{}", s.name_for_introduced_bound_var(n))) | |
184 | .format(", ") | |
185 | )?; | |
186 | } | |
5869c6ff | 187 | let parameters = self.substitution.0.as_slice(interner); |
3dfed10e XL |
188 | write!( |
189 | f, | |
190 | "fn({}) -> {}", | |
191 | parameters[..parameters.len() - 1] | |
192 | .iter() | |
193 | .map(|param| param.display(s)) | |
194 | .format(", "), | |
195 | parameters[parameters.len() - 1].display(s), | |
196 | ) | |
197 | } | |
198 | } | |
199 | ||
3dfed10e XL |
200 | impl<I: Interner> RenderAsRust<I> for Scalar { |
201 | fn fmt(&self, _s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
202 | use chalk_ir::{FloatTy::*, IntTy::*, UintTy::*}; | |
203 | write!( | |
204 | f, | |
205 | "{}", | |
206 | match self { | |
207 | Scalar::Bool => "bool", | |
208 | Scalar::Char => "char", | |
209 | Scalar::Int(int) => match int { | |
210 | Isize => "isize", | |
211 | I8 => "i8", | |
212 | I16 => "i16", | |
213 | I32 => "i32", | |
214 | I64 => "i64", | |
215 | I128 => "i128", | |
216 | }, | |
217 | Scalar::Uint(uint) => match uint { | |
218 | Usize => "usize", | |
219 | U8 => "u8", | |
220 | U16 => "u16", | |
221 | U32 => "u32", | |
222 | U64 => "u64", | |
223 | U128 => "u128", | |
224 | }, | |
225 | Scalar::Float(float) => match float { | |
226 | F32 => "f32", | |
227 | F64 => "f64", | |
228 | }, | |
229 | } | |
230 | ) | |
231 | } | |
232 | } | |
233 | ||
234 | impl<I: Interner> RenderAsRust<I> for LifetimeData<I> { | |
235 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
236 | match self { | |
237 | LifetimeData::BoundVar(v) => write!(f, "'{}", s.display_bound_var(v)), | |
238 | LifetimeData::InferenceVar(_) => write!(f, "'_"), | |
239 | LifetimeData::Placeholder(ix) => { | |
240 | write!(f, "'_placeholder_{}_{}", ix.ui.counter, ix.idx) | |
241 | } | |
29967ef6 | 242 | LifetimeData::Static => write!(f, "'static"), |
5869c6ff XL |
243 | LifetimeData::Empty(_) => write!(f, "'<empty>"), |
244 | LifetimeData::Erased => write!(f, "'_"), | |
3dfed10e XL |
245 | // Matching the void ensures at compile time that this code is |
246 | // unreachable | |
247 | LifetimeData::Phantom(void, _) => match *void {}, | |
248 | } | |
249 | } | |
250 | } | |
251 | ||
252 | impl<I: Interner> RenderAsRust<I> for ConstData<I> { | |
253 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
254 | write!(f, "{}", self.value.display(s)) | |
255 | } | |
256 | } | |
257 | ||
258 | impl<I: Interner> RenderAsRust<I> for ConstValue<I> { | |
259 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
260 | match self { | |
261 | ConstValue::BoundVar(v) => write!(f, "{}", s.display_bound_var(v)), | |
262 | ConstValue::InferenceVar(_) => write!(f, "_"), | |
263 | ConstValue::Placeholder(_) => write!(f, "<const placeholder>"), | |
5869c6ff | 264 | ConstValue::Concrete(value) => write!(f, "{:?}", value.interned), |
3dfed10e XL |
265 | } |
266 | } | |
267 | } | |
268 | ||
269 | impl<I: Interner> RenderAsRust<I> for GenericArgData<I> { | |
270 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
271 | match self { | |
272 | GenericArgData::Ty(ty) => write!(f, "{}", ty.display(s)), | |
273 | GenericArgData::Lifetime(lt) => write!(f, "{}", lt.display(s)), | |
274 | GenericArgData::Const(const_ty) => write!(f, "{}", const_ty.display(s)), | |
275 | } | |
276 | } | |
277 | } | |
278 | ||
279 | impl<I: Interner> RenderAsRust<I> for Ty<I> { | |
280 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
29967ef6 XL |
281 | // delegate to TyKind |
282 | self.kind(s.db().interner()).fmt(s, f) | |
3dfed10e XL |
283 | } |
284 | } | |
285 | ||
286 | impl<I: Interner> RenderAsRust<I> for Lifetime<I> { | |
287 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
288 | // delegate to LifetimeData | |
289 | self.data(s.db().interner()).fmt(s, f) | |
290 | } | |
291 | } | |
292 | ||
293 | impl<I: Interner> RenderAsRust<I> for Const<I> { | |
294 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
295 | self.data(s.db().interner()).fmt(s, f) | |
296 | } | |
297 | } | |
298 | ||
299 | impl<I: Interner> RenderAsRust<I> for GenericArg<I> { | |
300 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
301 | // delegate to GenericArgData | |
302 | self.data(s.db().interner()).fmt(s, f) | |
303 | } | |
304 | } |