Line data Source code
1 : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
2 :
3 : // This file is part of GCC.
4 :
5 : // GCC is free software; you can redistribute it and/or modify it under
6 : // the terms of the GNU General Public License as published by the Free
7 : // Software Foundation; either version 3, or (at your option) any later
8 : // version.
9 :
10 : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 : // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 : // for more details.
14 :
15 : // You should have received a copy of the GNU General Public License
16 : // along with GCC; see the file COPYING3. If not see
17 : // <http://www.gnu.org/licenses/>.
18 :
19 : #include "rust-ast-lower-pattern.h"
20 : #include "rust-ast-lower-expr.h"
21 : #include "rust-system.h"
22 :
23 : namespace Rust {
24 : namespace HIR {
25 :
26 28421 : ASTLoweringPattern::ASTLoweringPattern ()
27 28421 : : translated (nullptr), is_let_top_level (false)
28 28421 : {}
29 :
30 : HIR::Pattern *
31 28421 : ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
32 : {
33 28421 : ASTLoweringPattern resolver;
34 28421 : resolver.is_let_top_level = is_let_top_level;
35 28421 : pattern.accept_vis (resolver);
36 :
37 28421 : rust_assert (resolver.translated != nullptr);
38 :
39 28421 : resolver.mappings.insert_hir_pattern (resolver.translated);
40 28421 : resolver.mappings.insert_location (
41 28421 : resolver.translated->get_mappings ().get_hirid (), pattern.get_locus ());
42 :
43 28421 : return resolver.translated;
44 28421 : }
45 :
46 : void
47 23373 : ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
48 : {
49 23373 : auto crate_num = mappings.get_current_crate ();
50 46746 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
51 23373 : mappings.get_next_hir_id (crate_num),
52 23373 : UNKNOWN_LOCAL_DEFID);
53 :
54 23373 : std::unique_ptr<Pattern> subpattern;
55 23373 : if (pattern.has_subpattern ())
56 : {
57 31 : subpattern = std::unique_ptr<Pattern> (
58 31 : ASTLoweringPattern::translate (pattern.get_subpattern ()));
59 : }
60 23373 : translated
61 23373 : = new HIR::IdentifierPattern (mapping, pattern.get_ident (),
62 : pattern.get_locus (), pattern.get_is_ref (),
63 23373 : pattern.get_is_mut () ? Mutability::Mut
64 : : Mutability::Imm,
65 69058 : std::move (subpattern));
66 23373 : }
67 :
68 : void
69 1152 : ASTLoweringPattern::visit (AST::PathInExpression &pattern)
70 : {
71 1152 : translated = ASTLowerPathInExpression::translate (pattern);
72 1152 : }
73 :
74 : void
75 1057 : ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
76 : {
77 1057 : HIR::PathInExpression *path
78 1057 : = ASTLowerPathInExpression::translate (pattern.get_path ());
79 :
80 1057 : TupleStructItems *lowered = nullptr;
81 1057 : auto &items = pattern.get_items ();
82 1057 : switch (items.get_item_type ())
83 : {
84 45 : case AST::TupleStructItems::HAS_REST:
85 45 : {
86 45 : AST::TupleStructItemsHasRest &items_has_rest
87 : = static_cast<AST::TupleStructItemsHasRest &> (items);
88 :
89 45 : std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
90 45 : lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ());
91 82 : for (auto &pattern_member : items_has_rest.get_lower_patterns ())
92 : {
93 37 : lower_patterns.emplace_back (
94 37 : ASTLoweringPattern::translate (*pattern_member));
95 : }
96 :
97 45 : std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
98 45 : upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ());
99 68 : for (auto &pattern_member : items_has_rest.get_upper_patterns ())
100 : {
101 23 : upper_patterns.emplace_back (
102 23 : ASTLoweringPattern::translate (*pattern_member));
103 : }
104 :
105 45 : lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns),
106 45 : std::move (upper_patterns));
107 45 : }
108 45 : break;
109 :
110 1012 : case AST::TupleStructItems::NO_REST:
111 1012 : {
112 1012 : AST::TupleStructItemsNoRest &items_no_rest
113 : = static_cast<AST::TupleStructItemsNoRest &> (items);
114 :
115 1012 : std::vector<std::unique_ptr<HIR::Pattern>> patterns;
116 1012 : patterns.reserve (items_no_rest.get_patterns ().size ());
117 :
118 2111 : for (auto &inner_pattern : items_no_rest.get_patterns ())
119 1099 : patterns.emplace_back (
120 1099 : ASTLoweringPattern::translate (*inner_pattern));
121 :
122 1012 : lowered = new HIR::TupleStructItemsNoRest (std::move (patterns));
123 1012 : }
124 1012 : break;
125 : }
126 :
127 1057 : auto crate_num = mappings.get_current_crate ();
128 2114 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
129 1057 : mappings.get_next_hir_id (crate_num),
130 1057 : UNKNOWN_LOCAL_DEFID);
131 :
132 2114 : translated = new HIR::TupleStructPattern (
133 1057 : mapping, *path, std::unique_ptr<HIR::TupleStructItems> (lowered));
134 1057 : }
135 :
136 : void
137 208 : ASTLoweringPattern::visit (AST::StructPattern &pattern)
138 : {
139 208 : HIR::PathInExpression *path
140 208 : = ASTLowerPathInExpression::translate (pattern.get_path ());
141 :
142 208 : auto &raw_elems = pattern.get_struct_pattern_elems ();
143 :
144 208 : std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
145 538 : for (auto &field : raw_elems.get_struct_pattern_fields ())
146 : {
147 330 : HIR::StructPatternField *f = nullptr;
148 330 : switch (field->get_item_type ())
149 : {
150 32 : case AST::StructPatternField::ItemType::TUPLE_PAT:
151 32 : {
152 32 : auto &tuple
153 32 : = static_cast<AST::StructPatternFieldTuplePat &> (*field);
154 :
155 32 : auto crate_num = mappings.get_current_crate ();
156 32 : Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
157 32 : mappings.get_next_hir_id (crate_num),
158 32 : UNKNOWN_LOCAL_DEFID);
159 :
160 32 : std::unique_ptr<HIR::Pattern> pat (
161 32 : ASTLoweringPattern::translate (tuple.get_index_pattern ()));
162 :
163 64 : f = new HIR::StructPatternFieldTuplePat (mapping,
164 : tuple.get_index (),
165 : std::move (pat),
166 32 : tuple.get_outer_attrs (),
167 32 : tuple.get_locus ());
168 32 : }
169 32 : break;
170 :
171 184 : case AST::StructPatternField::ItemType::IDENT_PAT:
172 184 : {
173 184 : AST::StructPatternFieldIdentPat &ident
174 184 : = static_cast<AST::StructPatternFieldIdentPat &> (*field);
175 :
176 184 : auto crate_num = mappings.get_current_crate ();
177 184 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
178 184 : mappings.get_next_hir_id (crate_num),
179 184 : UNKNOWN_LOCAL_DEFID);
180 :
181 184 : std::unique_ptr<HIR::Pattern> pat (
182 184 : ASTLoweringPattern::translate (ident.get_ident_pattern ()));
183 :
184 184 : f = new HIR::StructPatternFieldIdentPat (mapping,
185 : ident.get_identifier (),
186 : std::move (pat),
187 184 : ident.get_outer_attrs (),
188 368 : ident.get_locus ());
189 184 : }
190 184 : break;
191 :
192 114 : case AST::StructPatternField::ItemType::IDENT:
193 114 : {
194 114 : AST::StructPatternFieldIdent &ident
195 114 : = static_cast<AST::StructPatternFieldIdent &> (*field.get ());
196 :
197 114 : auto crate_num = mappings.get_current_crate ();
198 114 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
199 114 : mappings.get_next_hir_id (crate_num),
200 114 : UNKNOWN_LOCAL_DEFID);
201 :
202 114 : f = new HIR::StructPatternFieldIdent (
203 : mapping, ident.get_identifier (), ident.is_ref (),
204 114 : ident.is_mut () ? Mutability::Mut : Mutability::Imm,
205 340 : ident.get_outer_attrs (), ident.get_locus ());
206 : }
207 114 : break;
208 : }
209 :
210 : // insert the reverse mappings and locations
211 330 : auto field_id = f->get_mappings ().get_hirid ();
212 330 : auto field_node_id = f->get_mappings ().get_nodeid ();
213 330 : mappings.insert_location (field_id, f->get_locus ());
214 330 : mappings.insert_node_to_hir (field_node_id, field_id);
215 :
216 : // add it to the lowered fields list
217 330 : fields.emplace_back (f);
218 : }
219 :
220 208 : auto crate_num = mappings.get_current_crate ();
221 416 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
222 208 : mappings.get_next_hir_id (crate_num),
223 208 : UNKNOWN_LOCAL_DEFID);
224 :
225 208 : HIR::StructPatternElements elems (
226 208 : std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
227 208 : translated = new HIR::StructPattern (mapping, *path, std::move (elems));
228 208 : }
229 :
230 : void
231 1138 : ASTLoweringPattern::visit (AST::WildcardPattern &pattern)
232 : {
233 1138 : auto crate_num = mappings.get_current_crate ();
234 2276 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
235 1138 : mappings.get_next_hir_id (crate_num),
236 1138 : UNKNOWN_LOCAL_DEFID);
237 :
238 1138 : translated = new HIR::WildcardPattern (mapping, pattern.get_locus ());
239 1138 : }
240 :
241 : void
242 550 : ASTLoweringPattern::visit (AST::TuplePattern &pattern)
243 : {
244 550 : std::unique_ptr<HIR::TuplePatternItems> items;
245 550 : switch (pattern.get_items ().get_item_type ())
246 : {
247 512 : case AST::TuplePatternItems::ItemType::NO_REST:
248 512 : {
249 512 : AST::TuplePatternItemsNoRest &ref
250 512 : = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ());
251 512 : items = lower_tuple_pattern_multiple (ref);
252 : }
253 512 : break;
254 :
255 38 : case AST::TuplePatternItems::ItemType::HAS_REST:
256 38 : {
257 38 : AST::TuplePatternItemsHasRest &ref
258 38 : = static_cast<AST::TuplePatternItemsHasRest &> (pattern.get_items ());
259 38 : items = lower_tuple_pattern_ranged (ref);
260 : }
261 38 : break;
262 : }
263 :
264 550 : auto crate_num = mappings.get_current_crate ();
265 1100 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
266 550 : mappings.get_next_hir_id (crate_num),
267 550 : UNKNOWN_LOCAL_DEFID);
268 :
269 550 : translated
270 550 : = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ());
271 550 : }
272 :
273 : void
274 463 : ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
275 : {
276 463 : auto crate_num = mappings.get_current_crate ();
277 926 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
278 463 : mappings.get_next_hir_id (crate_num),
279 463 : UNKNOWN_LOCAL_DEFID);
280 :
281 463 : HIR::Literal l = lower_literal (pattern.get_literal ());
282 463 : translated
283 463 : = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (),
284 926 : pattern.get_has_minus ());
285 463 : }
286 :
287 : void
288 46 : ASTLoweringPattern::visit (AST::RangePattern &pattern)
289 : {
290 46 : auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ());
291 46 : auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ());
292 :
293 46 : auto crate_num = mappings.get_current_crate ();
294 92 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
295 46 : mappings.get_next_hir_id (crate_num),
296 46 : UNKNOWN_LOCAL_DEFID);
297 :
298 46 : bool is_inclusive = (pattern.get_range_kind () == AST::RangeKind::INCLUDED);
299 :
300 46 : translated = new HIR::RangePattern (mapping, std::move (lower_bound),
301 : std::move (upper_bound),
302 46 : pattern.get_locus (), is_inclusive);
303 46 : }
304 :
305 : void
306 6 : ASTLoweringPattern::visit (AST::GroupedPattern &pattern)
307 : {
308 6 : is_let_top_level = false;
309 6 : pattern.get_pattern_in_parens ().accept_vis (*this);
310 6 : }
311 :
312 : void
313 197 : ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
314 : {
315 197 : auto crate_num = mappings.get_current_crate ();
316 394 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
317 197 : mappings.get_next_hir_id (crate_num),
318 197 : UNKNOWN_LOCAL_DEFID);
319 :
320 197 : HIR::Pattern *inner
321 197 : = ASTLoweringPattern::translate (pattern.get_referenced_pattern ());
322 :
323 197 : translated
324 197 : = new HIR::ReferencePattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
325 197 : pattern.get_is_mut () ? Mutability::Mut
326 : : Mutability::Imm,
327 394 : pattern.get_locus ());
328 :
329 197 : if (pattern.is_double_reference ())
330 : {
331 20 : Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
332 10 : mappings.get_next_hir_id (crate_num),
333 10 : UNKNOWN_LOCAL_DEFID);
334 10 : translated
335 10 : = new HIR::ReferencePattern (mapping2,
336 10 : std::unique_ptr<HIR::Pattern> (translated),
337 10 : Mutability::Imm, pattern.get_locus ());
338 : }
339 197 : }
340 :
341 : template <typename It>
342 : static std::vector<std::unique_ptr<HIR::Pattern>>
343 137 : lower_pattern_seq (It begin, It end)
344 : {
345 137 : std::vector<std::unique_ptr<HIR::Pattern>> ret;
346 137 : ret.reserve (end - begin);
347 303 : for (auto it = begin; it != end; it++)
348 166 : ret.emplace_back (ASTLoweringPattern::translate (**it));
349 137 : return ret;
350 : }
351 :
352 : void
353 86 : ASTLoweringPattern::visit (AST::SlicePattern &pattern)
354 : {
355 86 : tl::optional<size_t> rest_index;
356 86 : tl::optional<HIR::IdentifierPattern> rest_bind;
357 :
358 86 : std::vector<std::unique_ptr<AST::Pattern>> &sub_patterns
359 86 : = pattern.get_patterns ();
360 :
361 : // need this earlier than usual
362 : // since we might need to produce rest_bind
363 86 : auto crate_num = mappings.get_current_crate ();
364 :
365 291 : for (size_t i = 0; i < sub_patterns.size (); i++)
366 : {
367 170 : auto &pat = sub_patterns[i];
368 :
369 : // ASTValidation verified there's only one Rest pattern
370 : // so we can break once we find the first one
371 170 : if (pat->get_pattern_kind () == AST::Pattern::Kind::Identifier)
372 : {
373 27 : auto &ident_pat = static_cast<AST::IdentifierPattern &> (*pat);
374 27 : if (ident_pat.has_subpattern ())
375 : {
376 1 : if (ident_pat.get_subpattern ().get_pattern_kind ()
377 : == AST::Pattern::Kind::Rest)
378 : {
379 1 : Analysis::NodeMapping rest_bind_mapping (
380 1 : crate_num, ident_pat.get_node_id (),
381 1 : mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
382 :
383 1 : rest_bind = HIR::IdentifierPattern (
384 2 : std::move (rest_bind_mapping), ident_pat.get_ident (),
385 : ident_pat.get_locus (), ident_pat.get_is_ref (),
386 1 : ident_pat.get_is_mut () ? Mutability::Mut
387 3 : : Mutability::Imm);
388 1 : rest_index = i;
389 1 : break;
390 : }
391 : }
392 : }
393 143 : else if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
394 : {
395 50 : rest_index = i;
396 50 : break;
397 : }
398 : }
399 :
400 86 : std::unique_ptr<HIR::SlicePatternItems> items;
401 :
402 86 : if (rest_index)
403 : {
404 51 : auto rest_it = sub_patterns.begin () + *rest_index;
405 153 : items = std::make_unique<HIR::SlicePatternItemsHasRest> (
406 102 : lower_pattern_seq (sub_patterns.begin (), rest_it),
407 102 : lower_pattern_seq (rest_it + 1, sub_patterns.end ()),
408 51 : std::move (rest_bind));
409 : }
410 : else
411 : {
412 70 : items = std::make_unique<HIR::SlicePatternItemsNoRest> (
413 105 : lower_pattern_seq (sub_patterns.begin (), sub_patterns.end ()));
414 : }
415 :
416 172 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
417 86 : mappings.get_next_hir_id (crate_num),
418 86 : UNKNOWN_LOCAL_DEFID);
419 :
420 86 : translated
421 86 : = new HIR::SlicePattern (mapping, std::move (items), pattern.get_locus ());
422 86 : }
423 :
424 : void
425 151 : ASTLoweringPattern::visit (AST::AltPattern &pattern)
426 : {
427 151 : auto crate_num = mappings.get_current_crate ();
428 302 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
429 151 : mappings.get_next_hir_id (crate_num),
430 151 : UNKNOWN_LOCAL_DEFID);
431 :
432 151 : std::vector<std::unique_ptr<HIR::Pattern>> alts;
433 151 : alts.reserve (pattern.get_alts ().size ());
434 :
435 454 : for (auto &alt : pattern.get_alts ())
436 303 : alts.emplace_back (ASTLoweringPattern::translate (*alt));
437 :
438 151 : translated
439 151 : = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ());
440 :
441 151 : if (is_let_top_level)
442 : {
443 1 : rich_location richloc (line_table, pattern.get_locus ());
444 1 : richloc.add_fixit_replace ("use an outer grouped pattern");
445 1 : rust_error_at (
446 : richloc, "top level or-patterns are not allowed for %<let%> bindings");
447 1 : }
448 151 : }
449 :
450 : } // namespace HIR
451 : } // namespace Rust
|