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 26626 : ASTLoweringPattern::ASTLoweringPattern ()
27 26626 : : translated (nullptr), is_let_top_level (false)
28 26626 : {}
29 :
30 : HIR::Pattern *
31 26626 : ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
32 : {
33 26626 : ASTLoweringPattern resolver;
34 26626 : resolver.is_let_top_level = is_let_top_level;
35 26626 : pattern.accept_vis (resolver);
36 :
37 26626 : rust_assert (resolver.translated != nullptr);
38 :
39 26626 : resolver.mappings.insert_hir_pattern (resolver.translated);
40 26626 : resolver.mappings.insert_location (
41 26626 : resolver.translated->get_mappings ().get_hirid (), pattern.get_locus ());
42 :
43 26626 : return resolver.translated;
44 26626 : }
45 :
46 : void
47 21791 : ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
48 : {
49 21791 : auto crate_num = mappings.get_current_crate ();
50 43582 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
51 21791 : mappings.get_next_hir_id (crate_num),
52 21791 : UNKNOWN_LOCAL_DEFID);
53 :
54 21791 : std::unique_ptr<Pattern> subpattern;
55 21791 : if (pattern.has_subpattern ())
56 : {
57 24 : subpattern = std::unique_ptr<Pattern> (
58 24 : ASTLoweringPattern::translate (pattern.get_subpattern ()));
59 : }
60 21791 : translated
61 21791 : = new HIR::IdentifierPattern (mapping, pattern.get_ident (),
62 : pattern.get_locus (), pattern.get_is_ref (),
63 21791 : pattern.get_is_mut () ? Mutability::Mut
64 : : Mutability::Imm,
65 64412 : std::move (subpattern));
66 21791 : }
67 :
68 : void
69 1134 : ASTLoweringPattern::visit (AST::PathInExpression &pattern)
70 : {
71 1134 : translated = ASTLowerPathInExpression::translate (pattern);
72 1134 : }
73 :
74 : void
75 1025 : ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
76 : {
77 1025 : HIR::PathInExpression *path
78 1025 : = ASTLowerPathInExpression::translate (pattern.get_path ());
79 :
80 1025 : TupleStructItems *lowered = nullptr;
81 1025 : auto &items = pattern.get_items ();
82 1025 : 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 980 : case AST::TupleStructItems::NO_REST:
111 980 : {
112 980 : AST::TupleStructItemsNoRest &items_no_rest
113 : = static_cast<AST::TupleStructItemsNoRest &> (items);
114 :
115 980 : std::vector<std::unique_ptr<HIR::Pattern>> patterns;
116 980 : patterns.reserve (items_no_rest.get_patterns ().size ());
117 :
118 2047 : for (auto &inner_pattern : items_no_rest.get_patterns ())
119 1067 : patterns.emplace_back (
120 1067 : ASTLoweringPattern::translate (*inner_pattern));
121 :
122 980 : lowered = new HIR::TupleStructItemsNoRest (std::move (patterns));
123 980 : }
124 980 : break;
125 : }
126 :
127 1025 : auto crate_num = mappings.get_current_crate ();
128 2050 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
129 1025 : mappings.get_next_hir_id (crate_num),
130 1025 : UNKNOWN_LOCAL_DEFID);
131 :
132 2050 : translated = new HIR::TupleStructPattern (
133 1025 : mapping, *path, std::unique_ptr<HIR::TupleStructItems> (lowered));
134 1025 : }
135 :
136 : void
137 176 : ASTLoweringPattern::visit (AST::StructPattern &pattern)
138 : {
139 176 : HIR::PathInExpression *path
140 176 : = ASTLowerPathInExpression::translate (pattern.get_path ());
141 :
142 176 : auto &raw_elems = pattern.get_struct_pattern_elems ();
143 :
144 176 : std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
145 473 : for (auto &field : raw_elems.get_struct_pattern_fields ())
146 : {
147 297 : HIR::StructPatternField *f = nullptr;
148 297 : switch (field->get_item_type ())
149 : {
150 24 : case AST::StructPatternField::ItemType::TUPLE_PAT:
151 24 : {
152 24 : auto &tuple
153 24 : = static_cast<AST::StructPatternFieldTuplePat &> (*field);
154 :
155 24 : auto crate_num = mappings.get_current_crate ();
156 24 : Analysis::NodeMapping mapping (crate_num, tuple.get_node_id (),
157 24 : mappings.get_next_hir_id (crate_num),
158 24 : UNKNOWN_LOCAL_DEFID);
159 :
160 24 : std::unique_ptr<HIR::Pattern> pat (
161 24 : ASTLoweringPattern::translate (tuple.get_index_pattern ()));
162 :
163 48 : f = new HIR::StructPatternFieldTuplePat (mapping,
164 : tuple.get_index (),
165 : std::move (pat),
166 24 : tuple.get_outer_attrs (),
167 24 : tuple.get_locus ());
168 24 : }
169 24 : break;
170 :
171 167 : case AST::StructPatternField::ItemType::IDENT_PAT:
172 167 : {
173 167 : AST::StructPatternFieldIdentPat &ident
174 167 : = static_cast<AST::StructPatternFieldIdentPat &> (*field);
175 :
176 167 : auto crate_num = mappings.get_current_crate ();
177 167 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
178 167 : mappings.get_next_hir_id (crate_num),
179 167 : UNKNOWN_LOCAL_DEFID);
180 :
181 167 : std::unique_ptr<HIR::Pattern> pat (
182 167 : ASTLoweringPattern::translate (ident.get_ident_pattern ()));
183 :
184 167 : f = new HIR::StructPatternFieldIdentPat (mapping,
185 : ident.get_identifier (),
186 : std::move (pat),
187 167 : ident.get_outer_attrs (),
188 334 : ident.get_locus ());
189 167 : }
190 167 : break;
191 :
192 106 : case AST::StructPatternField::ItemType::IDENT:
193 106 : {
194 106 : AST::StructPatternFieldIdent &ident
195 106 : = static_cast<AST::StructPatternFieldIdent &> (*field.get ());
196 :
197 106 : auto crate_num = mappings.get_current_crate ();
198 106 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
199 106 : mappings.get_next_hir_id (crate_num),
200 106 : UNKNOWN_LOCAL_DEFID);
201 :
202 106 : f = new HIR::StructPatternFieldIdent (
203 : mapping, ident.get_identifier (), ident.is_ref (),
204 106 : ident.is_mut () ? Mutability::Mut : Mutability::Imm,
205 316 : ident.get_outer_attrs (), ident.get_locus ());
206 : }
207 106 : break;
208 : }
209 :
210 : // insert the reverse mappings and locations
211 297 : auto field_id = f->get_mappings ().get_hirid ();
212 297 : auto field_node_id = f->get_mappings ().get_nodeid ();
213 297 : mappings.insert_location (field_id, f->get_locus ());
214 297 : mappings.insert_node_to_hir (field_node_id, field_id);
215 :
216 : // add it to the lowered fields list
217 297 : fields.emplace_back (f);
218 : }
219 :
220 176 : auto crate_num = mappings.get_current_crate ();
221 352 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
222 176 : mappings.get_next_hir_id (crate_num),
223 176 : UNKNOWN_LOCAL_DEFID);
224 :
225 176 : HIR::StructPatternElements elems (
226 176 : std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
227 176 : translated = new HIR::StructPattern (mapping, *path, std::move (elems));
228 176 : }
229 :
230 : void
231 1104 : ASTLoweringPattern::visit (AST::WildcardPattern &pattern)
232 : {
233 1104 : auto crate_num = mappings.get_current_crate ();
234 2208 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
235 1104 : mappings.get_next_hir_id (crate_num),
236 1104 : UNKNOWN_LOCAL_DEFID);
237 :
238 1104 : translated = new HIR::WildcardPattern (mapping, pattern.get_locus ());
239 1104 : }
240 :
241 : void
242 462 : ASTLoweringPattern::visit (AST::TuplePattern &pattern)
243 : {
244 462 : std::unique_ptr<HIR::TuplePatternItems> items;
245 462 : switch (pattern.get_items ().get_item_type ())
246 : {
247 424 : case AST::TuplePatternItems::ItemType::NO_REST:
248 424 : {
249 424 : AST::TuplePatternItemsNoRest &ref
250 424 : = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ());
251 424 : items = lower_tuple_pattern_multiple (ref);
252 : }
253 424 : 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 462 : auto crate_num = mappings.get_current_crate ();
265 924 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
266 462 : mappings.get_next_hir_id (crate_num),
267 462 : UNKNOWN_LOCAL_DEFID);
268 :
269 462 : translated
270 462 : = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ());
271 462 : }
272 :
273 : void
274 457 : ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
275 : {
276 457 : auto crate_num = mappings.get_current_crate ();
277 914 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
278 457 : mappings.get_next_hir_id (crate_num),
279 457 : UNKNOWN_LOCAL_DEFID);
280 :
281 457 : HIR::Literal l = lower_literal (pattern.get_literal ());
282 457 : translated
283 457 : = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (),
284 914 : pattern.get_has_minus ());
285 457 : }
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 132 : lower_pattern_seq (It begin, It end)
344 : {
345 132 : std::vector<std::unique_ptr<HIR::Pattern>> ret;
346 132 : ret.reserve (end - begin);
347 296 : for (auto it = begin; it != end; it++)
348 164 : ret.emplace_back (ASTLoweringPattern::translate (**it));
349 132 : return ret;
350 : }
351 :
352 : void
353 83 : ASTLoweringPattern::visit (AST::SlicePattern &pattern)
354 : {
355 83 : tl::optional<size_t> rest_index;
356 :
357 83 : std::vector<std::unique_ptr<AST::Pattern>> &sub_patterns
358 83 : = pattern.get_patterns ();
359 :
360 200 : for (size_t i = 0; i < sub_patterns.size (); i++)
361 : {
362 166 : auto &pat = sub_patterns[i];
363 166 : if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
364 : {
365 49 : rest_index = i;
366 : // ASTValidation verified there's only one Rest pattern
367 49 : break;
368 : }
369 : }
370 :
371 83 : std::unique_ptr<HIR::SlicePatternItems> items;
372 :
373 83 : if (rest_index)
374 : {
375 49 : auto rest_it = sub_patterns.begin () + *rest_index;
376 147 : items = std::make_unique<HIR::SlicePatternItemsHasRest> (
377 98 : lower_pattern_seq (sub_patterns.begin (), rest_it),
378 147 : lower_pattern_seq (rest_it + 1, sub_patterns.end ()));
379 : }
380 : else
381 : {
382 68 : items = std::make_unique<HIR::SlicePatternItemsNoRest> (
383 102 : lower_pattern_seq (sub_patterns.begin (), sub_patterns.end ()));
384 : }
385 :
386 83 : auto crate_num = mappings.get_current_crate ();
387 166 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
388 83 : mappings.get_next_hir_id (crate_num),
389 83 : UNKNOWN_LOCAL_DEFID);
390 :
391 83 : translated
392 83 : = new HIR::SlicePattern (mapping, std::move (items), pattern.get_locus ());
393 83 : }
394 :
395 : void
396 151 : ASTLoweringPattern::visit (AST::AltPattern &pattern)
397 : {
398 151 : auto crate_num = mappings.get_current_crate ();
399 302 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
400 151 : mappings.get_next_hir_id (crate_num),
401 151 : UNKNOWN_LOCAL_DEFID);
402 :
403 151 : std::vector<std::unique_ptr<HIR::Pattern>> alts;
404 151 : alts.reserve (pattern.get_alts ().size ());
405 :
406 454 : for (auto &alt : pattern.get_alts ())
407 303 : alts.emplace_back (ASTLoweringPattern::translate (*alt));
408 :
409 151 : translated
410 151 : = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ());
411 :
412 151 : if (is_let_top_level)
413 : {
414 1 : rich_location richloc (line_table, pattern.get_locus ());
415 1 : richloc.add_fixit_replace ("use an outer grouped pattern");
416 1 : rust_error_at (
417 : richloc, "top level or-patterns are not allowed for %<let%> bindings");
418 1 : }
419 151 : }
420 :
421 : } // namespace HIR
422 : } // namespace Rust
|