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 101796 : ASTLoweringPattern::ASTLoweringPattern ()
27 101796 : : translated (nullptr), is_let_top_level (false)
28 101796 : {}
29 :
30 : HIR::Pattern *
31 101796 : ASTLoweringPattern::translate (AST::Pattern &pattern, bool is_let_top_level)
32 : {
33 101796 : ASTLoweringPattern resolver;
34 101796 : resolver.is_let_top_level = is_let_top_level;
35 101796 : pattern.accept_vis (resolver);
36 :
37 101796 : rust_assert (resolver.translated != nullptr);
38 :
39 101796 : resolver.mappings.hir.patterns.insert (resolver.translated);
40 101796 : resolver.mappings.insert_location (
41 101796 : resolver.translated->get_mappings ().get_hirid (), pattern.get_locus ());
42 :
43 101796 : return resolver.translated;
44 101796 : }
45 :
46 : void
47 42348 : ASTLoweringPattern::visit (AST::IdentifierPattern &pattern)
48 : {
49 42348 : auto crate_num = mappings.crate.get_current_crate ();
50 84696 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
51 42348 : mappings.get_next_hir_id (crate_num),
52 42348 : UNKNOWN_LOCAL_DEFID);
53 :
54 42348 : std::unique_ptr<Pattern> subpattern;
55 42348 : if (pattern.has_subpattern ())
56 : {
57 42 : subpattern = std::unique_ptr<Pattern> (
58 42 : ASTLoweringPattern::translate (pattern.get_subpattern ()));
59 : }
60 42348 : translated
61 42348 : = new HIR::IdentifierPattern (mapping, pattern.get_ident (),
62 : pattern.get_locus (), pattern.get_is_ref (),
63 42348 : pattern.get_is_mut () ? Mutability::Mut
64 : : Mutability::Imm,
65 125041 : std::move (subpattern));
66 42348 : }
67 :
68 : void
69 1919 : ASTLoweringPattern::visit (AST::PathInExpression &pattern)
70 : {
71 1919 : translated = ASTLowerPathInExpression::translate (pattern);
72 1919 : }
73 :
74 : void
75 2340 : ASTLoweringPattern::visit (AST::TupleStructPattern &pattern)
76 : {
77 2340 : HIR::PathInExpression *path
78 2340 : = ASTLowerPathInExpression::translate (pattern.get_path ());
79 :
80 2340 : TupleStructItems *lowered = nullptr;
81 2340 : auto &items = pattern.get_items ();
82 2340 : switch (items.get_item_type ())
83 : {
84 52 : case AST::TupleStructItems::HAS_REST:
85 52 : {
86 52 : AST::TupleStructItemsHasRest &items_has_rest
87 : = static_cast<AST::TupleStructItemsHasRest &> (items);
88 :
89 52 : std::vector<std::unique_ptr<HIR::Pattern>> lower_patterns;
90 52 : lower_patterns.reserve (items_has_rest.get_lower_patterns ().size ());
91 89 : 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 52 : std::vector<std::unique_ptr<HIR::Pattern>> upper_patterns;
98 52 : upper_patterns.reserve (items_has_rest.get_upper_patterns ().size ());
99 75 : 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 52 : lowered = new HIR::TupleStructItemsHasRest (std::move (lower_patterns),
106 52 : std::move (upper_patterns));
107 52 : }
108 52 : break;
109 :
110 2288 : case AST::TupleStructItems::NO_REST:
111 2288 : {
112 2288 : AST::TupleStructItemsNoRest &items_no_rest
113 : = static_cast<AST::TupleStructItemsNoRest &> (items);
114 :
115 2288 : std::vector<std::unique_ptr<HIR::Pattern>> patterns;
116 2288 : patterns.reserve (items_no_rest.get_patterns ().size ());
117 :
118 4690 : for (auto &inner_pattern : items_no_rest.get_patterns ())
119 2402 : patterns.emplace_back (
120 2402 : ASTLoweringPattern::translate (*inner_pattern));
121 :
122 2288 : lowered = new HIR::TupleStructItemsNoRest (std::move (patterns));
123 2288 : }
124 2288 : break;
125 : }
126 :
127 2340 : auto crate_num = mappings.crate.get_current_crate ();
128 4680 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
129 2340 : mappings.get_next_hir_id (crate_num),
130 2340 : UNKNOWN_LOCAL_DEFID);
131 :
132 4680 : translated = new HIR::TupleStructPattern (
133 2340 : mapping, *path, std::unique_ptr<HIR::TupleStructItems> (lowered));
134 2340 : }
135 :
136 : void
137 249 : ASTLoweringPattern::visit (AST::StructPattern &pattern)
138 : {
139 249 : HIR::PathInExpression *path
140 249 : = ASTLowerPathInExpression::translate (pattern.get_path ());
141 :
142 249 : auto &raw_elems = pattern.get_struct_pattern_elems ();
143 :
144 249 : std::vector<std::unique_ptr<HIR::StructPatternField>> fields;
145 631 : for (auto &field : raw_elems.get_struct_pattern_fields ())
146 : {
147 382 : HIR::StructPatternField *f = nullptr;
148 382 : 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.crate.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 224 : case AST::StructPatternField::ItemType::IDENT_PAT:
172 224 : {
173 224 : AST::StructPatternFieldIdentPat &ident
174 224 : = static_cast<AST::StructPatternFieldIdentPat &> (*field);
175 :
176 224 : auto crate_num = mappings.crate.get_current_crate ();
177 224 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
178 224 : mappings.get_next_hir_id (crate_num),
179 224 : UNKNOWN_LOCAL_DEFID);
180 :
181 224 : std::unique_ptr<HIR::Pattern> pat (
182 224 : ASTLoweringPattern::translate (ident.get_ident_pattern ()));
183 :
184 224 : f = new HIR::StructPatternFieldIdentPat (mapping,
185 : ident.get_identifier (),
186 : std::move (pat),
187 224 : ident.get_outer_attrs (),
188 448 : ident.get_locus ());
189 224 : }
190 224 : break;
191 :
192 126 : case AST::StructPatternField::ItemType::IDENT:
193 126 : {
194 126 : AST::StructPatternFieldIdent &ident
195 126 : = static_cast<AST::StructPatternFieldIdent &> (*field.get ());
196 :
197 126 : auto crate_num = mappings.crate.get_current_crate ();
198 126 : Analysis::NodeMapping mapping (crate_num, ident.get_node_id (),
199 126 : mappings.get_next_hir_id (crate_num),
200 126 : UNKNOWN_LOCAL_DEFID);
201 :
202 126 : f = new HIR::StructPatternFieldIdent (
203 : mapping, ident.get_identifier (), ident.is_ref (),
204 126 : ident.is_mut () ? Mutability::Mut : Mutability::Imm,
205 376 : ident.get_outer_attrs (), ident.get_locus ());
206 : }
207 126 : break;
208 : }
209 :
210 : // insert the reverse mappings and locations
211 382 : auto field_id = f->get_mappings ().get_hirid ();
212 382 : auto field_node_id = f->get_mappings ().get_nodeid ();
213 382 : mappings.insert_location (field_id, f->get_locus ());
214 382 : mappings.insert_node_to_hir (field_node_id, field_id);
215 :
216 : // add it to the lowered fields list
217 382 : fields.emplace_back (f);
218 : }
219 :
220 249 : auto crate_num = mappings.crate.get_current_crate ();
221 498 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
222 249 : mappings.get_next_hir_id (crate_num),
223 249 : UNKNOWN_LOCAL_DEFID);
224 :
225 249 : HIR::StructPatternElements elems (
226 249 : std::move (fields), pattern.get_struct_pattern_elems ().has_rest ());
227 249 : translated = new HIR::StructPattern (mapping, *path, std::move (elems));
228 249 : }
229 :
230 : void
231 5559 : ASTLoweringPattern::visit (AST::WildcardPattern &pattern)
232 : {
233 5559 : auto crate_num = mappings.crate.get_current_crate ();
234 11118 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
235 5559 : mappings.get_next_hir_id (crate_num),
236 5559 : UNKNOWN_LOCAL_DEFID);
237 :
238 5559 : translated = new HIR::WildcardPattern (mapping, pattern.get_locus ());
239 5559 : }
240 :
241 : void
242 3049 : ASTLoweringPattern::visit (AST::TuplePattern &pattern)
243 : {
244 3049 : std::unique_ptr<HIR::TuplePatternItems> items;
245 3049 : switch (pattern.get_items ().get_item_type ())
246 : {
247 3011 : case AST::TuplePatternItems::ItemType::NO_REST:
248 3011 : {
249 3011 : AST::TuplePatternItemsNoRest &ref
250 3011 : = static_cast<AST::TuplePatternItemsNoRest &> (pattern.get_items ());
251 3011 : items = lower_tuple_pattern_multiple (ref);
252 : }
253 3011 : 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 3049 : auto crate_num = mappings.crate.get_current_crate ();
265 6098 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
266 3049 : mappings.get_next_hir_id (crate_num),
267 3049 : UNKNOWN_LOCAL_DEFID);
268 :
269 3049 : translated
270 3049 : = new HIR::TuplePattern (mapping, std::move (items), pattern.get_locus ());
271 3049 : }
272 :
273 : void
274 45531 : ASTLoweringPattern::visit (AST::LiteralPattern &pattern)
275 : {
276 45531 : auto crate_num = mappings.crate.get_current_crate ();
277 91062 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
278 45531 : mappings.get_next_hir_id (crate_num),
279 45531 : UNKNOWN_LOCAL_DEFID);
280 :
281 45531 : HIR::Literal l = lower_literal (pattern.get_literal ());
282 45531 : translated
283 45531 : = new HIR::LiteralPattern (mapping, std::move (l), pattern.get_locus (),
284 91062 : pattern.get_has_minus ());
285 45531 : }
286 :
287 : void
288 119 : ASTLoweringPattern::visit (AST::RangePattern &pattern)
289 : {
290 119 : auto upper_bound = lower_range_pattern_bound (pattern.get_upper_bound ());
291 119 : auto lower_bound = lower_range_pattern_bound (pattern.get_lower_bound ());
292 :
293 119 : auto crate_num = mappings.crate.get_current_crate ();
294 238 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
295 119 : mappings.get_next_hir_id (crate_num),
296 119 : UNKNOWN_LOCAL_DEFID);
297 :
298 119 : bool is_inclusive = (pattern.get_range_kind () == AST::RangeKind::INCLUDED);
299 :
300 119 : translated = new HIR::RangePattern (mapping, std::move (lower_bound),
301 : std::move (upper_bound),
302 119 : pattern.get_locus (), is_inclusive);
303 119 : }
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 393 : ASTLoweringPattern::visit (AST::ReferencePattern &pattern)
314 : {
315 393 : auto crate_num = mappings.crate.get_current_crate ();
316 786 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
317 393 : mappings.get_next_hir_id (crate_num),
318 393 : UNKNOWN_LOCAL_DEFID);
319 :
320 393 : HIR::Pattern *inner
321 393 : = ASTLoweringPattern::translate (pattern.get_referenced_pattern ());
322 :
323 393 : translated
324 393 : = new HIR::ReferencePattern (mapping, std::unique_ptr<HIR::Pattern> (inner),
325 393 : pattern.get_is_mut () ? Mutability::Mut
326 : : Mutability::Imm,
327 784 : pattern.get_locus ());
328 :
329 393 : if (pattern.is_double_reference ())
330 : {
331 26 : Analysis::NodeMapping mapping2 (crate_num, pattern.get_node_id (),
332 13 : mappings.get_next_hir_id (crate_num),
333 13 : UNKNOWN_LOCAL_DEFID);
334 13 : translated
335 13 : = new HIR::ReferencePattern (mapping2,
336 13 : std::unique_ptr<HIR::Pattern> (translated),
337 13 : Mutability::Imm, pattern.get_locus ());
338 : }
339 393 : }
340 :
341 : template <typename It>
342 : static std::vector<std::unique_ptr<HIR::Pattern>>
343 166 : lower_pattern_seq (It begin, It end)
344 : {
345 166 : std::vector<std::unique_ptr<HIR::Pattern>> ret;
346 166 : ret.reserve (end - begin);
347 353 : for (auto it = begin; it != end; it++)
348 187 : ret.emplace_back (ASTLoweringPattern::translate (**it));
349 166 : return ret;
350 : }
351 :
352 : void
353 103 : ASTLoweringPattern::visit (AST::SlicePattern &pattern)
354 : {
355 103 : tl::optional<size_t> rest_index;
356 103 : tl::optional<HIR::IdentifierPattern> rest_bind;
357 :
358 103 : std::vector<std::unique_ptr<AST::Pattern>> &sub_patterns
359 103 : = pattern.get_patterns ();
360 :
361 : // need this earlier than usual
362 : // since we might need to produce rest_bind
363 103 : auto crate_num = mappings.crate.get_current_crate ();
364 :
365 342 : for (size_t i = 0; i < sub_patterns.size (); i++)
366 : {
367 199 : 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 199 : if (pat->get_pattern_kind () == AST::Pattern::Kind::Identifier)
372 : {
373 46 : auto &ident_pat = static_cast<AST::IdentifierPattern &> (*pat);
374 46 : if (ident_pat.has_subpattern ())
375 : {
376 5 : if (ident_pat.get_subpattern ().get_pattern_kind ()
377 : == AST::Pattern::Kind::Rest)
378 : {
379 5 : Analysis::NodeMapping rest_bind_mapping (
380 5 : crate_num, ident_pat.get_node_id (),
381 5 : mappings.get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID);
382 :
383 5 : rest_bind = HIR::IdentifierPattern (
384 10 : std::move (rest_bind_mapping), ident_pat.get_ident (),
385 : ident_pat.get_locus (), ident_pat.get_is_ref (),
386 5 : ident_pat.get_is_mut () ? Mutability::Mut
387 15 : : Mutability::Imm);
388 5 : rest_index = i;
389 5 : break;
390 : }
391 : }
392 : }
393 153 : else if (pat->get_pattern_kind () == AST::Pattern::Kind::Rest)
394 : {
395 58 : rest_index = i;
396 58 : break;
397 : }
398 : }
399 :
400 103 : std::unique_ptr<HIR::SlicePatternItems> items;
401 :
402 103 : if (rest_index)
403 : {
404 63 : auto rest_it = sub_patterns.begin () + *rest_index;
405 189 : items = std::make_unique<HIR::SlicePatternItemsHasRest> (
406 126 : lower_pattern_seq (sub_patterns.begin (), rest_it),
407 126 : lower_pattern_seq (rest_it + 1, sub_patterns.end ()),
408 63 : std::move (rest_bind));
409 : }
410 : else
411 : {
412 80 : items = std::make_unique<HIR::SlicePatternItemsNoRest> (
413 120 : lower_pattern_seq (sub_patterns.begin (), sub_patterns.end ()));
414 : }
415 :
416 206 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
417 103 : mappings.get_next_hir_id (crate_num),
418 103 : UNKNOWN_LOCAL_DEFID);
419 :
420 103 : translated
421 103 : = new HIR::SlicePattern (mapping, std::move (items), pattern.get_locus ());
422 103 : }
423 :
424 : void
425 186 : ASTLoweringPattern::visit (AST::AltPattern &pattern)
426 : {
427 186 : auto crate_num = mappings.crate.get_current_crate ();
428 372 : Analysis::NodeMapping mapping (crate_num, pattern.get_node_id (),
429 186 : mappings.get_next_hir_id (crate_num),
430 186 : UNKNOWN_LOCAL_DEFID);
431 :
432 186 : std::vector<std::unique_ptr<HIR::Pattern>> alts;
433 186 : alts.reserve (pattern.get_alts ().size ());
434 :
435 582 : for (auto &alt : pattern.get_alts ())
436 396 : alts.emplace_back (ASTLoweringPattern::translate (*alt));
437 :
438 186 : translated
439 186 : = new HIR::AltPattern (mapping, std::move (alts), pattern.get_locus ());
440 :
441 186 : 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 186 : }
449 :
450 : } // namespace HIR
451 : } // namespace Rust
|