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-hir-type-check-pattern.h"
20 : #include "rust-hir-pattern.h"
21 : #include "rust-hir-type-check-expr.h"
22 : #include "rust-token.h"
23 : #include "rust-type-util.h"
24 : #include "rust-immutable-name-resolution-context.h"
25 : #include "rust-tyty.h"
26 : #include "tree.h"
27 :
28 : namespace Rust {
29 : namespace Resolver {
30 :
31 43746 : TypeCheckPattern::TypeCheckPattern (TyTy::BaseType *parent)
32 43746 : : TypeCheckBase (), parent (parent), infered (new TyTy::ErrorType (0))
33 43746 : {}
34 :
35 : TyTy::BaseType *
36 43746 : TypeCheckPattern::Resolve (HIR::Pattern &pattern, TyTy::BaseType *parent)
37 : {
38 43746 : TypeCheckPattern resolver (parent);
39 43746 : pattern.accept_vis (resolver);
40 :
41 43746 : if (resolver.infered == nullptr)
42 0 : return new TyTy::ErrorType (pattern.get_mappings ().get_hirid ());
43 :
44 43746 : resolver.context->insert_type (pattern.get_mappings (), resolver.infered);
45 43746 : return resolver.infered;
46 43746 : }
47 :
48 : void
49 1086 : TypeCheckPattern::visit (HIR::PathInExpression &pattern)
50 : {
51 : // Pattern must be enum variants, sturcts, constants, or associated constansts
52 1086 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern);
53 :
54 1086 : NodeId ref_node_id = UNKNOWN_NODEID;
55 1086 : bool maybe_item = false;
56 :
57 1086 : auto &nr_ctx
58 1086 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
59 :
60 1086 : if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
61 : {
62 1084 : ref_node_id = *id;
63 1084 : maybe_item = true;
64 : }
65 :
66 1086 : bool path_is_const_item = false;
67 :
68 1086 : if (maybe_item)
69 : {
70 1084 : tl::optional<HirId> definition_id
71 1084 : = mappings.lookup_node_to_hir (ref_node_id);
72 1084 : rust_assert (definition_id.has_value ());
73 1084 : HirId def_id = definition_id.value ();
74 :
75 1084 : tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
76 : // If the path refrerences an item, it must be constants or structs.
77 1084 : if (hir_item.has_value ())
78 : {
79 5 : HIR::Item *item = hir_item.value ();
80 5 : if (item->get_item_kind () == HIR::Item::ItemKind::Constant)
81 : {
82 : path_is_const_item = true;
83 : }
84 4 : else if (item->get_item_kind () != HIR::Item::ItemKind::Struct)
85 : {
86 4 : HIR::Item *item = hir_item.value ();
87 4 : std::string item_kind
88 4 : = HIR::Item::item_kind_string (item->get_item_kind ());
89 :
90 4 : std::string path_buf;
91 12 : for (size_t i = 0; i < pattern.get_segments ().size (); i++)
92 : {
93 8 : HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
94 16 : path_buf += seg.to_string ();
95 8 : if (i != pattern.get_segments ().size () - 1)
96 4 : path_buf += "::";
97 : }
98 :
99 4 : rich_location rich_locus (
100 4 : line_table, pattern.get_final_segment ().get_locus ());
101 4 : rich_locus.add_fixit_replace (
102 : "not a unit struct, unit variant or constant");
103 4 : rust_error_at (rich_locus, ErrorCode::E0532,
104 : "expected unit struct, unit variant or constant, "
105 : "found %s %<%s%>",
106 : item_kind.c_str (), path_buf.c_str ());
107 4 : return;
108 4 : }
109 : }
110 : }
111 :
112 : // If the path is a constructor, it must be a unit struct or unit variants.
113 1082 : if (!path_is_const_item && pattern_ty->get_kind () == TyTy::TypeKind::ADT)
114 : {
115 1079 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (pattern_ty);
116 1079 : rust_assert (adt->get_variants ().size () > 0);
117 :
118 1079 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
119 1079 : if (adt->is_enum ())
120 : {
121 1079 : HirId variant_id = UNKNOWN_HIRID;
122 1079 : bool ok = context->lookup_variant_definition (
123 1079 : pattern.get_mappings ().get_hirid (), &variant_id);
124 1079 : rust_assert (ok);
125 :
126 1079 : ok = adt->lookup_variant_by_id (variant_id, &variant);
127 1079 : rust_assert (ok);
128 : }
129 :
130 1079 : if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
131 : {
132 3 : std::string variant_type = TyTy::VariantDef::variant_type_string (
133 3 : variant->get_variant_type ());
134 :
135 3 : rich_location rich_locus (line_table,
136 3 : pattern.get_final_segment ().get_locus ());
137 3 : rich_locus.add_fixit_replace (
138 : "not a unit struct, unit variant or constatnt");
139 3 : rust_error_at (rich_locus, ErrorCode::E0532,
140 : "expected unit struct, unit variant or constant, "
141 : "found %s variant %<%s::%s%>",
142 6 : variant_type.c_str (), adt->get_name ().c_str (),
143 3 : variant->get_identifier ().c_str ());
144 3 : return;
145 3 : }
146 :
147 1076 : infered = pattern_ty;
148 : }
149 : }
150 :
151 : void
152 1003 : TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
153 : {
154 1003 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
155 1003 : if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
156 : {
157 2 : rust_error_at (
158 2 : pattern.get_locus (), ErrorCode::E0532,
159 : "expected tuple struct or tuple variant, found function %qs",
160 2 : pattern_ty->get_name ().c_str ());
161 6 : return;
162 : }
163 :
164 1001 : infered = pattern_ty;
165 1001 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
166 :
167 1001 : TyTy::VariantDef *variant = nullptr;
168 1001 : if (adt->is_enum ())
169 : {
170 939 : HirId variant_id = UNKNOWN_HIRID;
171 939 : bool ok = context->lookup_variant_definition (
172 939 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
173 939 : if (!ok)
174 : {
175 3 : rust_error_at (
176 3 : pattern.get_locus (), ErrorCode::E0532,
177 : "expected tuple struct or tuple variant, found enum %qs",
178 3 : pattern_ty->get_name ().c_str ());
179 3 : return;
180 : }
181 :
182 936 : ok = adt->lookup_variant_by_id (variant_id, &variant);
183 936 : rust_assert (ok);
184 : }
185 : else
186 : {
187 62 : rust_assert (adt->number_of_variants () > 0);
188 62 : variant = adt->get_variants ().at (0);
189 : }
190 :
191 998 : rust_assert (variant != nullptr);
192 :
193 : // error[E0532]: expected tuple struct or tuple variant, found struct
194 : // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
195 998 : if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
196 : {
197 1 : std::string variant_type
198 1 : = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
199 :
200 1 : rich_location rich_locus (line_table, pattern.get_locus ());
201 1 : rich_locus.add_fixit_replace ("not a tuple struct or tuple variant");
202 1 : rust_error_at (
203 : rich_locus, ErrorCode::E0164,
204 : "expected tuple struct or tuple variant, found %s variant %<%s::%s%>",
205 2 : variant_type.c_str (), adt->get_name ().c_str (),
206 1 : variant->get_identifier ().c_str ());
207 1 : return;
208 1 : }
209 :
210 : // check the elements
211 : // error[E0023]: this pattern has 2 fields, but the corresponding tuple
212 : // variant has 1 field
213 : // error[E0023]: this pattern has 0 fields, but the corresponding tuple
214 : // variant has 1 field
215 :
216 997 : auto &items = pattern.get_items ();
217 997 : switch (items.get_item_type ())
218 : {
219 38 : case HIR::TupleStructItems::HAS_REST:
220 38 : {
221 38 : HIR::TupleStructItemsHasRest &items_has_rest
222 : = static_cast<HIR::TupleStructItemsHasRest &> (items);
223 38 : auto &lower_patterns = items_has_rest.get_lower_patterns ();
224 38 : auto &upper_patterns = items_has_rest.get_upper_patterns ();
225 38 : size_t pattern_min_cap
226 38 : = lower_patterns.size () + upper_patterns.size ();
227 38 : if (variant->num_fields () < pattern_min_cap)
228 : {
229 2 : if (!lower_patterns.empty ())
230 : {
231 : // TODO initialize rich_locus with loc of ADT definition instead
232 1 : rich_location rich_locus (line_table,
233 1 : lower_patterns[0]->get_locus ());
234 3 : for (auto &pattern : lower_patterns)
235 : {
236 2 : if (pattern == lower_patterns[0])
237 1 : continue;
238 1 : rich_locus.add_range (pattern->get_locus (),
239 : SHOW_RANGE_WITH_CARET);
240 : }
241 3 : for (auto &pattern : upper_patterns)
242 : {
243 2 : rich_locus.add_range (pattern->get_locus (),
244 : SHOW_RANGE_WITH_CARET);
245 : }
246 3 : rust_error_at (rich_locus, ErrorCode::E0023,
247 : "this pattern has %lu %s but the corresponding "
248 : "tuple variant has %lu %s",
249 : (unsigned long) (pattern_min_cap),
250 : pattern_min_cap == 1 ? "field" : "fields",
251 1 : (unsigned long) variant->num_fields (),
252 1 : variant->num_fields () == 1 ? "field"
253 : : "fields");
254 1 : }
255 : else
256 : {
257 : // TODO initialize rich_locus with loc of ADT definition instead
258 1 : rich_location rich_locus (line_table,
259 1 : upper_patterns[0]->get_locus ());
260 4 : for (auto &pattern : upper_patterns)
261 : {
262 3 : if (pattern == upper_patterns[0])
263 1 : continue;
264 2 : rich_locus.add_range (pattern->get_locus (),
265 : SHOW_RANGE_WITH_CARET);
266 : }
267 3 : rust_error_at (rich_locus, ErrorCode::E0023,
268 : "this pattern has %lu %s but the corresponding "
269 : "tuple variant has %lu %s",
270 : (unsigned long) (pattern_min_cap),
271 : pattern_min_cap == 1 ? "field" : "fields",
272 1 : (unsigned long) variant->num_fields (),
273 1 : variant->num_fields () == 1 ? "field"
274 : : "fields");
275 1 : }
276 : // we continue on to try and setup the types as best we can for
277 : // type checking
278 : }
279 :
280 : // iterate the fields manually to set them up
281 38 : size_t i = 0;
282 69 : for (auto &pattern : lower_patterns)
283 : {
284 31 : if (i >= variant->num_fields ())
285 : break;
286 :
287 31 : TyTy::StructFieldType *field = variant->get_field_at_index (i++);
288 31 : TyTy::BaseType *fty = field->get_field_type ();
289 :
290 : // setup the type on this pattern type
291 31 : context->insert_type (pattern->get_mappings (), fty);
292 31 : TypeCheckPattern::Resolve (*pattern, fty);
293 : }
294 :
295 38 : i = variant->num_fields () - upper_patterns.size ();
296 54 : for (auto &pattern : upper_patterns)
297 : {
298 17 : if (i >= variant->num_fields ())
299 : break;
300 :
301 16 : TyTy::StructFieldType *field = variant->get_field_at_index (i++);
302 16 : TyTy::BaseType *fty = field->get_field_type ();
303 :
304 : // setup the type on this pattern type
305 16 : context->insert_type (pattern->get_mappings (), fty);
306 16 : TypeCheckPattern::Resolve (*pattern, fty);
307 : }
308 : }
309 : break;
310 :
311 959 : case HIR::TupleStructItems::NO_REST:
312 959 : {
313 959 : HIR::TupleStructItemsNoRest &items_no_rest
314 : = static_cast<HIR::TupleStructItemsNoRest &> (items);
315 959 : auto &patterns = items_no_rest.get_patterns ();
316 :
317 959 : if (patterns.size () != variant->num_fields ())
318 : {
319 2 : if (patterns.empty ())
320 : {
321 0 : rust_error_at (pattern.get_locus (), ErrorCode::E0023,
322 : "this pattern has %lu %s but the corresponding "
323 : "tuple variant has %lu %s",
324 0 : (unsigned long) patterns.size (),
325 0 : patterns.size () == 1 ? "field" : "fields",
326 0 : (unsigned long) variant->num_fields (),
327 0 : variant->num_fields () == 1 ? "field"
328 : : "fields");
329 : }
330 : else
331 : {
332 2 : rich_location rich_locus (line_table,
333 2 : patterns[0]->get_locus ());
334 8 : for (auto &pattern : items_no_rest.get_patterns ())
335 : {
336 6 : if (pattern == patterns[0])
337 2 : continue;
338 4 : rich_locus.add_range (pattern->get_locus (),
339 : SHOW_RANGE_WITH_CARET);
340 : }
341 2 : rust_error_at (rich_locus, ErrorCode::E0023,
342 : "this pattern has %lu %s but the corresponding "
343 : "tuple variant has %lu %s",
344 2 : (unsigned long) patterns.size (),
345 2 : patterns.size () == 1 ? "field" : "fields",
346 2 : (unsigned long) variant->num_fields (),
347 2 : variant->num_fields () == 1 ? "field"
348 : : "fields");
349 2 : }
350 : // we continue on to try and setup the types as best we can for
351 : // type checking
352 : }
353 :
354 : // iterate the fields and set them up, I wish we had ZIP
355 959 : size_t i = 0;
356 1993 : for (auto &pattern : items_no_rest.get_patterns ())
357 : {
358 1036 : if (i >= variant->num_fields ())
359 : break;
360 :
361 1034 : TyTy::StructFieldType *field = variant->get_field_at_index (i++);
362 1034 : TyTy::BaseType *fty = field->get_field_type ();
363 :
364 : // setup the type on this pattern type
365 1034 : context->insert_type (pattern->get_mappings (), fty);
366 1034 : TypeCheckPattern::Resolve (*pattern, fty);
367 : }
368 : }
369 : break;
370 : }
371 : }
372 :
373 : void
374 3 : emit_invalid_field_error (location_t loc, Rust::TyTy::VariantDef *variant,
375 : const std::string &name)
376 : {
377 3 : rust_error_at (loc, ErrorCode::E0026,
378 : "variant %s does not have a field named %s",
379 3 : variant->get_identifier ().c_str (), name.c_str ());
380 3 : }
381 :
382 : void
383 164 : TypeCheckPattern::visit (HIR::StructPattern &pattern)
384 : {
385 164 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
386 164 : if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
387 : {
388 0 : rust_error_at (pattern.get_locus (),
389 : "expected tuple struct/variant, found: %s",
390 0 : pattern_ty->get_name ().c_str ());
391 3 : return;
392 : }
393 :
394 164 : infered = pattern_ty;
395 164 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
396 164 : if (adt->number_of_variants () == 0)
397 : {
398 0 : HIR::PathInExpression &path = pattern.get_path ();
399 0 : const AST::SimplePath &sp = path.as_simple_path ();
400 0 : rust_error_at (pattern.get_locus (), ErrorCode::E0574,
401 : "expected struct, variant or union type, found enum %qs",
402 0 : sp.as_string ().c_str ());
403 0 : return;
404 0 : }
405 :
406 164 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
407 164 : if (adt->is_enum ())
408 : {
409 118 : HirId variant_id = UNKNOWN_HIRID;
410 118 : bool ok = context->lookup_variant_definition (
411 118 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
412 118 : if (!ok)
413 : {
414 1 : HIR::PathInExpression &path = pattern.get_path ();
415 1 : const AST::SimplePath &sp = path.as_simple_path ();
416 1 : rust_error_at (
417 1 : pattern.get_locus (), ErrorCode::E0574,
418 : "expected struct, variant or union type, found enum %qs",
419 1 : sp.as_string ().c_str ());
420 1 : return;
421 1 : }
422 :
423 117 : ok = adt->lookup_variant_by_id (variant_id, &variant);
424 117 : rust_assert (ok);
425 : }
426 :
427 : // error[E0532]: expected tuple struct or tuple variant, found struct
428 : // variant `Foo::D`
429 163 : bool error_E0532 = false;
430 163 : if (variant->get_variant_type () == TyTy::VariantDef::VariantType::TUPLE)
431 : {
432 : // Tuple structs can still be matched with struct patterns via index
433 : // numbers e.g. Foo {0: a, .., 3: b}, so check whether the fields are of
434 : // type TUPLE_PAT. Throw E0532 if not.
435 16 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
436 39 : for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
437 : {
438 25 : if (field->get_item_type ()
439 : != HIR::StructPatternField::ItemType::TUPLE_PAT)
440 : {
441 : error_E0532 = true;
442 : break;
443 : }
444 : }
445 : }
446 147 : else if (variant->get_variant_type ()
447 : != TyTy::VariantDef::VariantType::STRUCT)
448 : {
449 : error_E0532 = true;
450 : }
451 :
452 16 : if (error_E0532)
453 : {
454 2 : std::string variant_type
455 2 : = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
456 :
457 2 : rich_location rich_locus (line_table, pattern.get_locus ());
458 2 : std::string rich_msg = "use the tuple variant pattern syntax instead "
459 4 : + variant->get_identifier () + "(_)";
460 2 : rich_locus.add_fixit_replace (rich_msg.c_str ());
461 :
462 2 : rust_error_at (rich_locus, ErrorCode::E0769,
463 : "%s variant %qs written as struct variant",
464 : variant_type.c_str (),
465 2 : variant->get_identifier ().c_str ());
466 2 : return;
467 2 : }
468 :
469 161 : std::vector<std::string> named_fields;
470 161 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
471 432 : for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
472 : {
473 271 : switch (field->get_item_type ())
474 : {
475 23 : case HIR::StructPatternField::ItemType::TUPLE_PAT:
476 23 : {
477 23 : HIR::StructPatternFieldTuplePat &tuple_pat
478 23 : = static_cast<HIR::StructPatternFieldTuplePat &> (*field.get ());
479 :
480 23 : if ((size_t) tuple_pat.get_index () >= variant->num_fields ())
481 : {
482 2 : emit_invalid_field_error (tuple_pat.get_locus (), variant,
483 2 : std::to_string (
484 : tuple_pat.get_index ()));
485 2 : break;
486 : }
487 21 : named_fields.push_back (std::to_string (tuple_pat.get_index ()));
488 21 : TyTy::StructFieldType *field
489 21 : = variant->get_field_at_index (tuple_pat.get_index ());
490 21 : TyTy::BaseType *fty = field->get_field_type ();
491 21 : TypeCheckPattern::Resolve (tuple_pat.get_tuple_pattern (), fty);
492 : }
493 21 : break;
494 :
495 150 : case HIR::StructPatternField::ItemType::IDENT_PAT:
496 150 : {
497 150 : HIR::StructPatternFieldIdentPat &ident
498 150 : = static_cast<HIR::StructPatternFieldIdentPat &> (*field);
499 :
500 150 : TyTy::StructFieldType *field = nullptr;
501 150 : if (!variant->lookup_field (ident.get_identifier ().as_string (),
502 : &field, nullptr))
503 : {
504 0 : emit_invalid_field_error (ident.get_locus (), variant,
505 0 : ident.get_identifier ().as_string ());
506 0 : break;
507 : }
508 150 : named_fields.push_back (ident.get_identifier ().as_string ());
509 :
510 150 : TyTy::BaseType *fty = field->get_field_type ();
511 150 : TypeCheckPattern::Resolve (ident.get_pattern (), fty);
512 : }
513 150 : break;
514 :
515 98 : case HIR::StructPatternField::ItemType::IDENT:
516 98 : {
517 98 : HIR::StructPatternFieldIdent &ident
518 98 : = static_cast<HIR::StructPatternFieldIdent &> (*field);
519 :
520 98 : TyTy::StructFieldType *field = nullptr;
521 98 : if (!variant->lookup_field (ident.get_identifier ().as_string (),
522 : &field, nullptr))
523 : {
524 1 : emit_invalid_field_error (ident.get_locus (), variant,
525 1 : ident.get_identifier ().as_string ());
526 1 : break;
527 : }
528 97 : named_fields.push_back (ident.get_identifier ().as_string ());
529 :
530 : // setup the type on this pattern
531 97 : TyTy::BaseType *fty = field->get_field_type ();
532 97 : context->insert_type (ident.get_mappings (), fty);
533 : }
534 97 : break;
535 : }
536 : }
537 :
538 : // check the elements
539 161 : if (adt->is_union ())
540 : {
541 5 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
542 5 : if (struct_pattern_elems.get_struct_pattern_fields ().size () != 1)
543 2 : rust_error_at (pattern.get_locus (),
544 : "union patterns should have exactly one field");
545 :
546 : else
547 : {
548 6 : switch (struct_pattern_elems.get_struct_pattern_fields ()
549 3 : .at (0)
550 3 : ->get_item_type ())
551 : {
552 : case HIR::StructPatternField::ItemType::IDENT:
553 : case HIR::StructPatternField::ItemType::IDENT_PAT:
554 : break;
555 0 : default:
556 0 : {
557 0 : auto first_elem
558 0 : = struct_pattern_elems.get_struct_pattern_fields ()
559 0 : .at (0)
560 0 : ->to_string ();
561 0 : rust_error_at (pattern.get_locus (),
562 : "%qs cannot be used in union patterns",
563 : first_elem.c_str ());
564 0 : }
565 : }
566 : }
567 : }
568 : else
569 : {
570 : // Expects enum struct or struct struct.
571 : // error[E0027]: pattern does not mention fields `x`, `y`
572 : // error[E0026]: variant `Foo::D` does not have a field named `b`
573 156 : if (!pattern.get_struct_pattern_elems ().has_rest ()
574 307 : && named_fields.size () != variant->num_fields ())
575 : {
576 3 : std::map<std::string, bool> missing_names;
577 :
578 : // populate with all fields
579 9 : for (auto &field : variant->get_fields ())
580 6 : missing_names[field->get_name ()] = true;
581 :
582 : // then eliminate with named_fields
583 4 : for (auto &named : named_fields)
584 1 : missing_names.erase (named);
585 :
586 : // then get the list of missing names
587 3 : size_t i = 0;
588 3 : std::string missing_fields_str;
589 8 : for (auto it = missing_names.begin (); it != missing_names.end ();
590 5 : it++)
591 : {
592 5 : bool has_next = (i + 1) < missing_names.size ();
593 13 : missing_fields_str += it->first + (has_next ? ", " : "");
594 5 : i++;
595 : }
596 :
597 3 : rust_error_at (pattern.get_locus (), ErrorCode::E0027,
598 : "pattern does not mention fields %s",
599 : missing_fields_str.c_str ());
600 3 : }
601 : }
602 161 : }
603 :
604 : void
605 1250 : TypeCheckPattern::visit (HIR::WildcardPattern &pattern)
606 : {
607 : // wildcard patterns within the MatchArm's are simply just the same type as
608 : // the parent
609 1250 : infered = parent->clone ();
610 1250 : infered->set_ref (pattern.get_mappings ().get_hirid ());
611 1250 : }
612 :
613 : void
614 424 : TypeCheckPattern::visit (HIR::TuplePattern &pattern)
615 : {
616 424 : std::unique_ptr<HIR::TuplePatternItems> items;
617 :
618 : // Check whether parent is tuple
619 424 : auto resolved_parent = parent->destructure ();
620 424 : if (resolved_parent->get_kind () != TyTy::TUPLE)
621 : {
622 3 : rust_error_at (pattern.get_locus (), "expected %s, found tuple",
623 3 : parent->as_string ().c_str ());
624 3 : return;
625 : }
626 421 : TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent);
627 :
628 421 : switch (pattern.get_items ().get_item_type ())
629 : {
630 394 : case HIR::TuplePatternItems::ItemType::NO_REST:
631 394 : {
632 394 : auto &ref
633 394 : = static_cast<HIR::TuplePatternItemsNoRest &> (pattern.get_items ());
634 :
635 394 : const auto &patterns = ref.get_patterns ();
636 394 : size_t nitems_to_resolve = patterns.size ();
637 :
638 394 : if (patterns.size () != par.get_fields ().size ())
639 : {
640 4 : emit_pattern_size_error (pattern, par.get_fields ().size (),
641 : patterns.size ());
642 4 : nitems_to_resolve
643 4 : = std::min (nitems_to_resolve, par.get_fields ().size ());
644 : }
645 :
646 394 : std::vector<TyTy::TyVar> pattern_elems;
647 1197 : for (size_t i = 0; i < nitems_to_resolve; i++)
648 : {
649 803 : auto &p = patterns[i];
650 803 : TyTy::BaseType *par_type = par.get_field (i);
651 :
652 803 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
653 803 : pattern_elems.emplace_back (elem->get_ref ());
654 : }
655 788 : infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
656 788 : pattern.get_locus (), pattern_elems);
657 394 : }
658 394 : break;
659 :
660 27 : case HIR::TuplePatternItems::ItemType::HAS_REST:
661 27 : {
662 27 : HIR::TuplePatternItemsHasRest &ref
663 27 : = static_cast<HIR::TuplePatternItemsHasRest &> (pattern.get_items ());
664 :
665 27 : const auto &lower = ref.get_lower_patterns ();
666 27 : const auto &upper = ref.get_upper_patterns ();
667 27 : size_t min_size_required = lower.size () + upper.size ();
668 :
669 : // Ensure that size of lower and upper patterns <= parent size
670 27 : if (min_size_required > par.get_fields ().size ())
671 : {
672 3 : emit_pattern_size_error (pattern, par.get_fields ().size (),
673 : min_size_required);
674 : // continue and attempt to resolve individual items in the pattern
675 : }
676 :
677 : // Resolve lower patterns
678 27 : std::vector<TyTy::TyVar> pattern_elems;
679 27 : size_t nlower_items_to_resolve
680 27 : = std::min (lower.size (), par.get_fields ().size ());
681 55 : for (size_t i = 0; i < nlower_items_to_resolve; i++)
682 : {
683 28 : auto &p = lower[i];
684 28 : TyTy::BaseType *par_type = par.get_field (i);
685 :
686 28 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
687 28 : pattern_elems.emplace_back (elem->get_ref ());
688 : }
689 :
690 27 : if (lower.size () > par.get_fields ().size ())
691 : break;
692 :
693 : // Pad pattern_elems until needing to resolve upper patterns
694 27 : size_t rest_end
695 27 : = std::max (par.get_fields ().size () - upper.size (), lower.size ());
696 71 : for (size_t i = lower.size (); i < rest_end; i++)
697 : {
698 44 : TyTy::BaseType *par_type = par.get_field (i);
699 44 : pattern_elems.emplace_back (par_type->get_ref ());
700 : }
701 :
702 27 : size_t nupper_items_to_resolve
703 27 : = std::min (upper.size (),
704 27 : par.get_fields ().size () - pattern_elems.size ());
705 : // Resolve upper patterns
706 55 : for (size_t i = 0; i < nupper_items_to_resolve; i++)
707 : {
708 28 : auto &p = upper[i];
709 28 : TyTy::BaseType *par_type = par.get_field (rest_end + i);
710 :
711 28 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
712 28 : pattern_elems.emplace_back (elem->get_ref ());
713 : }
714 :
715 54 : infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
716 54 : pattern.get_locus (), pattern_elems);
717 0 : }
718 27 : break;
719 : }
720 424 : }
721 :
722 : void
723 425 : TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
724 : {
725 425 : TyTy::BaseType *resolved
726 425 : = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
727 425 : pattern.get_locus ());
728 425 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
729 : {
730 0 : infered = resolved;
731 0 : return;
732 : }
733 :
734 425 : infered = unify_site (pattern.get_mappings ().get_hirid (),
735 425 : TyTy::TyWithLocation (parent),
736 425 : TyTy::TyWithLocation (resolved), pattern.get_locus ());
737 : }
738 :
739 : void
740 40 : TypeCheckPattern::visit (HIR::RangePattern &pattern)
741 : {
742 : // Resolve the upper and lower bounds, and ensure they are compatible types
743 40 : TyTy::BaseType *upper = nullptr, *lower = nullptr;
744 :
745 40 : upper = typecheck_range_pattern_bound (pattern.get_upper_bound (),
746 40 : pattern.get_mappings (),
747 40 : pattern.get_locus ());
748 :
749 120 : lower = typecheck_range_pattern_bound (pattern.get_lower_bound (),
750 40 : pattern.get_mappings (),
751 40 : pattern.get_locus ());
752 :
753 40 : infered = unify_site (pattern.get_mappings ().get_hirid (),
754 40 : TyTy::TyWithLocation (upper),
755 40 : TyTy::TyWithLocation (lower), pattern.get_locus ());
756 40 : }
757 :
758 : void
759 38934 : TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
760 : {
761 38934 : if (pattern.has_subpattern ())
762 : {
763 17 : TypeCheckPattern::Resolve (pattern.get_subpattern (), parent);
764 : }
765 :
766 38934 : if (!pattern.get_is_ref ())
767 : {
768 38931 : infered = parent;
769 38931 : return;
770 : }
771 :
772 9 : infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
773 3 : TyTy::TyVar (parent->get_ref ()),
774 3 : pattern.is_mut () ? Mutability::Mut
775 6 : : Mutability::Imm);
776 : }
777 :
778 : void
779 0 : TypeCheckPattern::visit (HIR::QualifiedPathInExpression &pattern)
780 : {
781 0 : rust_sorry_at (pattern.get_locus (),
782 : "type checking qualified path patterns not supported");
783 0 : }
784 :
785 : void
786 199 : TypeCheckPattern::visit (HIR::ReferencePattern &pattern)
787 : {
788 199 : if (parent->get_kind () != TyTy::TypeKind::REF)
789 : {
790 1 : rust_error_at (pattern.get_locus (), "expected %s, found reference",
791 1 : parent->as_string ().c_str ());
792 1 : return;
793 : }
794 :
795 198 : auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
796 198 : TyTy::BaseType *infered_base
797 198 : = TypeCheckPattern::Resolve (pattern.get_referenced_pattern (),
798 : ref_ty_ty.get_base ());
799 594 : infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
800 198 : TyTy::TyVar (infered_base->get_ref ()),
801 198 : pattern.is_mut () ? Mutability::Mut
802 396 : : Mutability::Imm);
803 : }
804 :
805 : void
806 76 : TypeCheckPattern::visit (HIR::SlicePattern &pattern)
807 : {
808 76 : auto resolved_parent = parent->destructure ();
809 76 : TyTy::BaseType *parent_element_ty = nullptr;
810 76 : switch (resolved_parent->get_kind ())
811 : {
812 37 : case TyTy::ARRAY:
813 37 : {
814 37 : auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
815 37 : parent_element_ty = array_ty_ty.get_element_type ();
816 37 : auto capacity = array_ty_ty.get_capacity ();
817 :
818 37 : tree cap = error_mark_node;
819 37 : if (capacity->get_kind () != TyTy::TypeKind::CONST)
820 : {
821 : // Error case - capacity is not a const type
822 : break;
823 : }
824 :
825 37 : auto *capacity_const = capacity->as_const_type ();
826 37 : switch (capacity_const->const_kind ())
827 : {
828 37 : case TyTy::BaseConstType::ConstKind::Value:
829 37 : {
830 37 : const auto &const_value
831 : = *static_cast<TyTy::ConstValueType *> (capacity);
832 37 : cap = const_value.get_value ();
833 : }
834 37 : break;
835 :
836 0 : case TyTy::BaseConstType::ConstKind::Decl:
837 0 : case TyTy::BaseConstType::ConstKind::Infer:
838 0 : case TyTy::BaseConstType::ConstKind::Error:
839 0 : cap = error_mark_node;
840 0 : break;
841 : }
842 :
843 37 : if (error_operand_p (cap))
844 : {
845 0 : rust_error_at (parent->get_locus (),
846 : "capacity of array %qs is not known at compile time",
847 0 : array_ty_ty.get_name ().c_str ());
848 0 : break;
849 : }
850 37 : auto cap_wi = wi::to_wide (cap).to_uhwi ();
851 :
852 : // size check during compile time
853 37 : switch (pattern.get_items ().get_item_type ())
854 : {
855 16 : case HIR::SlicePatternItems::ItemType::NO_REST:
856 16 : {
857 16 : auto &ref = static_cast<HIR::SlicePatternItemsNoRest &> (
858 16 : pattern.get_items ());
859 16 : if (cap_wi != ref.get_patterns ().size ())
860 : {
861 2 : rust_error_at (
862 1 : pattern.get_locus (), ErrorCode::E0527,
863 : "pattern requires %lu elements but array has %lu",
864 1 : (unsigned long) ref.get_patterns ().size (),
865 : (unsigned long) cap_wi);
866 1 : break;
867 : }
868 : }
869 : break;
870 21 : case HIR::SlicePatternItems::ItemType::HAS_REST:
871 21 : {
872 21 : auto &ref = static_cast<HIR::SlicePatternItemsHasRest &> (
873 21 : pattern.get_items ());
874 21 : auto pattern_min_cap = ref.get_lower_patterns ().size ()
875 21 : + ref.get_upper_patterns ().size ();
876 :
877 21 : if (cap_wi < pattern_min_cap)
878 : {
879 0 : rust_error_at (pattern.get_locus (), ErrorCode::E0528,
880 : "pattern requires at least %lu elements but "
881 : "array has %lu",
882 : (unsigned long) pattern_min_cap,
883 : (unsigned long) cap_wi);
884 0 : break;
885 : }
886 : }
887 : break;
888 : }
889 :
890 : break;
891 : }
892 0 : case TyTy::SLICE:
893 0 : {
894 0 : auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent);
895 0 : parent_element_ty = slice_ty_ty.get_element_type ();
896 0 : break;
897 : }
898 39 : case TyTy::REF:
899 39 : {
900 39 : auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
901 39 : const TyTy::SliceType *slice = nullptr;
902 39 : if (!ref_ty_ty.is_dyn_slice_type (&slice))
903 : {
904 0 : rust_error_at (pattern.get_locus (), "expected %s, found slice",
905 0 : parent->as_string ().c_str ());
906 0 : return;
907 : }
908 39 : parent_element_ty = slice->get_element_type ();
909 39 : break;
910 : }
911 0 : default:
912 0 : {
913 0 : rust_error_at (pattern.get_locus (), "expected %s, found slice",
914 0 : parent->as_string ().c_str ());
915 0 : return;
916 : }
917 : }
918 :
919 76 : rust_assert (parent_element_ty != nullptr);
920 : // infered inherits array/slice typing from parent
921 76 : infered = parent->clone ();
922 76 : infered->set_ref (pattern.get_mappings ().get_hirid ());
923 :
924 : // Type check every item in the SlicePattern against parent's element ty
925 76 : switch (pattern.get_items ().get_item_type ())
926 : {
927 32 : case HIR::SlicePatternItems::ItemType::NO_REST:
928 32 : {
929 32 : auto &ref
930 32 : = static_cast<HIR::SlicePatternItemsNoRest &> (pattern.get_items ());
931 96 : for (const auto &pattern_member : ref.get_patterns ())
932 : {
933 64 : TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
934 : }
935 : break;
936 : }
937 44 : case HIR::SlicePatternItems::ItemType::HAS_REST:
938 44 : {
939 44 : auto &ref
940 44 : = static_cast<HIR::SlicePatternItemsHasRest &> (pattern.get_items ());
941 87 : for (const auto &pattern_member : ref.get_lower_patterns ())
942 : {
943 43 : TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
944 : }
945 87 : for (const auto &pattern_member : ref.get_upper_patterns ())
946 : {
947 43 : TypeCheckPattern::Resolve (*pattern_member, parent_element_ty);
948 : }
949 : break;
950 : }
951 : }
952 : }
953 :
954 : void
955 7 : TypeCheckPattern::emit_pattern_size_error (const HIR::Pattern &pattern,
956 : size_t expected_field_count,
957 : size_t got_field_count)
958 : {
959 7 : rich_location r (line_table, pattern.get_locus ());
960 7 : r.add_range (mappings.lookup_location (parent->get_ref ()));
961 18 : rust_error_at (r,
962 : "expected a tuple with %lu %s, found one "
963 : "with %lu %s",
964 : (unsigned long) expected_field_count,
965 : expected_field_count == 1 ? "element" : "elements",
966 : (unsigned long) got_field_count,
967 : got_field_count == 1 ? "element" : "elements");
968 7 : }
969 :
970 : TyTy::BaseType *
971 80 : TypeCheckPattern::typecheck_range_pattern_bound (
972 : Rust::HIR::RangePatternBound &bound, Analysis::NodeMapping mappings,
973 : location_t locus)
974 : {
975 80 : TyTy::BaseType *resolved_bound = nullptr;
976 80 : switch (bound.get_bound_type ())
977 : {
978 59 : case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
979 59 : {
980 59 : auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
981 :
982 59 : HIR::Literal lit = ref.get_literal ();
983 :
984 59 : resolved_bound = resolve_literal (mappings, lit, locus);
985 59 : }
986 59 : break;
987 :
988 21 : case HIR::RangePatternBound::RangePatternBoundType::PATH:
989 21 : {
990 21 : auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
991 :
992 21 : resolved_bound = TypeCheckExpr::Resolve (ref.get_path ());
993 : }
994 21 : break;
995 :
996 0 : case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
997 0 : {
998 0 : auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
999 :
1000 0 : resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ());
1001 : }
1002 0 : break;
1003 : }
1004 :
1005 80 : return resolved_bound;
1006 : }
1007 :
1008 : void
1009 145 : TypeCheckPattern::visit (HIR::AltPattern &pattern)
1010 : {
1011 145 : const auto &alts = pattern.get_alts ();
1012 :
1013 : // lub - taken from TypeCheckExpr::visit(ArrayExpr)
1014 145 : std::vector<TyTy::BaseType *> types;
1015 436 : for (auto &alt_pattern : alts)
1016 : {
1017 291 : types.push_back (TypeCheckPattern::Resolve (*alt_pattern, parent));
1018 : }
1019 :
1020 145 : TyTy::BaseType *alt_pattern_type
1021 145 : = TyTy::TyVar::get_implicit_infer_var (pattern.get_locus ()).get_tyty ();
1022 :
1023 436 : for (auto &type : types)
1024 : {
1025 291 : alt_pattern_type
1026 291 : = unify_site (pattern.get_mappings ().get_hirid (),
1027 291 : TyTy::TyWithLocation (alt_pattern_type),
1028 291 : TyTy::TyWithLocation (type, type->get_locus ()),
1029 291 : pattern.get_locus ());
1030 : }
1031 :
1032 145 : infered = alt_pattern_type;
1033 145 : }
1034 :
1035 : TyTy::BaseType *
1036 3 : ClosureParamInfer::Resolve (HIR::Pattern &pattern)
1037 : {
1038 3 : ClosureParamInfer resolver;
1039 3 : pattern.accept_vis (resolver);
1040 :
1041 3 : if (resolver.infered->get_kind () != TyTy::TypeKind::ERROR)
1042 : {
1043 3 : resolver.context->insert_implicit_type (resolver.infered->get_ref (),
1044 : resolver.infered);
1045 3 : resolver.mappings.insert_location (resolver.infered->get_ref (),
1046 3 : pattern.get_locus ());
1047 : }
1048 3 : return resolver.infered;
1049 3 : }
1050 :
1051 3 : ClosureParamInfer::ClosureParamInfer ()
1052 3 : : TypeCheckBase (), infered (new TyTy::ErrorType (0))
1053 3 : {}
1054 :
1055 : void
1056 1 : ClosureParamInfer::visit (HIR::WildcardPattern &pattern)
1057 : {
1058 1 : HirId id = pattern.get_mappings ().get_hirid ();
1059 1 : infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
1060 : TyTy::InferType::TypeHint::Default (),
1061 1 : pattern.get_locus ());
1062 1 : }
1063 :
1064 : void
1065 1 : ClosureParamInfer::visit (HIR::IdentifierPattern &pattern)
1066 : {
1067 1 : if (pattern.has_subpattern ())
1068 : {
1069 0 : ClosureParamInfer::Resolve (pattern.get_subpattern ());
1070 : }
1071 :
1072 1 : HirId id = pattern.get_mappings ().get_hirid ();
1073 1 : infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
1074 : TyTy::InferType::TypeHint::Default (),
1075 1 : pattern.get_locus ());
1076 1 : }
1077 :
1078 : void
1079 1 : ClosureParamInfer::visit (HIR::ReferencePattern &pattern)
1080 : {
1081 1 : TyTy::BaseType *element
1082 1 : = ClosureParamInfer::Resolve (pattern.get_referenced_pattern ());
1083 :
1084 1 : HirId id = pattern.get_mappings ().get_hirid ();
1085 1 : infered = new TyTy::ReferenceType (id, TyTy::TyVar (element->get_ref ()),
1086 2 : pattern.get_mutability ());
1087 1 : }
1088 :
1089 : void
1090 0 : ClosureParamInfer::visit (HIR::PathInExpression &pattern)
1091 : {
1092 0 : rust_sorry_at (pattern.get_locus (),
1093 : "unable to infer this kind of parameter pattern");
1094 0 : }
1095 :
1096 : void
1097 0 : ClosureParamInfer::visit (HIR::StructPattern &pattern)
1098 : {
1099 0 : rust_sorry_at (pattern.get_locus (),
1100 : "unable to infer this kind of parameter pattern");
1101 0 : }
1102 :
1103 : void
1104 0 : ClosureParamInfer::visit (HIR::TupleStructPattern &pattern)
1105 : {
1106 0 : rust_sorry_at (pattern.get_locus (),
1107 : "unable to infer this kind of parameter pattern");
1108 0 : }
1109 :
1110 : void
1111 0 : ClosureParamInfer::visit (HIR::TuplePattern &pattern)
1112 : {
1113 0 : rust_sorry_at (pattern.get_locus (),
1114 : "unable to infer this kind of parameter pattern");
1115 0 : }
1116 :
1117 : void
1118 0 : ClosureParamInfer::visit (HIR::LiteralPattern &pattern)
1119 : {
1120 0 : rust_sorry_at (pattern.get_locus (),
1121 : "unable to infer this kind of parameter pattern");
1122 0 : }
1123 :
1124 : void
1125 0 : ClosureParamInfer::visit (HIR::RangePattern &pattern)
1126 : {
1127 0 : rust_sorry_at (pattern.get_locus (),
1128 : "unable to infer this kind of parameter pattern");
1129 0 : }
1130 :
1131 : void
1132 0 : ClosureParamInfer::visit (HIR::QualifiedPathInExpression &pattern)
1133 : {
1134 0 : rust_sorry_at (pattern.get_locus (),
1135 : "unable to infer this kind of parameter pattern");
1136 0 : }
1137 :
1138 : void
1139 0 : ClosureParamInfer::visit (HIR::SlicePattern &pattern)
1140 : {
1141 0 : rust_sorry_at (pattern.get_locus (),
1142 : "unable to infer this kind of parameter pattern");
1143 0 : }
1144 :
1145 : void
1146 0 : ClosureParamInfer::visit (HIR::AltPattern &pattern)
1147 : {
1148 0 : rust_sorry_at (pattern.get_locus (),
1149 : "unable to infer this kind of parameter pattern");
1150 0 : }
1151 :
1152 : } // namespace Resolver
1153 : } // namespace Rust
|