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