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 : for (auto &member : items.get_upper_patterns ())
96 : {
97 0 : member->accept_vis (*this);
98 : }
99 : break;
100 : }
101 : }
102 0 : }
103 :
104 : void
105 0 : PatternBindingBuilder::visit (HIR::AltPattern &pattern)
106 : {
107 0 : rust_sorry_at (pattern.get_locus (),
108 : "borrow-checking of alt patterns is not yet implemented");
109 0 : }
110 :
111 : void
112 0 : PatternBindingBuilder::visit (HIR::StructPattern &pattern)
113 : {
114 0 : SavedState saved (this);
115 :
116 0 : auto tyty = ctx.place_db[init.value ()].tyty;
117 0 : rust_assert (tyty->get_kind () == TyTy::ADT);
118 0 : auto adt_ty = static_cast<TyTy::ADTType *> (tyty);
119 0 : rust_assert (adt_ty->is_struct_struct ());
120 0 : auto struct_ty = adt_ty->get_variants ().at (0);
121 :
122 0 : for (auto &field :
123 0 : pattern.get_struct_pattern_elems ().get_struct_pattern_fields ())
124 : {
125 0 : switch (field->get_item_type ())
126 : {
127 0 : case HIR::StructPatternField::TUPLE_PAT:
128 0 : {
129 0 : auto tuple
130 0 : = static_cast<HIR::StructPatternFieldTuplePat *> (field.get ());
131 :
132 0 : init = init.map ([&] (PlaceId id) {
133 0 : return ctx.place_db.lookup_or_add_path (
134 : Place::FIELD, lookup_type (tuple->get_tuple_pattern ()), id,
135 0 : tuple->get_index ());
136 : });
137 :
138 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
139 0 : return ty->as<TyTy::ADTType> ()
140 0 : ->get_variants ()
141 0 : .at (0)
142 0 : ->get_fields ()
143 0 : .at (tuple->get_index ())
144 0 : ->get_field_type ();
145 : });
146 :
147 0 : tuple->get_tuple_pattern ().accept_vis (*this);
148 0 : break;
149 : }
150 0 : case HIR::StructPatternField::IDENT_PAT:
151 0 : {
152 0 : auto ident_field
153 0 : = static_cast<HIR::StructPatternFieldIdentPat *> (field.get ());
154 0 : TyTy::StructFieldType *field_ty = nullptr;
155 0 : size_t field_index = 0;
156 0 : auto ok = struct_ty->lookup_field (
157 0 : ident_field->get_identifier ().as_string (), &field_ty,
158 : &field_index);
159 0 : rust_assert (ok);
160 0 : init = ctx.place_db.lookup_or_add_path (Place::FIELD,
161 : field_ty->get_field_type (),
162 0 : saved.init.value (),
163 0 : field_index);
164 0 : ident_field->get_pattern ().accept_vis (*this);
165 0 : break;
166 : }
167 0 : case HIR::StructPatternField::IDENT:
168 0 : {
169 0 : auto ident_field
170 0 : = static_cast<HIR::StructPatternFieldIdent *> (field.get ());
171 0 : TyTy::StructFieldType *field_ty = nullptr;
172 0 : size_t field_index = 0;
173 0 : auto ok = struct_ty->lookup_field (
174 0 : ident_field->get_identifier ().as_string (), &field_ty,
175 : &field_index);
176 0 : rust_assert (ok);
177 0 : init = ctx.place_db.lookup_or_add_path (Place::FIELD,
178 : field_ty->get_field_type (),
179 0 : saved.init.value (),
180 0 : field_index);
181 0 : visit_identifier (ident_field->get_mappings (),
182 0 : ident_field->get_has_ref (),
183 : ident_field->get_locus (),
184 0 : ident_field->is_mut ());
185 0 : break;
186 : }
187 : }
188 : }
189 0 : }
190 :
191 : void
192 0 : PatternBindingBuilder::visit_tuple_fields (
193 : std::vector<std::unique_ptr<HIR::Pattern>> &fields, SavedState &saved,
194 : size_t &index)
195 : {
196 0 : for (auto &item : fields)
197 : {
198 0 : auto type = lookup_type (*item);
199 :
200 0 : init = init.map ([&] (PlaceId id) {
201 0 : return ctx.place_db.lookup_or_add_path (Place::FIELD, type, id, index);
202 : });
203 :
204 0 : type_annotation = type_annotation.map ([&] (TyTy::BaseType *ty) {
205 0 : return ty->as<TyTy::TupleType> ()->get_fields ().at (index).get_tyty ();
206 : });
207 :
208 0 : regions = regions.map ([&] (FreeRegions regs) {
209 0 : return bind_regions (Resolver::TypeCheckContext::get ()
210 0 : ->get_variance_analysis_ctx ()
211 0 : .query_type_regions (type),
212 0 : regs);
213 0 : });
214 :
215 0 : item->accept_vis (*this);
216 0 : index++;
217 : }
218 0 : }
219 :
220 : void
221 0 : PatternBindingBuilder::visit (HIR::TuplePattern &pattern)
222 : {
223 0 : SavedState saved (this);
224 :
225 0 : size_t index = 0;
226 0 : switch (pattern.get_items ().get_item_type ())
227 : {
228 0 : case HIR::TuplePatternItems::NO_REST:
229 0 : {
230 0 : auto &items
231 0 : = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
232 0 : visit_tuple_fields (items.get_patterns (), saved, index);
233 0 : break;
234 : }
235 0 : case HIR::TuplePatternItems::HAS_REST:
236 0 : {
237 0 : auto &items
238 0 : = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
239 :
240 0 : auto tyty = ctx.place_db[init.value ()].tyty;
241 0 : rust_assert (tyty->get_kind () == TyTy::TUPLE);
242 :
243 0 : auto skipped = (static_cast<TyTy::TupleType *> (tyty))->num_fields ()
244 0 : - items.get_lower_patterns ().size ()
245 0 : - items.get_upper_patterns ().size ();
246 :
247 0 : visit_tuple_fields (items.get_lower_patterns (), saved, index);
248 0 : index += skipped;
249 0 : visit_tuple_fields (items.get_upper_patterns (), saved, index);
250 0 : break;
251 : }
252 : }
253 0 : init = saved.init;
254 0 : }
255 :
256 : void
257 0 : PatternBindingBuilder::visit (HIR::TupleStructPattern &pattern)
258 : {
259 0 : SavedState saved (this);
260 :
261 0 : type_annotation = tl::nullopt;
262 :
263 0 : auto type = lookup_type (pattern);
264 :
265 0 : regions = regions.map ([&] (FreeRegions regs) {
266 0 : return bind_regions (Resolver::TypeCheckContext::get ()
267 0 : ->get_variance_analysis_ctx ()
268 0 : .query_type_regions (type),
269 0 : regs);
270 0 : });
271 :
272 0 : size_t index = 0;
273 0 : switch (pattern.get_items ().get_item_type ())
274 : {
275 0 : case HIR::TupleStructItems::HAS_REST:
276 0 : {
277 0 : auto &items
278 0 : = static_cast<HIR::TupleStructItemsHasRest &> (pattern.get_items ());
279 :
280 0 : rust_assert (type->get_kind () == TyTy::ADT);
281 0 : auto adt_ty = static_cast<TyTy::ADTType *> (type);
282 0 : rust_assert (adt_ty->is_tuple_struct ());
283 :
284 0 : auto skipped = adt_ty->get_variants ().at (0)->get_fields ().size ()
285 0 : - items.get_lower_patterns ().size ()
286 0 : - items.get_upper_patterns ().size ();
287 :
288 0 : visit_tuple_fields (items.get_lower_patterns (), saved, index);
289 0 : index += skipped;
290 0 : visit_tuple_fields (items.get_upper_patterns (), saved, index);
291 0 : break;
292 : }
293 0 : case HIR::TupleStructItems::NO_REST:
294 0 : {
295 0 : auto &items
296 0 : = static_cast<HIR::TupleStructItemsNoRest &> (pattern.get_items ());
297 0 : visit_tuple_fields (items.get_patterns (), saved, index);
298 0 : break;
299 : }
300 : }
301 0 : }
302 : } // namespace BIR
303 : } // namespace Rust
|