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