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