Line data Source code
1 : #include "rust-bir-builder-pattern.h"
2 :
3 : namespace Rust {
4 : namespace BIR {
5 :
6 : void
7 0 : PatternBindingBuilder::visit_identifier (const Analysis::NodeMapping &node,
8 : bool is_ref, location_t location,
9 : bool is_mut)
10 : {
11 0 : if (is_ref)
12 : {
13 0 : translated = declare_variable (
14 : node,
15 : new TyTy::ReferenceType (node.get_hirid (),
16 0 : TyTy::TyVar (node.get_hirid ()),
17 0 : (is_mut) ? Mutability::Mut : Mutability::Imm));
18 : }
19 : else
20 : {
21 0 : translated = declare_variable (node);
22 : }
23 :
24 0 : if (init.has_value ())
25 : {
26 0 : push_assignment (translated, init.value (), location);
27 : }
28 0 : }
29 :
30 : void
31 0 : PatternBindingBuilder::visit (HIR::IdentifierPattern &pattern)
32 : {
33 : // Top-level identifiers are resolved directly to avoid useless temporary
34 : // (for cleaner BIR).
35 0 : visit_identifier (pattern.get_mappings (), pattern.get_is_ref (),
36 0 : pattern.get_locus (), pattern.is_mut ());
37 0 : }
38 :
39 : void
40 0 : PatternBindingBuilder::visit (HIR::ReferencePattern &pattern)
41 : {
42 0 : SavedState saved (this);
43 :
44 0 : init = init.map ([&] (PlaceId id) {
45 0 : return ctx.place_db.lookup_or_add_path (Place::DEREF, lookup_type (pattern),
46 0 : id);
47 : });
48 :
49 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
50 0 : return ty->as<TyTy::ReferenceType> ()->get_base ();
51 : });
52 :
53 0 : pattern.get_referenced_pattern ().accept_vis (*this);
54 0 : }
55 :
56 : void
57 0 : PatternBindingBuilder::visit (HIR::SlicePattern &pattern)
58 : {
59 0 : SavedState saved (this);
60 :
61 : // All indexes are supposed to point to the same place for borrow-checking.
62 : // init = ctx.place_db.lookup_or_add_path (Place::INDEX, lookup_type
63 : // (pattern), saved.init);
64 0 : init = init.map ([&] (PlaceId id) {
65 0 : return ctx.place_db.lookup_or_add_path (Place::INDEX, lookup_type (pattern),
66 0 : id);
67 : });
68 :
69 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
70 0 : return ty->as<TyTy::SliceType> ()->get_element_type ();
71 : });
72 :
73 : // Regions are unchanged.
74 :
75 0 : switch (pattern.get_items ().get_item_type ())
76 : {
77 0 : case HIR::SlicePatternItems::NO_REST:
78 0 : {
79 0 : auto &items
80 0 : = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
81 0 : for (auto &member : items.get_patterns ())
82 : {
83 0 : member->accept_vis (*this);
84 : }
85 : break;
86 : }
87 0 : case HIR::SlicePatternItems::HAS_REST:
88 0 : {
89 0 : auto &items
90 0 : = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
91 0 : for (auto &member : items.get_lower_patterns ())
92 : {
93 0 : member->accept_vis (*this);
94 : }
95 0 : if (items.has_rest_bind ())
96 : {
97 0 : items.get_rest_bind ().accept_vis (*this);
98 : }
99 0 : for (auto &member : items.get_upper_patterns ())
100 : {
101 0 : member->accept_vis (*this);
102 : }
103 : break;
104 : }
105 : }
106 0 : }
107 :
108 : void
109 0 : PatternBindingBuilder::visit (HIR::AltPattern &pattern)
110 : {
111 0 : rust_sorry_at (pattern.get_locus (),
112 : "borrow-checking of alt patterns is not yet implemented");
113 0 : }
114 :
115 : void
116 0 : PatternBindingBuilder::visit (HIR::StructPattern &pattern)
117 : {
118 0 : SavedState saved (this);
119 :
120 0 : auto tyty = ctx.place_db[init.value ()].tyty;
121 0 : rust_assert (tyty->get_kind () == TyTy::ADT);
122 0 : auto adt_ty = static_cast<TyTy::ADTType *> (tyty);
123 0 : rust_assert (adt_ty->is_struct_struct ());
124 0 : auto struct_ty = adt_ty->get_variants ().at (0);
125 :
126 0 : for (auto &field :
127 0 : pattern.get_struct_pattern_elems ().get_struct_pattern_fields ())
128 : {
129 0 : switch (field->get_item_type ())
130 : {
131 0 : case HIR::StructPatternField::TUPLE_PAT:
132 0 : {
133 0 : auto tuple
134 0 : = static_cast<HIR::StructPatternFieldTuplePat *> (field.get ());
135 :
136 0 : init = init.map ([&] (PlaceId id) {
137 0 : return ctx.place_db.lookup_or_add_path (
138 : Place::FIELD, lookup_type (tuple->get_tuple_pattern ()), id,
139 0 : tuple->get_index ());
140 : });
141 :
142 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
143 0 : return ty->as<TyTy::ADTType> ()
144 0 : ->get_variants ()
145 0 : .at (0)
146 0 : ->get_fields ()
147 0 : .at (tuple->get_index ())
148 0 : ->get_field_type ();
149 : });
150 :
151 0 : tuple->get_tuple_pattern ().accept_vis (*this);
152 0 : break;
153 : }
154 0 : case HIR::StructPatternField::IDENT_PAT:
155 0 : {
156 0 : auto ident_field
157 0 : = static_cast<HIR::StructPatternFieldIdentPat *> (field.get ());
158 0 : TyTy::StructFieldType *field_ty = nullptr;
159 0 : size_t field_index = 0;
160 0 : auto ok = struct_ty->lookup_field (
161 0 : ident_field->get_identifier ().as_string (), &field_ty,
162 : &field_index);
163 0 : rust_assert (ok);
164 0 : init = ctx.place_db.lookup_or_add_path (Place::FIELD,
165 : field_ty->get_field_type (),
166 0 : saved.init.value (),
167 0 : field_index);
168 0 : ident_field->get_pattern ().accept_vis (*this);
169 0 : break;
170 : }
171 0 : case HIR::StructPatternField::IDENT:
172 0 : {
173 0 : auto ident_field
174 0 : = static_cast<HIR::StructPatternFieldIdent *> (field.get ());
175 0 : TyTy::StructFieldType *field_ty = nullptr;
176 0 : size_t field_index = 0;
177 0 : auto ok = struct_ty->lookup_field (
178 0 : ident_field->get_identifier ().as_string (), &field_ty,
179 : &field_index);
180 0 : rust_assert (ok);
181 0 : init = ctx.place_db.lookup_or_add_path (Place::FIELD,
182 : field_ty->get_field_type (),
183 0 : saved.init.value (),
184 0 : field_index);
185 0 : visit_identifier (ident_field->get_mappings (),
186 : ident_field->get_has_ref (),
187 : ident_field->get_locus (),
188 : ident_field->is_mut ());
189 0 : break;
190 : }
191 : }
192 : }
193 0 : }
194 :
195 : void
196 0 : PatternBindingBuilder::visit_tuple_fields (
197 : std::vector<std::unique_ptr<HIR::Pattern>> &fields, SavedState &saved,
198 : size_t &index)
199 : {
200 0 : for (auto &item : fields)
201 : {
202 0 : auto type = lookup_type (*item);
203 :
204 0 : init = init.map ([&] (PlaceId id) {
205 0 : return ctx.place_db.lookup_or_add_path (Place::FIELD, type, id, index);
206 : });
207 :
208 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
209 0 : return ty->as<TyTy::TupleType> ()->get_fields ().at (index).get_tyty ();
210 : });
211 :
212 0 : regions = regions.map ([&] (FreeRegions regs) {
213 0 : return bind_regions (Resolver::TypeCheckContext::get ()
214 0 : ->get_variance_analysis_ctx ()
215 0 : .query_type_regions (type),
216 0 : regs);
217 0 : });
218 :
219 0 : item->accept_vis (*this);
220 0 : index++;
221 : }
222 0 : }
223 :
224 : void
225 0 : PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
226 : {
227 0 : SavedState saved (this);
228 :
229 0 : size_t index = 0;
230 0 : switch (pattern.get_items ().get_item_type ())
231 : {
232 0 : case HIR::TuplePatternItems::NO_REST:
233 0 : {
234 0 : auto &items
235 0 : = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
236 0 : visit_tuple_fields (items.get_patterns (), saved, index);
237 0 : break;
238 : }
239 0 : case HIR::TuplePatternItems::HAS_REST:
240 0 : {
241 0 : auto &items
242 0 : = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
243 :
244 0 : auto tyty = ctx.place_db[init.value ()].tyty;
245 0 : rust_assert (tyty->get_kind () == TyTy::TUPLE);
246 :
247 0 : auto skipped = (static_cast<TyTy::TupleType *> (tyty))->num_fields ()
248 0 : - items.get_lower_patterns ().size ()
249 0 : - items.get_upper_patterns ().size ();
250 :
251 0 : visit_tuple_fields (items.get_lower_patterns (), saved, index);
252 0 : index += skipped;
253 0 : visit_tuple_fields (items.get_upper_patterns (), saved, index);
254 0 : break;
255 : }
256 : }
257 0 : init = saved.init;
258 0 : }
259 :
260 : void
261 0 : PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
262 : {
263 0 : SavedState saved (this);
264 :
265 0 : type_annotation = tl::nullopt;
266 :
267 0 : auto type = lookup_type (pattern);
268 :
269 0 : regions = regions.map ([&] (FreeRegions regs) {
270 0 : return bind_regions (Resolver::TypeCheckContext::get ()
271 0 : ->get_variance_analysis_ctx ()
272 0 : .query_type_regions (type),
273 0 : regs);
274 0 : });
275 :
276 0 : size_t index = 0;
277 0 : switch (pattern.get_items ().get_item_type ())
278 : {
279 0 : case HIR::TupleStructItems::HAS_REST:
280 0 : {
281 0 : auto &items
282 0 : = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ());
283 :
284 0 : rust_assert (type->get_kind () == TyTy::ADT);
285 0 : auto adt_ty = static_cast<TyTy::ADTType *> (type);
286 0 : rust_assert (adt_ty->is_tuple_struct ());
287 :
288 0 : auto skipped = adt_ty->get_variants ().at (0)->get_fields ().size ()
289 0 : - items.get_lower_patterns ().size ()
290 0 : - items.get_upper_patterns ().size ();
291 :
292 0 : visit_tuple_fields (items.get_lower_patterns (), saved, index);
293 0 : index += skipped;
294 0 : visit_tuple_fields (items.get_upper_patterns (), saved, index);
295 0 : break;
296 : }
297 0 : case HIR::TupleStructItems::NO_REST:
298 0 : {
299 0 : auto &items
300 0 : = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ());
301 0 : visit_tuple_fields (items.get_patterns (), saved, index);
302 0 : break;
303 : }
304 : }
305 0 : }
306 : } // namespace BIR
307 : } // namespace Rust
|