1use std::fmt::{Formatter, Result};
5
6use crate::split::Split;
7use chalk_ir::{interner::Interner, *};
8use itertools::Itertools;
9
10use super::{
11    display_self_where_clauses_as_bounds, display_type_with_generics, render_trait::RenderAsRust,
12    state::InternalWriterState,
13};
14
15impl<I: Interner> RenderAsRust<I> for TyKind<I> {
16    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
17        let interner = s.db().interner();
18        match self {
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                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                        ","
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            TyKind::FnDef(..) => write!(f, "<fn_def>"),
95            TyKind::Closure(..) => write!(f, "<closure>"),
96            TyKind::Foreign(..) => write!(f, "<foreign>"),
97            TyKind::Coroutine(..) => write!(f, "<coroutine>"),
98            TyKind::CoroutineWitness(..) => write!(f, "<coroutine_witness>"),
99
100            TyKind::Array(ty, const_) => write!(f, "[{}; {}]", ty.display(s), const_.display(s),),
101            TyKind::Dyn(dyn_ty) => {
102                {
105                    let s = &s.add_debrujin_index(None);
106                    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            }
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>"),
124        }
125    }
126}
127
128impl<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
137impl<I: Interner> RenderAsRust<I> for ProjectionTy<I> {
138    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
139        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
163impl<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
174impl<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        }
187        let parameters = self.substitution.0.as_slice(interner);
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
200impl<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                    F16 => "f16",
227                    F32 => "f32",
228                    F64 => "f64",
229                    F128 => "f128",
230                },
231            }
232        )
233    }
234}
235
236impl<I: Interner> RenderAsRust<I> for LifetimeData<I> {
237    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
238        match self {
239            LifetimeData::BoundVar(v) => write!(f, "'{}", s.display_bound_var(v)),
240            LifetimeData::InferenceVar(_) => write!(f, "'_"),
241            LifetimeData::Placeholder(ix) => {
242                write!(f, "'_placeholder_{}_{}", ix.ui.counter, ix.idx)
243            }
244            LifetimeData::Static => write!(f, "'static"),
245            LifetimeData::Erased => write!(f, "'_"),
246            LifetimeData::Error => write!(f, "'{{error}}"),
247            LifetimeData::Phantom(void, _) => match *void {},
250        }
251    }
252}
253
254impl<I: Interner> RenderAsRust<I> for ConstData<I> {
255    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
256        write!(f, "{}", self.value.display(s))
257    }
258}
259
260impl<I: Interner> RenderAsRust<I> for ConstValue<I> {
261    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
262        match self {
263            ConstValue::BoundVar(v) => write!(f, "{}", s.display_bound_var(v)),
264            ConstValue::InferenceVar(_) => write!(f, "_"),
265            ConstValue::Placeholder(_) => write!(f, "<const placeholder>"),
266            ConstValue::Concrete(value) => write!(f, "{:?}", value.interned),
267        }
268    }
269}
270
271impl<I: Interner> RenderAsRust<I> for GenericArgData<I> {
272    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
273        match self {
274            GenericArgData::Ty(ty) => write!(f, "{}", ty.display(s)),
275            GenericArgData::Lifetime(lt) => write!(f, "{}", lt.display(s)),
276            GenericArgData::Const(const_ty) => write!(f, "{}", const_ty.display(s)),
277        }
278    }
279}
280
281impl<I: Interner> RenderAsRust<I> for Ty<I> {
282    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
283        self.kind(s.db().interner()).fmt(s, f)
285    }
286}
287
288impl<I: Interner> RenderAsRust<I> for Lifetime<I> {
289    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
290        self.data(s.db().interner()).fmt(s, f)
292    }
293}
294
295impl<I: Interner> RenderAsRust<I> for Const<I> {
296    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result {
297        self.data(s.db().interner()).fmt(s, f)
298    }
299}
300
301impl<I: Interner> RenderAsRust<I> for GenericArg<I> {
302    fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result {
303        self.data(s.db().interner()).fmt(s, f)
305    }
306}