Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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-type-util.h"
23 : : #include "rust-immutable-name-resolution-context.h"
24 : :
25 : : namespace Rust {
26 : : namespace Resolver {
27 : :
28 : 42882 : TypeCheckPattern::TypeCheckPattern (TyTy::BaseType *parent)
29 : 42882 : : TypeCheckBase (), parent (parent), infered (new TyTy::ErrorType (0))
30 : 42882 : {}
31 : :
32 : : TyTy::BaseType *
33 : 42882 : TypeCheckPattern::Resolve (HIR::Pattern &pattern, TyTy::BaseType *parent)
34 : : {
35 : 42882 : TypeCheckPattern resolver (parent);
36 : 42882 : pattern.accept_vis (resolver);
37 : :
38 : 42882 : if (resolver.infered == nullptr)
39 : 0 : return new TyTy::ErrorType (pattern.get_mappings ().get_hirid ());
40 : :
41 : 42882 : resolver.context->insert_type (pattern.get_mappings (), resolver.infered);
42 : 42882 : return resolver.infered;
43 : 42882 : }
44 : :
45 : : void
46 : 1083 : TypeCheckPattern::visit (HIR::PathInExpression &pattern)
47 : : {
48 : : // Pattern must be enum variants, sturcts, constants, or associated constansts
49 : 1083 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern);
50 : :
51 : 1083 : NodeId ref_node_id = UNKNOWN_NODEID;
52 : 1083 : bool maybe_item = false;
53 : :
54 : 1083 : auto &nr_ctx
55 : 1083 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
56 : :
57 : 1083 : if (auto id = nr_ctx.lookup (pattern.get_mappings ().get_nodeid ()))
58 : : {
59 : 1081 : ref_node_id = *id;
60 : 1081 : maybe_item = true;
61 : : }
62 : :
63 : 1083 : bool path_is_const_item = false;
64 : :
65 : 1083 : if (maybe_item)
66 : : {
67 : 1081 : tl::optional<HirId> definition_id
68 : 1081 : = mappings.lookup_node_to_hir (ref_node_id);
69 : 1081 : rust_assert (definition_id.has_value ());
70 : 1081 : HirId def_id = definition_id.value ();
71 : :
72 : 1081 : tl::optional<HIR::Item *> hir_item = mappings.lookup_hir_item (def_id);
73 : : // If the path refrerences an item, it must be constants or structs.
74 : 1081 : if (hir_item.has_value ())
75 : : {
76 : 5 : HIR::Item *item = hir_item.value ();
77 : 5 : if (item->get_item_kind () == HIR::Item::ItemKind::Constant)
78 : : {
79 : : path_is_const_item = true;
80 : : }
81 : 4 : else if (item->get_item_kind () != HIR::Item::ItemKind::Struct)
82 : : {
83 : 4 : HIR::Item *item = hir_item.value ();
84 : 4 : std::string item_kind
85 : 4 : = HIR::Item::item_kind_string (item->get_item_kind ());
86 : :
87 : 4 : std::string path_buf;
88 : 12 : for (size_t i = 0; i < pattern.get_segments ().size (); i++)
89 : : {
90 : 8 : HIR::PathExprSegment &seg = pattern.get_segments ().at (i);
91 : 16 : path_buf += seg.as_string ();
92 : 8 : if (i != pattern.get_segments ().size () - 1)
93 : 4 : path_buf += "::";
94 : : }
95 : :
96 : 4 : rich_location rich_locus (
97 : 4 : line_table, pattern.get_final_segment ().get_locus ());
98 : 4 : rich_locus.add_fixit_replace (
99 : : "not a unit struct, unit variant or constant");
100 : 4 : rust_error_at (rich_locus, ErrorCode::E0532,
101 : : "expected unit struct, unit variant or constant, "
102 : : "found %s %<%s%>",
103 : : item_kind.c_str (), path_buf.c_str ());
104 : 4 : return;
105 : 4 : }
106 : : }
107 : : }
108 : :
109 : : // If the path is a constructor, it must be a unit struct or unit variants.
110 : 1079 : if (!path_is_const_item && pattern_ty->get_kind () == TyTy::TypeKind::ADT)
111 : : {
112 : 1076 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (pattern_ty);
113 : 1076 : rust_assert (adt->get_variants ().size () > 0);
114 : :
115 : 1076 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
116 : 1076 : if (adt->is_enum ())
117 : : {
118 : 1076 : HirId variant_id = UNKNOWN_HIRID;
119 : 1076 : bool ok = context->lookup_variant_definition (
120 : 1076 : pattern.get_mappings ().get_hirid (), &variant_id);
121 : 1076 : rust_assert (ok);
122 : :
123 : 1076 : ok = adt->lookup_variant_by_id (variant_id, &variant);
124 : 1076 : rust_assert (ok);
125 : : }
126 : :
127 : 1076 : if (variant->get_variant_type () != TyTy::VariantDef::VariantType::NUM)
128 : : {
129 : 3 : std::string variant_type = TyTy::VariantDef::variant_type_string (
130 : 3 : variant->get_variant_type ());
131 : :
132 : 3 : rich_location rich_locus (line_table,
133 : 3 : pattern.get_final_segment ().get_locus ());
134 : 3 : rich_locus.add_fixit_replace (
135 : : "not a unit struct, unit variant or constatnt");
136 : 3 : rust_error_at (rich_locus, ErrorCode::E0532,
137 : : "expected unit struct, unit variant or constant, "
138 : : "found %s variant %<%s::%s%>",
139 : 6 : variant_type.c_str (), adt->get_name ().c_str (),
140 : 3 : variant->get_identifier ().c_str ());
141 : 3 : return;
142 : 3 : }
143 : :
144 : 1073 : infered = pattern_ty;
145 : : }
146 : : }
147 : :
148 : : void
149 : 960 : TypeCheckPattern::visit (HIR::TupleStructPattern &pattern)
150 : : {
151 : 960 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
152 : 960 : if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
153 : : {
154 : 2 : rust_error_at (
155 : 2 : pattern.get_locus (), ErrorCode::E0532,
156 : : "expected tuple struct or tuple variant, found function %qs",
157 : 2 : pattern_ty->get_name ().c_str ());
158 : 3 : return;
159 : : }
160 : :
161 : 958 : infered = pattern_ty;
162 : 958 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
163 : 958 : rust_assert (adt->number_of_variants () > 0);
164 : :
165 : 958 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
166 : 958 : if (adt->is_enum ())
167 : : {
168 : 936 : HirId variant_id = UNKNOWN_HIRID;
169 : 936 : bool ok = context->lookup_variant_definition (
170 : 936 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
171 : 936 : rust_assert (ok);
172 : :
173 : 936 : ok = adt->lookup_variant_by_id (variant_id, &variant);
174 : 936 : rust_assert (ok);
175 : : }
176 : :
177 : : // error[E0532]: expected tuple struct or tuple variant, found struct
178 : : // variant `Foo::D`, E0532 by rustc 1.49.0 , E0164 by rustc 1.71.0
179 : 958 : if (variant->get_variant_type () != TyTy::VariantDef::VariantType::TUPLE)
180 : : {
181 : 1 : std::string variant_type
182 : 1 : = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
183 : :
184 : 1 : rich_location rich_locus (line_table, pattern.get_locus ());
185 : 1 : rich_locus.add_fixit_replace ("not a tuple struct or tuple variant");
186 : 1 : rust_error_at (
187 : : rich_locus, ErrorCode::E0164,
188 : : "expected tuple struct or tuple variant, found %s variant %<%s::%s%>",
189 : 2 : variant_type.c_str (), adt->get_name ().c_str (),
190 : 1 : variant->get_identifier ().c_str ());
191 : 1 : return;
192 : 1 : }
193 : :
194 : : // check the elements
195 : : // error[E0023]: this pattern has 2 fields, but the corresponding tuple
196 : : // variant has 1 field
197 : : // error[E0023]: this pattern has 0 fields, but the corresponding tuple
198 : : // variant has 1 field
199 : :
200 : 957 : auto &items = pattern.get_items ();
201 : 957 : switch (items.get_item_type ())
202 : : {
203 : 0 : case HIR::TupleStructItems::RANGED:
204 : 0 : {
205 : : // TODO
206 : 0 : rust_unreachable ();
207 : : }
208 : 957 : break;
209 : :
210 : 957 : case HIR::TupleStructItems::MULTIPLE:
211 : 957 : {
212 : 957 : HIR::TupleStructItemsNoRange &items_no_range
213 : : = static_cast<HIR::TupleStructItemsNoRange &> (items);
214 : :
215 : 957 : if (items_no_range.get_patterns ().size () != variant->num_fields ())
216 : : {
217 : 1 : rust_error_at (
218 : 1 : pattern.get_locus (), ErrorCode::E0023,
219 : : "this pattern has %lu fields but the corresponding "
220 : : "tuple variant has %lu field",
221 : 1 : (unsigned long) items_no_range.get_patterns ().size (),
222 : 1 : (unsigned long) variant->num_fields ());
223 : : // we continue on to try and setup the types as best we can for
224 : : // type checking
225 : : }
226 : :
227 : : // iterate the fields and set them up, I wish we had ZIP
228 : 957 : size_t i = 0;
229 : 1988 : for (auto &pattern : items_no_range.get_patterns ())
230 : : {
231 : 1032 : if (i >= variant->num_fields ())
232 : : break;
233 : :
234 : 1031 : TyTy::StructFieldType *field = variant->get_field_at_index (i++);
235 : 1031 : TyTy::BaseType *fty = field->get_field_type ();
236 : :
237 : : // setup the type on this pattern type
238 : 1031 : context->insert_type (pattern->get_mappings (), fty);
239 : 1031 : TypeCheckPattern::Resolve (*pattern, fty);
240 : : }
241 : : }
242 : : break;
243 : : }
244 : : }
245 : :
246 : : void
247 : 1 : emit_invalid_field_error (location_t loc, Rust::TyTy::VariantDef *variant,
248 : : const std::string &name)
249 : : {
250 : 1 : rust_error_at (loc, ErrorCode::E0026,
251 : : "variant %s does not have a field named %s",
252 : 1 : variant->get_identifier ().c_str (), name.c_str ());
253 : 1 : }
254 : :
255 : : void
256 : 147 : TypeCheckPattern::visit (HIR::StructPattern &pattern)
257 : : {
258 : 147 : TyTy::BaseType *pattern_ty = TypeCheckExpr::Resolve (pattern.get_path ());
259 : 147 : if (pattern_ty->get_kind () != TyTy::TypeKind::ADT)
260 : : {
261 : 0 : rust_error_at (pattern.get_locus (),
262 : : "expected tuple struct/variant, found: %s",
263 : 0 : pattern_ty->get_name ().c_str ());
264 : 2 : return;
265 : : }
266 : :
267 : 147 : infered = pattern_ty;
268 : 147 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (infered);
269 : 147 : if (adt->number_of_variants () == 0)
270 : : {
271 : 0 : HIR::PathInExpression &path = pattern.get_path ();
272 : 0 : const AST::SimplePath &sp = path.as_simple_path ();
273 : 0 : rust_error_at (pattern.get_locus (), ErrorCode::E0574,
274 : : "expected struct, variant or union type, found enum %qs",
275 : 0 : sp.as_string ().c_str ());
276 : 0 : return;
277 : 0 : }
278 : :
279 : 147 : TyTy::VariantDef *variant = adt->get_variants ().at (0);
280 : 147 : if (adt->is_enum ())
281 : : {
282 : 118 : HirId variant_id = UNKNOWN_HIRID;
283 : 118 : bool ok = context->lookup_variant_definition (
284 : 118 : pattern.get_path ().get_mappings ().get_hirid (), &variant_id);
285 : 118 : if (!ok)
286 : : {
287 : 1 : HIR::PathInExpression &path = pattern.get_path ();
288 : 1 : const AST::SimplePath &sp = path.as_simple_path ();
289 : 1 : rust_error_at (
290 : 1 : pattern.get_locus (), ErrorCode::E0574,
291 : : "expected struct, variant or union type, found enum %qs",
292 : 1 : sp.as_string ().c_str ());
293 : 1 : return;
294 : 1 : }
295 : :
296 : 117 : ok = adt->lookup_variant_by_id (variant_id, &variant);
297 : 117 : rust_assert (ok);
298 : : }
299 : :
300 : : // error[E0532]: expected tuple struct or tuple variant, found struct
301 : : // variant `Foo::D`
302 : 146 : if (variant->get_variant_type () != TyTy::VariantDef::VariantType::STRUCT)
303 : : {
304 : 1 : std::string variant_type
305 : 1 : = TyTy::VariantDef::variant_type_string (variant->get_variant_type ());
306 : :
307 : 1 : rich_location rich_locus (line_table, pattern.get_locus ());
308 : 1 : std::string rich_msg = "use the tuple variant pattern syntax instead "
309 : 2 : + variant->get_identifier () + "(_)";
310 : 1 : rich_locus.add_fixit_replace (rich_msg.c_str ());
311 : :
312 : 1 : rust_error_at (rich_locus, ErrorCode::E0769,
313 : : "%s variant %qs written as struct variant",
314 : : variant_type.c_str (),
315 : 1 : variant->get_identifier ().c_str ());
316 : 1 : return;
317 : 1 : }
318 : :
319 : 145 : std::vector<std::string> named_fields;
320 : 145 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
321 : 390 : for (auto &field : struct_pattern_elems.get_struct_pattern_fields ())
322 : : {
323 : 245 : switch (field->get_item_type ())
324 : : {
325 : 0 : case HIR::StructPatternField::ItemType::TUPLE_PAT:
326 : 0 : {
327 : : // TODO
328 : 0 : rust_unreachable ();
329 : : }
330 : 149 : break;
331 : :
332 : 149 : case HIR::StructPatternField::ItemType::IDENT_PAT:
333 : 149 : {
334 : 149 : HIR::StructPatternFieldIdentPat &ident
335 : 149 : = static_cast<HIR::StructPatternFieldIdentPat &> (*field);
336 : :
337 : 149 : TyTy::StructFieldType *field = nullptr;
338 : 149 : if (!variant->lookup_field (ident.get_identifier ().as_string (),
339 : : &field, nullptr))
340 : : {
341 : 0 : emit_invalid_field_error (ident.get_locus (), variant,
342 : 0 : ident.get_identifier ().as_string ());
343 : 0 : break;
344 : : }
345 : 149 : named_fields.push_back (ident.get_identifier ().as_string ());
346 : :
347 : 149 : TyTy::BaseType *fty = field->get_field_type ();
348 : 149 : TypeCheckPattern::Resolve (ident.get_pattern (), fty);
349 : : }
350 : 149 : break;
351 : :
352 : 96 : case HIR::StructPatternField::ItemType::IDENT:
353 : 96 : {
354 : 96 : HIR::StructPatternFieldIdent &ident
355 : 96 : = static_cast<HIR::StructPatternFieldIdent &> (*field);
356 : :
357 : 96 : TyTy::StructFieldType *field = nullptr;
358 : 96 : if (!variant->lookup_field (ident.get_identifier ().as_string (),
359 : : &field, nullptr))
360 : : {
361 : 1 : emit_invalid_field_error (ident.get_locus (), variant,
362 : 1 : ident.get_identifier ().as_string ());
363 : 1 : break;
364 : : }
365 : 95 : named_fields.push_back (ident.get_identifier ().as_string ());
366 : :
367 : : // setup the type on this pattern
368 : 95 : TyTy::BaseType *fty = field->get_field_type ();
369 : 95 : context->insert_type (ident.get_mappings (), fty);
370 : : }
371 : 95 : break;
372 : : }
373 : : }
374 : :
375 : : // check the elements
376 : 145 : if (adt->is_union ())
377 : : {
378 : 5 : auto &struct_pattern_elems = pattern.get_struct_pattern_elems ();
379 : 5 : if (struct_pattern_elems.get_struct_pattern_fields ().size () != 1)
380 : 2 : rust_error_at (pattern.get_locus (),
381 : : "union patterns should have exactly one field");
382 : :
383 : : else
384 : : {
385 : 6 : switch (struct_pattern_elems.get_struct_pattern_fields ()
386 : 3 : .at (0)
387 : 3 : ->get_item_type ())
388 : : {
389 : : case HIR::StructPatternField::ItemType::IDENT:
390 : : case HIR::StructPatternField::ItemType::IDENT_PAT:
391 : : break;
392 : 0 : default:
393 : 0 : {
394 : 0 : auto first_elem
395 : 0 : = struct_pattern_elems.get_struct_pattern_fields ()
396 : 0 : .at (0)
397 : 0 : ->as_string ();
398 : 0 : rust_error_at (pattern.get_locus (),
399 : : "%qs cannot be used in union patterns",
400 : : first_elem.c_str ());
401 : 0 : }
402 : : }
403 : : }
404 : : }
405 : : else
406 : : {
407 : : // Expects enum struct or struct struct.
408 : : // error[E0027]: pattern does not mention fields `x`, `y`
409 : : // error[E0026]: variant `Foo::D` does not have a field named `b`
410 : 140 : if (named_fields.size () != variant->num_fields ())
411 : : {
412 : 2 : std::map<std::string, bool> missing_names;
413 : :
414 : : // populate with all fields
415 : 6 : for (auto &field : variant->get_fields ())
416 : 4 : missing_names[field->get_name ()] = true;
417 : :
418 : : // then eliminate with named_fields
419 : 3 : for (auto &named : named_fields)
420 : 1 : missing_names.erase (named);
421 : :
422 : : // then get the list of missing names
423 : 2 : size_t i = 0;
424 : 2 : std::string missing_fields_str;
425 : 5 : for (auto it = missing_names.begin (); it != missing_names.end ();
426 : 3 : it++)
427 : : {
428 : 3 : bool has_next = (i + 1) < missing_names.size ();
429 : 8 : missing_fields_str += it->first + (has_next ? ", " : "");
430 : 3 : i++;
431 : : }
432 : :
433 : 2 : rust_error_at (pattern.get_locus (), ErrorCode::E0027,
434 : : "pattern does not mention fields %s",
435 : : missing_fields_str.c_str ());
436 : 2 : }
437 : : }
438 : 145 : }
439 : :
440 : : void
441 : 1159 : TypeCheckPattern::visit (HIR::WildcardPattern &pattern)
442 : : {
443 : : // wildcard patterns within the MatchArm's are simply just the same type as
444 : : // the parent
445 : 1159 : infered = parent->clone ();
446 : 1159 : infered->set_ref (pattern.get_mappings ().get_hirid ());
447 : 1159 : }
448 : :
449 : : void
450 : 401 : TypeCheckPattern::visit (HIR::TuplePattern &pattern)
451 : : {
452 : 401 : std::unique_ptr<HIR::TuplePatternItems> items;
453 : :
454 : : // Check whether parent is tuple
455 : 401 : auto resolved_parent = parent->destructure ();
456 : 401 : if (resolved_parent->get_kind () != TyTy::TUPLE)
457 : : {
458 : 2 : rust_error_at (pattern.get_locus (), "expected %s, found tuple",
459 : 2 : parent->as_string ().c_str ());
460 : 2 : return;
461 : : }
462 : 399 : TyTy::TupleType &par = *static_cast<TyTy::TupleType *> (resolved_parent);
463 : :
464 : 399 : switch (pattern.get_items ().get_item_type ())
465 : : {
466 : 375 : case HIR::TuplePatternItems::ItemType::MULTIPLE:
467 : 375 : {
468 : 375 : auto &ref = static_cast<HIR::TuplePatternItemsMultiple &> (
469 : 375 : pattern.get_items ());
470 : :
471 : 375 : const auto &patterns = ref.get_patterns ();
472 : 375 : size_t nitems_to_resolve = patterns.size ();
473 : :
474 : 375 : if (patterns.size () != par.get_fields ().size ())
475 : : {
476 : 4 : emit_pattern_size_error (pattern, par.get_fields ().size (),
477 : : patterns.size ());
478 : 4 : nitems_to_resolve
479 : 4 : = std::min (nitems_to_resolve, par.get_fields ().size ());
480 : : }
481 : :
482 : 375 : std::vector<TyTy::TyVar> pattern_elems;
483 : 1128 : for (size_t i = 0; i < nitems_to_resolve; i++)
484 : : {
485 : 753 : auto &p = patterns[i];
486 : 753 : TyTy::BaseType *par_type = par.get_field (i);
487 : :
488 : 753 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
489 : 753 : pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
490 : : }
491 : 750 : infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
492 : 750 : pattern.get_locus (), pattern_elems);
493 : 375 : }
494 : 375 : break;
495 : :
496 : 24 : case HIR::TuplePatternItems::ItemType::RANGED:
497 : 24 : {
498 : 24 : HIR::TuplePatternItemsRanged &ref
499 : 24 : = static_cast<HIR::TuplePatternItemsRanged &> (pattern.get_items ());
500 : :
501 : 24 : const auto &lower = ref.get_lower_patterns ();
502 : 24 : const auto &upper = ref.get_upper_patterns ();
503 : 24 : size_t min_size_required = lower.size () + upper.size ();
504 : :
505 : : // Ensure that size of lower and upper patterns <= parent size
506 : 24 : if (min_size_required > par.get_fields ().size ())
507 : : {
508 : 2 : emit_pattern_size_error (pattern, par.get_fields ().size (),
509 : : min_size_required);
510 : : // TODO attempt to continue to do typechecking even after wrong size
511 : 2 : break;
512 : : }
513 : :
514 : : // Resolve lower patterns
515 : 22 : std::vector<TyTy::TyVar> pattern_elems;
516 : 44 : for (size_t i = 0; i < lower.size (); i++)
517 : : {
518 : 22 : auto &p = lower[i];
519 : 22 : TyTy::BaseType *par_type = par.get_field (i);
520 : :
521 : 22 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
522 : 22 : pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
523 : : }
524 : :
525 : : // Pad pattern_elems until needing to resolve upper patterns
526 : 22 : size_t rest_end = par.get_fields ().size () - upper.size ();
527 : 66 : for (size_t i = lower.size (); i < rest_end; i++)
528 : : {
529 : 44 : TyTy::BaseType *par_type = par.get_field (i);
530 : 44 : pattern_elems.push_back (TyTy::TyVar (par_type->get_ref ()));
531 : : }
532 : :
533 : : // Resolve upper patterns
534 : 44 : for (size_t i = 0; i < upper.size (); i++)
535 : : {
536 : 22 : auto &p = upper[i];
537 : 22 : TyTy::BaseType *par_type = par.get_field (rest_end + i);
538 : :
539 : 22 : TyTy::BaseType *elem = TypeCheckPattern::Resolve (*p, par_type);
540 : 22 : pattern_elems.push_back (TyTy::TyVar (elem->get_ref ()));
541 : : }
542 : :
543 : 44 : infered = new TyTy::TupleType (pattern.get_mappings ().get_hirid (),
544 : 44 : pattern.get_locus (), pattern_elems);
545 : 22 : }
546 : 22 : break;
547 : : }
548 : 401 : }
549 : :
550 : : void
551 : 278 : TypeCheckPattern::visit (HIR::LiteralPattern &pattern)
552 : : {
553 : 278 : TyTy::BaseType *resolved
554 : 278 : = resolve_literal (pattern.get_mappings (), pattern.get_literal (),
555 : 278 : pattern.get_locus ());
556 : 278 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
557 : : {
558 : 0 : infered = resolved;
559 : 0 : return;
560 : : }
561 : :
562 : 278 : infered = unify_site (pattern.get_mappings ().get_hirid (),
563 : 278 : TyTy::TyWithLocation (parent),
564 : 278 : TyTy::TyWithLocation (resolved), pattern.get_locus ());
565 : : }
566 : :
567 : : void
568 : 21 : TypeCheckPattern::visit (HIR::RangePattern &pattern)
569 : : {
570 : : // Resolve the upper and lower bounds, and ensure they are compatible types
571 : 21 : TyTy::BaseType *upper = nullptr, *lower = nullptr;
572 : :
573 : 21 : upper = typecheck_range_pattern_bound (pattern.get_upper_bound (),
574 : 21 : pattern.get_mappings (),
575 : 21 : pattern.get_locus ());
576 : :
577 : 63 : lower = typecheck_range_pattern_bound (pattern.get_lower_bound (),
578 : 21 : pattern.get_mappings (),
579 : 21 : pattern.get_locus ());
580 : :
581 : 21 : infered = unify_site (pattern.get_mappings ().get_hirid (),
582 : 21 : TyTy::TyWithLocation (upper),
583 : 21 : TyTy::TyWithLocation (lower), pattern.get_locus ());
584 : 21 : }
585 : :
586 : : void
587 : 38457 : TypeCheckPattern::visit (HIR::IdentifierPattern &pattern)
588 : : {
589 : 38457 : if (pattern.has_subpattern ())
590 : : {
591 : 9 : TypeCheckPattern::Resolve (pattern.get_subpattern (), parent);
592 : : }
593 : :
594 : 38457 : if (!pattern.get_is_ref ())
595 : : {
596 : 38456 : infered = parent;
597 : 38456 : return;
598 : : }
599 : :
600 : 3 : infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
601 : 1 : TyTy::TyVar (parent->get_ref ()),
602 : 1 : pattern.is_mut () ? Mutability::Mut
603 : 2 : : Mutability::Imm);
604 : : }
605 : :
606 : : void
607 : 0 : TypeCheckPattern::visit (HIR::QualifiedPathInExpression &pattern)
608 : : {
609 : 0 : rust_sorry_at (pattern.get_locus (),
610 : : "type checking qualified path patterns not supported");
611 : 0 : }
612 : :
613 : : void
614 : 199 : TypeCheckPattern::visit (HIR::ReferencePattern &pattern)
615 : : {
616 : 199 : if (parent->get_kind () != TyTy::TypeKind::REF)
617 : : {
618 : 1 : rust_error_at (pattern.get_locus (), "expected %s, found reference",
619 : 1 : parent->as_string ().c_str ());
620 : 1 : return;
621 : : }
622 : :
623 : 198 : auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
624 : 198 : TyTy::BaseType *infered_base
625 : 198 : = TypeCheckPattern::Resolve (pattern.get_referenced_pattern (),
626 : : ref_ty_ty.get_base ());
627 : 594 : infered = new TyTy::ReferenceType (pattern.get_mappings ().get_hirid (),
628 : 198 : TyTy::TyVar (infered_base->get_ref ()),
629 : 198 : pattern.is_mut () ? Mutability::Mut
630 : 396 : : Mutability::Imm);
631 : : }
632 : :
633 : : void
634 : 32 : TypeCheckPattern::visit (HIR::SlicePattern &pattern)
635 : : {
636 : 32 : auto resolved_parent = parent->destructure ();
637 : 32 : TyTy::BaseType *parent_element_ty = nullptr;
638 : 32 : switch (resolved_parent->get_kind ())
639 : : {
640 : 16 : case TyTy::ARRAY:
641 : 16 : {
642 : 16 : auto &array_ty_ty = static_cast<TyTy::ArrayType &> (*parent);
643 : 16 : parent_element_ty = array_ty_ty.get_element_type ();
644 : 16 : auto capacity = array_ty_ty.get_capacity ();
645 : 16 : tree cap = capacity->get_value ();
646 : 16 : if (error_operand_p (cap))
647 : : {
648 : 0 : rust_error_at (parent->get_locus (),
649 : : "capacity of array %qs is not known at compile time",
650 : 0 : array_ty_ty.get_name ().c_str ());
651 : 0 : break;
652 : : }
653 : 16 : auto cap_wi = wi::to_wide (cap).to_uhwi ();
654 : 16 : if (cap_wi != pattern.get_items ().size ())
655 : : {
656 : 2 : rust_error_at (pattern.get_locus (), ErrorCode::E0527,
657 : : "pattern requires %lu elements but array has %lu",
658 : 1 : (unsigned long) pattern.get_items ().size (),
659 : : (unsigned long) cap_wi);
660 : 1 : break;
661 : : }
662 : : break;
663 : : }
664 : 0 : case TyTy::SLICE:
665 : 0 : {
666 : 0 : auto &slice_ty_ty = static_cast<TyTy::SliceType &> (*parent);
667 : 0 : parent_element_ty = slice_ty_ty.get_element_type ();
668 : 0 : break;
669 : : }
670 : 16 : case TyTy::REF:
671 : 16 : {
672 : 16 : auto &ref_ty_ty = static_cast<TyTy::ReferenceType &> (*parent);
673 : 16 : const TyTy::SliceType *slice = nullptr;
674 : 16 : if (!ref_ty_ty.is_dyn_slice_type (&slice))
675 : : {
676 : 0 : rust_error_at (pattern.get_locus (), "expected %s, found slice",
677 : 0 : parent->as_string ().c_str ());
678 : 0 : return;
679 : : }
680 : 16 : parent_element_ty = slice->get_element_type ();
681 : 16 : break;
682 : : }
683 : 0 : default:
684 : 0 : {
685 : 0 : rust_error_at (pattern.get_locus (), "expected %s, found slice",
686 : 0 : parent->as_string ().c_str ());
687 : 0 : return;
688 : : }
689 : : }
690 : :
691 : 32 : rust_assert (parent_element_ty != nullptr);
692 : : // infered inherits array/slice typing from parent
693 : 32 : infered = parent->clone ();
694 : 32 : infered->set_ref (pattern.get_mappings ().get_hirid ());
695 : :
696 : : // Type check every item in the SlicePattern against parent's element ty
697 : : // TODO update this after adding support for RestPattern in SlicePattern
698 : 96 : for (const auto &item : pattern.get_items ())
699 : : {
700 : 64 : TypeCheckPattern::Resolve (*item, parent_element_ty);
701 : : }
702 : : }
703 : :
704 : : void
705 : 6 : TypeCheckPattern::emit_pattern_size_error (const HIR::Pattern &pattern,
706 : : size_t expected_field_count,
707 : : size_t got_field_count)
708 : : {
709 : 6 : rich_location r (line_table, pattern.get_locus ());
710 : 6 : r.add_range (mappings.lookup_location (parent->get_ref ()));
711 : 15 : rust_error_at (r,
712 : : "expected a tuple with %lu %s, found one "
713 : : "with %lu %s",
714 : : (unsigned long) expected_field_count,
715 : : expected_field_count == 1 ? "element" : "elements",
716 : : (unsigned long) got_field_count,
717 : : got_field_count == 1 ? "element" : "elements");
718 : 6 : }
719 : :
720 : : TyTy::BaseType *
721 : 42 : TypeCheckPattern::typecheck_range_pattern_bound (
722 : : Rust::HIR::RangePatternBound &bound, Analysis::NodeMapping mappings,
723 : : location_t locus)
724 : : {
725 : 42 : TyTy::BaseType *resolved_bound = nullptr;
726 : 42 : switch (bound.get_bound_type ())
727 : : {
728 : 21 : case HIR::RangePatternBound::RangePatternBoundType::LITERAL:
729 : 21 : {
730 : 21 : auto &ref = static_cast<HIR::RangePatternBoundLiteral &> (bound);
731 : :
732 : 21 : HIR::Literal lit = ref.get_literal ();
733 : :
734 : 21 : resolved_bound = resolve_literal (mappings, lit, locus);
735 : 21 : }
736 : 21 : break;
737 : :
738 : 21 : case HIR::RangePatternBound::RangePatternBoundType::PATH:
739 : 21 : {
740 : 21 : auto &ref = static_cast<HIR::RangePatternBoundPath &> (bound);
741 : :
742 : 21 : resolved_bound = TypeCheckExpr::Resolve (ref.get_path ());
743 : : }
744 : 21 : break;
745 : :
746 : 0 : case HIR::RangePatternBound::RangePatternBoundType::QUALPATH:
747 : 0 : {
748 : 0 : auto &ref = static_cast<HIR::RangePatternBoundQualPath &> (bound);
749 : :
750 : 0 : resolved_bound = TypeCheckExpr::Resolve (ref.get_qualified_path ());
751 : : }
752 : 0 : break;
753 : : }
754 : :
755 : 42 : return resolved_bound;
756 : : }
757 : :
758 : : void
759 : 145 : TypeCheckPattern::visit (HIR::AltPattern &pattern)
760 : : {
761 : 145 : const auto &alts = pattern.get_alts ();
762 : :
763 : : // lub - taken from TypeCheckExpr::visit(ArrayExpr)
764 : 145 : std::vector<TyTy::BaseType *> types;
765 : 436 : for (auto &alt_pattern : alts)
766 : : {
767 : 291 : types.push_back (TypeCheckPattern::Resolve (*alt_pattern, parent));
768 : : }
769 : :
770 : 145 : TyTy::BaseType *alt_pattern_type
771 : 145 : = TyTy::TyVar::get_implicit_infer_var (pattern.get_locus ()).get_tyty ();
772 : :
773 : 436 : for (auto &type : types)
774 : : {
775 : 291 : alt_pattern_type
776 : 291 : = unify_site (pattern.get_mappings ().get_hirid (),
777 : 291 : TyTy::TyWithLocation (alt_pattern_type),
778 : 291 : TyTy::TyWithLocation (type, type->get_locus ()),
779 : 291 : pattern.get_locus ());
780 : : }
781 : :
782 : 145 : infered = alt_pattern_type;
783 : 145 : }
784 : :
785 : : TyTy::BaseType *
786 : 3 : ClosureParamInfer::Resolve (HIR::Pattern &pattern)
787 : : {
788 : 3 : ClosureParamInfer resolver;
789 : 3 : pattern.accept_vis (resolver);
790 : :
791 : 3 : if (resolver.infered->get_kind () != TyTy::TypeKind::ERROR)
792 : : {
793 : 3 : resolver.context->insert_implicit_type (resolver.infered->get_ref (),
794 : : resolver.infered);
795 : 3 : resolver.mappings.insert_location (resolver.infered->get_ref (),
796 : 3 : pattern.get_locus ());
797 : : }
798 : 3 : return resolver.infered;
799 : 3 : }
800 : :
801 : 3 : ClosureParamInfer::ClosureParamInfer ()
802 : 3 : : TypeCheckBase (), infered (new TyTy::ErrorType (0))
803 : 3 : {}
804 : :
805 : : void
806 : 1 : ClosureParamInfer::visit (HIR::WildcardPattern &pattern)
807 : : {
808 : 1 : HirId id = pattern.get_mappings ().get_hirid ();
809 : 1 : infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
810 : : TyTy::InferType::TypeHint::Default (),
811 : 1 : pattern.get_locus ());
812 : 1 : }
813 : :
814 : : void
815 : 1 : ClosureParamInfer::visit (HIR::IdentifierPattern &pattern)
816 : : {
817 : 1 : HirId id = pattern.get_mappings ().get_hirid ();
818 : 1 : infered = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL,
819 : : TyTy::InferType::TypeHint::Default (),
820 : 1 : pattern.get_locus ());
821 : 1 : }
822 : :
823 : : void
824 : 1 : ClosureParamInfer::visit (HIR::ReferencePattern &pattern)
825 : : {
826 : 1 : TyTy::BaseType *element
827 : 1 : = ClosureParamInfer::Resolve (pattern.get_referenced_pattern ());
828 : :
829 : 1 : HirId id = pattern.get_mappings ().get_hirid ();
830 : 1 : infered = new TyTy::ReferenceType (id, TyTy::TyVar (element->get_ref ()),
831 : 2 : pattern.get_mutability ());
832 : 1 : }
833 : :
834 : : void
835 : 0 : ClosureParamInfer::visit (HIR::PathInExpression &pattern)
836 : : {
837 : 0 : rust_sorry_at (pattern.get_locus (),
838 : : "unable to infer this kind of parameter pattern");
839 : 0 : }
840 : :
841 : : void
842 : 0 : ClosureParamInfer::visit (HIR::StructPattern &pattern)
843 : : {
844 : 0 : rust_sorry_at (pattern.get_locus (),
845 : : "unable to infer this kind of parameter pattern");
846 : 0 : }
847 : :
848 : : void
849 : 0 : ClosureParamInfer::visit (HIR::TupleStructPattern &pattern)
850 : : {
851 : 0 : rust_sorry_at (pattern.get_locus (),
852 : : "unable to infer this kind of parameter pattern");
853 : 0 : }
854 : :
855 : : void
856 : 0 : ClosureParamInfer::visit (HIR::TuplePattern &pattern)
857 : : {
858 : 0 : rust_sorry_at (pattern.get_locus (),
859 : : "unable to infer this kind of parameter pattern");
860 : 0 : }
861 : :
862 : : void
863 : 0 : ClosureParamInfer::visit (HIR::LiteralPattern &pattern)
864 : : {
865 : 0 : rust_sorry_at (pattern.get_locus (),
866 : : "unable to infer this kind of parameter pattern");
867 : 0 : }
868 : :
869 : : void
870 : 0 : ClosureParamInfer::visit (HIR::RangePattern &pattern)
871 : : {
872 : 0 : rust_sorry_at (pattern.get_locus (),
873 : : "unable to infer this kind of parameter pattern");
874 : 0 : }
875 : :
876 : : void
877 : 0 : ClosureParamInfer::visit (HIR::QualifiedPathInExpression &pattern)
878 : : {
879 : 0 : rust_sorry_at (pattern.get_locus (),
880 : : "unable to infer this kind of parameter pattern");
881 : 0 : }
882 : :
883 : : void
884 : 0 : ClosureParamInfer::visit (HIR::SlicePattern &pattern)
885 : : {
886 : 0 : rust_sorry_at (pattern.get_locus (),
887 : : "unable to infer this kind of parameter pattern");
888 : 0 : }
889 : :
890 : : void
891 : 0 : ClosureParamInfer::visit (HIR::AltPattern &pattern)
892 : : {
893 : 0 : rust_sorry_at (pattern.get_locus (),
894 : : "unable to infer this kind of parameter pattern");
895 : 0 : }
896 : :
897 : : } // namespace Resolver
898 : : } // namespace Rust
|