gccrs: Refactor unify to hit a unify_site
[official-gcc.git] / gcc / rust / typecheck / rust-tyty-rules.h
blob7ffffc1dd59c10886a9ee727a7e065d632fbeb04
1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
3 // This file is part of GCC.
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.
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.
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/>.
19 #ifndef RUST_TYTY_RULES
20 #define RUST_TYTY_RULES
22 #include "rust-diagnostics.h"
23 #include "rust-tyty.h"
24 #include "rust-tyty-visitor.h"
25 #include "rust-hir-map.h"
26 #include "rust-hir-type-check.h"
28 namespace Rust {
29 namespace TyTy {
31 /* Rules specify how to unify two Ty. For example, the result of unifying the
32 two tuples (u64, A) and (B, i64) would be (u64, i64).
34 Performing a unification requires a double dispatch. To illustrate, suppose
35 we want to unify `ty1` and `ty2`. Here's what it looks like:
36 1. The caller calls `ty1.unify(ty2)`. This is the first dispatch.
37 2. `ty1` creates a rule specific to its type(e.g. TupleRules).
38 3. The rule calls `ty2.accept_vis(rule)`. This is the second dispatch.
39 4. `ty2` calls `rule.visit(*this)`, which will method-overload to the
40 correct implementation at compile time.
42 The nice thing about Rules is that they seperate unification logic from the
43 representation of Ty. To support unifying a new Ty, implement its
44 `accept_vis` and `unify` method to pass the unification request to Rules.
45 Then, create a new `XXXRules` class and implement one `visit` method for
46 every Ty it can unify with. */
47 class BaseRules : public TyVisitor
49 public:
50 virtual ~BaseRules () {}
52 /* Unify two ty. Returns a pointer to the newly-created unified ty, or nullptr
53 if the two types cannot be unified. The caller is responsible for releasing
54 the memory of the returned ty.
56 This method is meant to be used internally by Ty. If you're trying to unify
57 two ty, you can simply call `unify` on ty themselves. */
58 virtual BaseType *unify (BaseType *other)
60 if (other->get_kind () == TypeKind::PARAM)
62 ParamType *p = static_cast<ParamType *> (other);
63 other = p->resolve ();
65 else if (other->get_kind () == TypeKind::PLACEHOLDER)
67 PlaceholderType *p = static_cast<PlaceholderType *> (other);
68 if (p->can_resolve ())
70 other = p->resolve ();
71 return get_base ()->unify (other);
74 else if (other->get_kind () == TypeKind::PROJECTION)
76 ProjectionType *p = static_cast<ProjectionType *> (other);
77 other = p->get ();
78 return get_base ()->unify (other);
81 other->accept_vis (*this);
82 if (resolved->get_kind () == TyTy::TypeKind::ERROR)
83 return resolved;
85 resolved->append_reference (get_base ()->get_ref ());
86 resolved->append_reference (other->get_ref ());
87 for (auto ref : get_base ()->get_combined_refs ())
88 resolved->append_reference (ref);
89 for (auto ref : other->get_combined_refs ())
90 resolved->append_reference (ref);
92 other->append_reference (resolved->get_ref ());
93 other->append_reference (get_base ()->get_ref ());
94 get_base ()->append_reference (resolved->get_ref ());
95 get_base ()->append_reference (other->get_ref ());
97 bool result_resolved = resolved->get_kind () != TyTy::TypeKind::INFER;
98 bool result_is_infer_var = resolved->get_kind () == TyTy::TypeKind::INFER;
99 bool results_is_non_general_infer_var
100 = (result_is_infer_var
101 && (static_cast<InferType *> (resolved))->get_infer_kind ()
102 != TyTy::InferType::GENERAL);
103 if (result_resolved || results_is_non_general_infer_var)
105 for (auto &ref : resolved->get_combined_refs ())
107 TyTy::BaseType *ref_tyty = nullptr;
108 bool ok = context->lookup_type (ref, &ref_tyty);
109 if (!ok)
110 continue;
112 // if any of the types are inference variables lets fix them
113 if (ref_tyty->get_kind () == TyTy::TypeKind::INFER)
115 context->insert_type (
116 Analysis::NodeMapping (mappings->get_current_crate (),
117 UNKNOWN_NODEID, ref,
118 UNKNOWN_LOCAL_DEFID),
119 resolved->clone ());
123 return resolved;
126 virtual void visit (TupleType &type) override {}
128 virtual void visit (ADTType &type) override {}
130 virtual void visit (InferType &type) override {}
132 virtual void visit (FnType &type) override {}
134 virtual void visit (FnPtr &type) override {}
136 virtual void visit (ArrayType &type) override {}
138 virtual void visit (SliceType &type) override {}
140 virtual void visit (BoolType &type) override {}
142 virtual void visit (IntType &type) override {}
144 virtual void visit (UintType &type) override {}
146 virtual void visit (USizeType &type) override {}
148 virtual void visit (ISizeType &type) override {}
150 virtual void visit (FloatType &type) override {}
152 virtual void visit (ErrorType &type) override {}
154 virtual void visit (CharType &type) override {}
156 virtual void visit (ReferenceType &type) override {}
158 virtual void visit (PointerType &type) override {}
160 virtual void visit (ParamType &type) override {}
162 virtual void visit (StrType &type) override {}
164 virtual void visit (NeverType &type) override {}
166 virtual void visit (PlaceholderType &type) override {}
168 virtual void visit (ProjectionType &type) override {}
170 virtual void visit (DynamicObjectType &type) override {}
172 virtual void visit (ClosureType &type) override {}
174 protected:
175 BaseRules (BaseType *base)
176 : mappings (Analysis::Mappings::get ()),
177 context (Resolver::TypeCheckContext::get ()),
178 resolved (new ErrorType (base->get_ref (), base->get_ref ()))
181 Analysis::Mappings *mappings;
182 Resolver::TypeCheckContext *context;
184 /* Temporary storage for the result of a unification.
185 We could return the result directly instead of storing it in the rule
186 object, but that involves modifying the visitor pattern to accommodate
187 the return value, which is too complex. */
188 BaseType *resolved;
190 private:
191 /* Returns a pointer to the ty that created this rule. */
192 virtual BaseType *get_base () = 0;
195 class InferRules : public BaseRules
197 using Rust::TyTy::BaseRules::visit;
199 public:
200 InferRules (InferType *base) : BaseRules (base), base (base) {}
202 void visit (BoolType &type) override
204 bool is_valid
205 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
206 if (is_valid)
208 resolved = type.clone ();
209 return;
212 BaseRules::visit (type);
215 void visit (IntType &type) override
217 bool is_valid
218 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
219 || (base->get_infer_kind ()
220 == TyTy::InferType::InferTypeKind::INTEGRAL);
221 if (is_valid)
223 resolved = type.clone ();
224 return;
227 BaseRules::visit (type);
230 void visit (UintType &type) override
232 bool is_valid
233 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
234 || (base->get_infer_kind ()
235 == TyTy::InferType::InferTypeKind::INTEGRAL);
236 if (is_valid)
238 resolved = type.clone ();
239 return;
242 BaseRules::visit (type);
245 void visit (USizeType &type) override
247 bool is_valid
248 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
249 || (base->get_infer_kind ()
250 == TyTy::InferType::InferTypeKind::INTEGRAL);
251 if (is_valid)
253 resolved = type.clone ();
254 return;
257 BaseRules::visit (type);
260 void visit (ISizeType &type) override
262 bool is_valid
263 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
264 || (base->get_infer_kind ()
265 == TyTy::InferType::InferTypeKind::INTEGRAL);
266 if (is_valid)
268 resolved = type.clone ();
269 return;
272 BaseRules::visit (type);
275 void visit (FloatType &type) override
277 bool is_valid
278 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL)
279 || (base->get_infer_kind () == TyTy::InferType::InferTypeKind::FLOAT);
280 if (is_valid)
282 resolved = type.clone ();
283 return;
286 BaseRules::visit (type);
289 void visit (ArrayType &type) override
291 bool is_valid
292 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
293 if (is_valid)
295 resolved = type.clone ();
296 return;
299 BaseRules::visit (type);
302 void visit (SliceType &type) override
304 bool is_valid
305 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
306 if (is_valid)
308 resolved = type.clone ();
309 return;
312 BaseRules::visit (type);
315 void visit (ADTType &type) override
317 bool is_valid
318 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
319 if (is_valid)
321 resolved = type.clone ();
322 return;
325 BaseRules::visit (type);
328 void visit (TupleType &type) override
330 bool is_valid
331 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
332 if (is_valid)
334 resolved = type.clone ();
335 return;
338 BaseRules::visit (type);
341 void visit (InferType &type) override
343 switch (base->get_infer_kind ())
345 case InferType::InferTypeKind::GENERAL:
346 resolved = type.clone ();
347 return;
349 case InferType::InferTypeKind::INTEGRAL: {
350 if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
352 resolved = type.clone ();
353 return;
355 else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
357 resolved = base->clone ();
358 return;
361 break;
363 case InferType::InferTypeKind::FLOAT: {
364 if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
366 resolved = type.clone ();
367 return;
369 else if (type.get_infer_kind () == InferType::InferTypeKind::GENERAL)
371 resolved = base->clone ();
372 return;
375 break;
378 BaseRules::visit (type);
381 void visit (CharType &type) override
384 bool is_valid
385 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
386 if (is_valid)
388 resolved = type.clone ();
389 return;
392 BaseRules::visit (type);
396 void visit (ReferenceType &type) override
398 bool is_valid
399 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
400 if (is_valid)
402 resolved = type.clone ();
403 return;
406 BaseRules::visit (type);
409 void visit (PointerType &type) override
411 bool is_valid
412 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
413 if (is_valid)
415 resolved = type.clone ();
416 return;
419 BaseRules::visit (type);
422 void visit (ParamType &type) override
424 bool is_valid
425 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
426 if (is_valid)
428 resolved = type.clone ();
429 return;
432 BaseRules::visit (type);
435 void visit (DynamicObjectType &type) override
437 bool is_valid
438 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
439 if (is_valid)
441 resolved = type.clone ();
442 return;
445 BaseRules::visit (type);
448 void visit (ClosureType &type) override
450 bool is_valid
451 = (base->get_infer_kind () == TyTy::InferType::InferTypeKind::GENERAL);
452 if (is_valid)
454 resolved = type.clone ();
455 return;
458 BaseRules::visit (type);
461 private:
462 BaseType *get_base () override { return base; }
464 InferType *base;
467 class FnRules : public BaseRules
469 using Rust::TyTy::BaseRules::visit;
471 public:
472 FnRules (FnType *base) : BaseRules (base), base (base) {}
474 void visit (InferType &type) override
476 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
478 BaseRules::visit (type);
479 return;
482 resolved = base->clone ();
483 resolved->set_ref (type.get_ref ());
486 void visit (FnType &type) override
488 if (base->num_params () != type.num_params ())
490 BaseRules::visit (type);
491 return;
494 for (size_t i = 0; i < base->num_params (); i++)
496 auto a = base->param_at (i).second;
497 auto b = type.param_at (i).second;
499 auto unified_param = a->unify (b);
500 if (unified_param == nullptr)
502 BaseRules::visit (type);
503 return;
507 auto unified_return
508 = base->get_return_type ()->unify (type.get_return_type ());
509 if (unified_return == nullptr)
511 BaseRules::visit (type);
512 return;
515 resolved = base->clone ();
516 resolved->set_ref (type.get_ref ());
519 private:
520 BaseType *get_base () override { return base; }
522 FnType *base;
525 class FnptrRules : public BaseRules
527 using Rust::TyTy::BaseRules::visit;
529 public:
530 FnptrRules (FnPtr *base) : BaseRules (base), base (base) {}
532 void visit (InferType &type) override
534 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
536 BaseRules::visit (type);
537 return;
540 resolved = base->clone ();
541 resolved->set_ref (type.get_ref ());
544 void visit (FnPtr &type) override
546 auto this_ret_type = base->get_return_type ();
547 auto other_ret_type = type.get_return_type ();
548 auto unified_result = this_ret_type->unify (other_ret_type);
549 if (unified_result == nullptr
550 || unified_result->get_kind () == TypeKind::ERROR)
552 BaseRules::visit (type);
553 return;
556 if (base->num_params () != type.num_params ())
558 BaseRules::visit (type);
559 return;
562 for (size_t i = 0; i < base->num_params (); i++)
564 auto this_param = base->param_at (i);
565 auto other_param = type.param_at (i);
566 auto unified_param = this_param->unify (other_param);
567 if (unified_param == nullptr
568 || unified_param->get_kind () == TypeKind::ERROR)
570 BaseRules::visit (type);
571 return;
575 resolved = base->clone ();
576 resolved->set_ref (type.get_ref ());
579 void visit (FnType &type) override
581 auto this_ret_type = base->get_return_type ();
582 auto other_ret_type = type.get_return_type ();
583 auto unified_result = this_ret_type->unify (other_ret_type);
584 if (unified_result == nullptr
585 || unified_result->get_kind () == TypeKind::ERROR)
587 BaseRules::visit (type);
588 return;
591 if (base->num_params () != type.num_params ())
593 BaseRules::visit (type);
594 return;
597 for (size_t i = 0; i < base->num_params (); i++)
599 auto this_param = base->param_at (i);
600 auto other_param = type.param_at (i).second;
601 auto unified_param = this_param->unify (other_param);
602 if (unified_param == nullptr
603 || unified_param->get_kind () == TypeKind::ERROR)
605 BaseRules::visit (type);
606 return;
610 resolved = base->clone ();
611 resolved->set_ref (type.get_ref ());
614 private:
615 BaseType *get_base () override { return base; }
617 FnPtr *base;
620 class ClosureRules : public BaseRules
622 using Rust::TyTy::BaseRules::visit;
624 public:
625 ClosureRules (ClosureType *base) : BaseRules (base), base (base) {}
627 // TODO
629 private:
630 BaseType *get_base () override { return base; }
632 ClosureType *base;
635 class ArrayRules : public BaseRules
637 using Rust::TyTy::BaseRules::visit;
639 public:
640 ArrayRules (ArrayType *base) : BaseRules (base), base (base) {}
642 void visit (ArrayType &type) override
644 // check base type
645 auto base_resolved
646 = base->get_element_type ()->unify (type.get_element_type ());
647 if (base_resolved == nullptr)
649 BaseRules::visit (type);
650 return;
653 resolved
654 = new ArrayType (type.get_ref (), type.get_ty_ref (),
655 type.get_ident ().locus, type.get_capacity_expr (),
656 TyVar (base_resolved->get_ref ()));
659 void visit (InferType &type) override
661 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
663 BaseRules::visit (type);
664 return;
667 resolved = base->clone ();
668 resolved->set_ref (type.get_ref ());
671 private:
672 BaseType *get_base () override { return base; }
674 ArrayType *base;
677 class SliceRules : public BaseRules
679 using Rust::TyTy::BaseRules::visit;
681 public:
682 SliceRules (SliceType *base) : BaseRules (base), base (base) {}
684 void visit (SliceType &type) override
686 // check base type
687 auto base_resolved
688 = base->get_element_type ()->unify (type.get_element_type ());
689 if (base_resolved == nullptr)
691 BaseRules::visit (type);
692 return;
695 resolved = new SliceType (type.get_ref (), type.get_ty_ref (),
696 type.get_ident ().locus,
697 TyVar (base_resolved->get_ref ()));
700 void visit (InferType &type) override
702 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
704 BaseRules::visit (type);
705 return;
708 resolved = base->clone ();
709 resolved->set_ref (type.get_ref ());
712 private:
713 BaseType *get_base () override { return base; }
715 SliceType *base;
718 class BoolRules : public BaseRules
720 using Rust::TyTy::BaseRules::visit;
722 public:
723 BoolRules (BoolType *base) : BaseRules (base), base (base) {}
725 void visit (BoolType &type) override
727 resolved = new BoolType (type.get_ref (), type.get_ty_ref ());
730 void visit (InferType &type) override
732 switch (type.get_infer_kind ())
734 case InferType::InferTypeKind::GENERAL:
735 resolved = base->clone ();
736 break;
738 default:
739 BaseRules::visit (type);
740 break;
744 private:
745 BaseType *get_base () override { return base; }
747 BoolType *base;
750 class IntRules : public BaseRules
752 using Rust::TyTy::BaseRules::visit;
754 public:
755 IntRules (IntType *base) : BaseRules (base), base (base) {}
757 void visit (InferType &type) override
759 // cant assign a float inference variable
760 if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
762 BaseRules::visit (type);
763 return;
766 resolved = base->clone ();
767 resolved->set_ref (type.get_ref ());
770 void visit (IntType &type) override
772 if (type.get_int_kind () != base->get_int_kind ())
774 BaseRules::visit (type);
775 return;
778 resolved
779 = new IntType (type.get_ref (), type.get_ty_ref (), type.get_int_kind ());
782 private:
783 BaseType *get_base () override { return base; }
785 IntType *base;
788 class UintRules : public BaseRules
790 using Rust::TyTy::BaseRules::visit;
792 public:
793 UintRules (UintType *base) : BaseRules (base), base (base) {}
795 void visit (InferType &type) override
797 // cant assign a float inference variable
798 if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
800 BaseRules::visit (type);
801 return;
804 resolved = base->clone ();
805 resolved->set_ref (type.get_ref ());
808 void visit (UintType &type) override
810 if (type.get_uint_kind () != base->get_uint_kind ())
812 BaseRules::visit (type);
813 return;
816 resolved = new UintType (type.get_ref (), type.get_ty_ref (),
817 type.get_uint_kind ());
820 private:
821 BaseType *get_base () override { return base; }
823 UintType *base;
826 class FloatRules : public BaseRules
828 using Rust::TyTy::BaseRules::visit;
830 public:
831 FloatRules (FloatType *base) : BaseRules (base), base (base) {}
833 void visit (InferType &type) override
835 if (type.get_infer_kind () == InferType::InferTypeKind::INTEGRAL)
837 BaseRules::visit (type);
838 return;
841 resolved = base->clone ();
842 resolved->set_ref (type.get_ref ());
845 void visit (FloatType &type) override
847 if (type.get_float_kind () != base->get_float_kind ())
849 BaseRules::visit (type);
850 return;
853 resolved = new FloatType (type.get_ref (), type.get_ty_ref (),
854 type.get_float_kind ());
857 private:
858 BaseType *get_base () override { return base; }
860 FloatType *base;
863 class ADTRules : public BaseRules
865 using Rust::TyTy::BaseRules::visit;
867 public:
868 ADTRules (ADTType *base) : BaseRules (base), base (base) {}
870 void visit (ADTType &type) override
872 if (base->get_adt_kind () != type.get_adt_kind ())
874 BaseRules::visit (type);
875 return;
878 if (base->get_identifier ().compare (type.get_identifier ()) != 0)
880 BaseRules::visit (type);
881 return;
884 if (base->number_of_variants () != type.number_of_variants ())
886 BaseRules::visit (type);
887 return;
890 for (size_t i = 0; i < type.number_of_variants (); ++i)
892 TyTy::VariantDef *a = base->get_variants ().at (i);
893 TyTy::VariantDef *b = type.get_variants ().at (i);
895 if (a->num_fields () != b->num_fields ())
897 BaseRules::visit (type);
898 return;
901 for (size_t j = 0; j < a->num_fields (); j++)
903 TyTy::StructFieldType *base_field = a->get_field_at_index (j);
904 TyTy::StructFieldType *other_field = b->get_field_at_index (j);
906 TyTy::BaseType *this_field_ty = base_field->get_field_type ();
907 TyTy::BaseType *other_field_ty = other_field->get_field_type ();
909 BaseType *unified_ty = this_field_ty->unify (other_field_ty);
910 if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
911 return;
915 // generic args for the unit-struct case
916 if (type.is_unit () && base->is_unit ())
918 rust_assert (type.get_num_substitutions ()
919 == base->get_num_substitutions ());
921 for (size_t i = 0; i < type.get_num_substitutions (); i++)
923 auto &a = base->get_substs ().at (i);
924 auto &b = type.get_substs ().at (i);
926 auto pa = a.get_param_ty ();
927 auto pb = b.get_param_ty ();
929 auto res = pa->unify (pb);
930 if (res->get_kind () == TyTy::TypeKind::ERROR)
932 return;
937 resolved = type.clone ();
940 void visit (InferType &type) override
942 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
944 BaseRules::visit (type);
945 return;
948 resolved = base->clone ();
949 resolved->set_ref (type.get_ref ());
952 private:
953 BaseType *get_base () override { return base; }
955 ADTType *base;
958 class TupleRules : public BaseRules
960 using Rust::TyTy::BaseRules::visit;
962 public:
963 TupleRules (TupleType *base) : BaseRules (base), base (base) {}
965 void visit (TupleType &type) override
967 if (base->num_fields () != type.num_fields ())
969 BaseRules::visit (type);
970 return;
973 std::vector<TyVar> fields;
974 for (size_t i = 0; i < base->num_fields (); i++)
976 BaseType *bo = base->get_field (i);
977 BaseType *fo = type.get_field (i);
979 BaseType *unified_ty = bo->unify (fo);
980 if (unified_ty->get_kind () == TyTy::TypeKind::ERROR)
981 return;
983 fields.push_back (TyVar (unified_ty->get_ref ()));
986 resolved = new TyTy::TupleType (type.get_ref (), type.get_ty_ref (),
987 type.get_ident ().locus, fields);
990 void visit (InferType &type) override
992 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
994 BaseRules::visit (type);
995 return;
998 resolved = base->clone ();
999 resolved->set_ref (type.get_ref ());
1002 private:
1003 BaseType *get_base () override { return base; }
1005 TupleType *base;
1008 class USizeRules : public BaseRules
1010 using Rust::TyTy::BaseRules::visit;
1012 public:
1013 USizeRules (USizeType *base) : BaseRules (base), base (base) {}
1015 void visit (InferType &type) override
1017 // cant assign a float inference variable
1018 if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
1020 BaseRules::visit (type);
1021 return;
1024 resolved = base->clone ();
1025 resolved->set_ref (type.get_ref ());
1028 void visit (USizeType &type) override { resolved = type.clone (); }
1030 private:
1031 BaseType *get_base () override { return base; }
1033 USizeType *base;
1036 class ISizeRules : public BaseRules
1038 using Rust::TyTy::BaseRules::visit;
1040 public:
1041 ISizeRules (ISizeType *base) : BaseRules (base), base (base) {}
1043 void visit (InferType &type) override
1045 // cant assign a float inference variable
1046 if (type.get_infer_kind () == InferType::InferTypeKind::FLOAT)
1048 BaseRules::visit (type);
1049 return;
1052 resolved = base->clone ();
1053 resolved->set_ref (type.get_ref ());
1056 void visit (ISizeType &type) override { resolved = type.clone (); }
1058 private:
1059 BaseType *get_base () override { return base; }
1061 ISizeType *base;
1064 class CharRules : public BaseRules
1066 using Rust::TyTy::BaseRules::visit;
1068 public:
1069 CharRules (CharType *base) : BaseRules (base), base (base) {}
1071 void visit (InferType &type) override
1073 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1075 BaseRules::visit (type);
1076 return;
1079 resolved = base->clone ();
1080 resolved->set_ref (type.get_ref ());
1083 void visit (CharType &type) override { resolved = type.clone (); }
1085 private:
1086 BaseType *get_base () override { return base; }
1088 CharType *base;
1091 class ReferenceRules : public BaseRules
1093 using Rust::TyTy::BaseRules::visit;
1095 public:
1096 ReferenceRules (ReferenceType *base) : BaseRules (base), base (base) {}
1098 void visit (ReferenceType &type) override
1100 auto base_type = base->get_base ();
1101 auto other_base_type = type.get_base ();
1103 TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
1104 if (base_resolved == nullptr
1105 || base_resolved->get_kind () == TypeKind::ERROR)
1107 BaseRules::visit (type);
1108 return;
1111 // rust is permissive about mutablity here you can always go from mutable to
1112 // immutable but not the otherway round
1113 bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
1114 if (!mutability_ok)
1116 BaseRules::visit (type);
1117 return;
1120 resolved = new ReferenceType (base->get_ref (), base->get_ty_ref (),
1121 TyVar (base_resolved->get_ref ()),
1122 base->mutability ());
1125 void visit (InferType &type) override
1127 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1129 BaseRules::visit (type);
1130 return;
1133 resolved = base->clone ();
1134 resolved->set_ref (type.get_ref ());
1137 private:
1138 BaseType *get_base () override { return base; }
1140 ReferenceType *base;
1143 class PointerRules : public BaseRules
1145 using Rust::TyTy::BaseRules::visit;
1147 public:
1148 PointerRules (PointerType *base) : BaseRules (base), base (base) {}
1150 void visit (PointerType &type) override
1152 auto base_type = base->get_base ();
1153 auto other_base_type = type.get_base ();
1155 TyTy::BaseType *base_resolved = base_type->unify (other_base_type);
1156 if (base_resolved == nullptr
1157 || base_resolved->get_kind () == TypeKind::ERROR)
1159 BaseRules::visit (type);
1160 return;
1163 // rust is permissive about mutablity here you can always go from mutable to
1164 // immutable but not the otherway round
1165 bool mutability_ok = base->is_mutable () ? type.is_mutable () : true;
1166 if (!mutability_ok)
1168 BaseRules::visit (type);
1169 return;
1172 resolved = new PointerType (base->get_ref (), base->get_ty_ref (),
1173 TyVar (base_resolved->get_ref ()),
1174 base->mutability ());
1177 void visit (InferType &type) override
1179 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1181 BaseRules::visit (type);
1182 return;
1185 resolved = base->clone ();
1186 resolved->set_ref (type.get_ref ());
1189 private:
1190 BaseType *get_base () override { return base; }
1192 PointerType *base;
1195 class ParamRules : public BaseRules
1197 using Rust::TyTy::BaseRules::visit;
1199 public:
1200 ParamRules (ParamType *base) : BaseRules (base), base (base) {}
1202 // param types are a placeholder we shouldn't have cases where we unify
1203 // against it. eg: struct foo<T> { a: T }; When we invoke it we can do either:
1205 // foo<i32>{ a: 123 }.
1206 // Then this enforces the i32 type to be referenced on the
1207 // field via an hirid.
1209 // rust also allows for a = foo{a:123}; Where we can use an Inference Variable
1210 // to handle the typing of the struct
1211 BaseType *unify (BaseType *other) override final
1213 if (!base->can_resolve ())
1214 return BaseRules::unify (other);
1216 auto lookup = base->resolve ();
1217 return lookup->unify (other);
1220 void visit (ParamType &type) override
1222 if (base->get_symbol ().compare (type.get_symbol ()) != 0)
1224 BaseRules::visit (type);
1225 return;
1228 resolved = type.clone ();
1231 void visit (InferType &type) override
1233 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1235 BaseRules::visit (type);
1236 return;
1239 resolved = base->clone ();
1242 private:
1243 BaseType *get_base () override { return base; }
1245 ParamType *base;
1248 class StrRules : public BaseRules
1250 // FIXME we will need a enum for the StrType like ByteBuf etc..
1251 using Rust::TyTy::BaseRules::visit;
1253 public:
1254 StrRules (StrType *base) : BaseRules (base), base (base) {}
1256 void visit (StrType &type) override { resolved = type.clone (); }
1258 private:
1259 BaseType *get_base () override { return base; }
1261 StrType *base;
1264 class NeverRules : public BaseRules
1266 using Rust::TyTy::BaseRules::visit;
1268 public:
1269 NeverRules (NeverType *base) : BaseRules (base), base (base) {}
1271 void visit (NeverType &type) override { resolved = type.clone (); }
1273 private:
1274 BaseType *get_base () override { return base; }
1276 NeverType *base;
1279 class PlaceholderRules : public BaseRules
1281 using Rust::TyTy::BaseRules::visit;
1283 public:
1284 PlaceholderRules (PlaceholderType *base) : BaseRules (base), base (base) {}
1286 BaseType *unify (BaseType *other) override final
1288 if (!base->can_resolve ())
1289 return BaseRules::unify (other);
1291 BaseType *lookup = base->resolve ();
1292 return lookup->unify (other);
1295 void visit (PlaceholderType &type) override
1297 if (base->get_symbol ().compare (type.get_symbol ()) != 0)
1299 BaseRules::visit (type);
1300 return;
1303 resolved = type.clone ();
1306 void visit (InferType &type) override
1308 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1310 BaseRules::visit (type);
1311 return;
1314 resolved = base->clone ();
1317 private:
1318 BaseType *get_base () override { return base; }
1320 PlaceholderType *base;
1323 class DynamicRules : public BaseRules
1325 using Rust::TyTy::BaseRules::visit;
1327 public:
1328 DynamicRules (DynamicObjectType *base) : BaseRules (base), base (base) {}
1330 void visit (InferType &type) override
1332 if (type.get_infer_kind () != InferType::InferTypeKind::GENERAL)
1334 BaseRules::visit (type);
1335 return;
1338 resolved = base->clone ();
1341 void visit (DynamicObjectType &type) override
1343 if (base->num_specified_bounds () != type.num_specified_bounds ())
1345 BaseRules::visit (type);
1346 return;
1349 Location ref_locus = mappings->lookup_location (type.get_ref ());
1350 if (!base->bounds_compatible (type, ref_locus, true))
1352 BaseRules::visit (type);
1353 return;
1356 resolved = base->clone ();
1359 private:
1360 BaseType *get_base () override { return base; }
1362 DynamicObjectType *base;
1365 } // namespace TyTy
1366 } // namespace Rust
1368 #endif // RUST_TYTY_RULES