]>
Commit | Line | Data |
---|---|---|
3dfed10e XL |
1 | //! Writer logic for `where` clauses and other bounds. |
2 | //! | |
3 | //! Contains logic for writing the various forms of `Foo: Bar`. | |
4 | use std::fmt::{Display, Formatter, Result}; | |
5 | ||
6 | use crate::rust_ir::*; | |
7 | use chalk_ir::{interner::Interner, *}; | |
8 | use itertools::Itertools; | |
9 | ||
10 | use super::{ | |
11 | display_trait_with_assoc_ty_value, display_type_with_generics, render_trait::RenderAsRust, | |
12 | state::InternalWriterState, | |
13 | }; | |
14 | use crate::split::Split; | |
15 | ||
16 | impl<I: Interner> RenderAsRust<I> for InlineBound<I> { | |
17 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
18 | match self { | |
19 | // Foo: Vec<T> | |
20 | InlineBound::TraitBound(trait_bound) => trait_bound.fmt(s, f), | |
21 | // Foo: Iterator<Item=Foo> | |
22 | InlineBound::AliasEqBound(eq_bound) => eq_bound.fmt(s, f), | |
23 | } | |
24 | } | |
25 | } | |
26 | ||
27 | impl<I: Interner> RenderAsRust<I> for TraitBound<I> { | |
28 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
29 | display_type_with_generics(s, self.trait_id, &self.args_no_self).fmt(f) | |
30 | } | |
31 | } | |
32 | ||
33 | impl<I: Interner> RenderAsRust<I> for AliasEqBound<I> { | |
34 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
35 | display_trait_with_assoc_ty_value( | |
36 | s, | |
37 | s.db().associated_ty_data(self.associated_ty_id), | |
38 | &self.trait_bound.args_no_self, | |
39 | &self.parameters, | |
40 | &self.value, | |
41 | ) | |
42 | .fmt(f) | |
43 | } | |
44 | } | |
45 | ||
46 | impl<I: Interner> RenderAsRust<I> for QuantifiedWhereClause<I> { | |
47 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
48 | let interner = s.db().interner(); | |
49 | let s = &s.add_debrujin_index(None); | |
50 | if !self.binders.is_empty(interner) { | |
51 | write!( | |
52 | f, | |
53 | "forall<{}> ", | |
54 | s.binder_var_display(&self.binders).format(", ") | |
55 | )?; | |
56 | } | |
57 | self.skip_binders().fmt(s, f) | |
58 | } | |
59 | } | |
60 | ||
61 | impl<I: Interner> RenderAsRust<I> for QuantifiedInlineBound<I> { | |
62 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
63 | let interner = s.db().interner(); | |
64 | let s = &s.add_debrujin_index(None); | |
65 | if !self.binders.is_empty(&interner) { | |
66 | write!( | |
67 | f, | |
68 | "forall<{}> ", | |
69 | s.binder_var_display(&self.binders).format(", ") | |
70 | )?; | |
71 | } | |
72 | self.skip_binders().fmt(s, f) | |
73 | } | |
74 | } | |
75 | ||
76 | impl<I: Interner> RenderAsRust<I> for Vec<QuantifiedWhereClause<I>> { | |
77 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
78 | write!( | |
79 | f, | |
80 | "{}", | |
81 | self.iter() | |
82 | .map(|where_clause| { format!("{}{}", s.indent(), where_clause.display(s)) }) | |
83 | .format(",\n") | |
84 | )?; | |
85 | Ok(()) | |
86 | } | |
87 | } | |
88 | ||
89 | impl<I: Interner> RenderAsRust<I> for WhereClause<I> { | |
90 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
91 | match self { | |
92 | WhereClause::Implemented(trait_ref) => trait_ref.fmt(s, f), | |
93 | WhereClause::AliasEq(alias_eq) => alias_eq.fmt(s, f), | |
94 | WhereClause::LifetimeOutlives(lifetime) => lifetime.display(s).fmt(f), | |
95 | WhereClause::TypeOutlives(ty) => ty.display(s).fmt(f), | |
96 | } | |
97 | } | |
98 | } | |
99 | ||
100 | /// This renders `TraitRef` as a clause in a where clause, as opposed to its | |
101 | /// usage in other places. | |
102 | impl<I: Interner> RenderAsRust<I> for TraitRef<I> { | |
103 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
104 | let interner = s.db().interner(); | |
105 | write!( | |
106 | f, | |
107 | "{}: {}", | |
108 | self.self_type_parameter(interner).display(s), | |
109 | display_type_with_generics( | |
110 | s, | |
111 | self.trait_id, | |
112 | &self.substitution.as_slice(interner)[1..] | |
113 | ) | |
114 | ) | |
115 | } | |
116 | } | |
117 | ||
118 | /// This renders `AliasEq` as a clause in a where clause, as opposed to its | |
119 | /// usage in other places. | |
120 | impl<I: Interner> RenderAsRust<I> for AliasEq<I> { | |
121 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &'_ mut Formatter<'_>) -> Result { | |
122 | // we have: X: Y<A1, A2, A3, Z<B1, B2, B3>=D> | |
123 | // B1, B2, B3, X, A1, A2, A3 are put into alias_eq.alias.substitution | |
124 | // D is alias_eq.ty | |
125 | // Z is alias_eq.alias.associated_ty_id | |
126 | // Y is also packed into alias_eq.alias.associated_ty_id | |
127 | // Now, we split out A*, Y/Z and B*: | |
128 | // trait_params is X, A1, A2, A3, | |
129 | // assoc_type_params is B1, B2, B3, | |
130 | // assoc_ty_datum stores info about Y and Z. | |
131 | match &self.alias { | |
132 | AliasTy::Projection(projection_ty) => { | |
133 | let (assoc_ty_datum, trait_params, assoc_type_params) = | |
134 | s.db().split_projection(&projection_ty); | |
135 | // An alternate form might be `<{} as {}<{}>>::{}<{}> = {}` (with same | |
136 | // parameter ordering). This alternate form would require type equality | |
137 | // constraints (https://github.com/rust-lang/rust/issues/20041). | |
138 | write!( | |
139 | f, | |
140 | "{}: {}", | |
141 | trait_params[0].display(s), | |
142 | display_trait_with_assoc_ty_value( | |
143 | s, | |
144 | assoc_ty_datum, | |
145 | &trait_params[1..], | |
146 | assoc_type_params, | |
147 | &self.ty | |
148 | ), | |
149 | ) | |
150 | } | |
151 | AliasTy::Opaque(_) => todo!("opaque types"), | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | impl<I: Interner> RenderAsRust<I> for LifetimeOutlives<I> { | |
157 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
158 | // a': 'b | |
159 | write!(f, "{}: {}", self.a.display(s), self.b.display(s)) | |
160 | } | |
161 | } | |
162 | ||
163 | impl<I: Interner> RenderAsRust<I> for TypeOutlives<I> { | |
164 | fn fmt(&self, s: &InternalWriterState<'_, I>, f: &mut Formatter<'_>) -> Result { | |
165 | // T: 'a | |
166 | write!(f, "{}: {}", self.ty.display(s), self.lifetime.display(s)) | |
167 | } | |
168 | } |