LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-expr.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 87.5 % 1418 1241
Test Date: 2026-07-11 15:47:05 Functions: 98.1 % 53 52
Legend: Lines:     hit not hit

            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 "optional.h"
      20              : #include "rust-common.h"
      21              : #include "rust-diagnostics.h"
      22              : #include "rust-hir-expr.h"
      23              : #include "rust-hir-map.h"
      24              : #include "rust-rib.h"
      25              : #include "rust-system.h"
      26              : #include "rust-tyty-call.h"
      27              : #include "rust-hir-type-check-struct-field.h"
      28              : #include "rust-hir-path-probe.h"
      29              : #include "rust-substitution-mapper.h"
      30              : #include "rust-hir-trait-resolve.h"
      31              : #include "rust-hir-dot-operator.h"
      32              : #include "rust-hir-type-check-pattern.h"
      33              : #include "rust-hir-type-check-expr.h"
      34              : #include "rust-hir-type-check-stmt.h"
      35              : #include "rust-hir-type-check-item.h"
      36              : #include "rust-type-util.h"
      37              : #include "rust-finalized-name-resolution-context.h"
      38              : #include "rust-compile-base.h"
      39              : #include "rust-tyty-util.h"
      40              : #include "rust-tyty.h"
      41              : 
      42              : namespace Rust {
      43              : namespace Resolver {
      44              : 
      45       150489 : TypeCheckExpr::TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {}
      46              : 
      47              : // Perform type checking on expr. Also runs type unification algorithm.
      48              : // Returns the unified type of expr
      49              : TyTy::BaseType *
      50       150481 : TypeCheckExpr::Resolve (HIR::Expr &expr)
      51              : {
      52       150481 :   TypeCheckExpr resolver;
      53       150481 :   expr.accept_vis (resolver);
      54              : 
      55       150481 :   if (resolver.infered == nullptr)
      56           86 :     return new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
      57              : 
      58       150395 :   if (resolver.infered->get_kind () != TyTy::TypeKind::CONST)
      59              :     {
      60       150258 :       auto ref = expr.get_mappings ().get_hirid ();
      61       150258 :       resolver.infered->set_ref (ref);
      62              :     }
      63       150395 :   resolver.context->insert_type (expr.get_mappings (), resolver.infered);
      64              : 
      65       150395 :   if (auto fn = resolver.infered->try_as<const TyTy::FnType> ())
      66              :     {
      67        10737 :       if (fn->is_syn_constant ())
      68           28 :         resolver.infered = fn->get_return_type ();
      69              :     }
      70              : 
      71       150395 :   return resolver.infered;
      72       150481 : }
      73              : 
      74              : TyTy::BaseType *
      75            8 : TypeCheckExpr::ResolveOpOverload (LangItem::Kind lang_item_type,
      76              :                                   HIR::OperatorExprMeta expr,
      77              :                                   TyTy::BaseType *lhs, TyTy::BaseType *rhs,
      78              :                                   HIR::PathIdentSegment specified_segment)
      79              : {
      80            8 :   TypeCheckExpr resolver;
      81              : 
      82           16 :   resolver.resolve_operator_overload (lang_item_type, expr, lhs, rhs,
      83              :                                       specified_segment);
      84            8 :   return resolver.infered;
      85            8 : }
      86              : 
      87              : void
      88          900 : TypeCheckExpr::visit (HIR::TupleIndexExpr &expr)
      89              : {
      90          900 :   auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ());
      91          900 :   if (resolved->get_kind () == TyTy::TypeKind::ERROR)
      92              :     {
      93            0 :       rust_error_at (expr.get_tuple_expr ().get_locus (),
      94              :                      "failed to resolve TupleIndexExpr receiver");
      95            0 :       return;
      96              :     }
      97              : 
      98              :   // FIXME does this require autoderef here?
      99          900 :   if (resolved->get_kind () == TyTy::TypeKind::REF)
     100              :     {
     101          317 :       TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (resolved);
     102          317 :       resolved = r->get_base ();
     103              :     }
     104              : 
     105          900 :   bool is_valid_type = resolved->get_kind () == TyTy::TypeKind::ADT
     106          900 :                        || resolved->get_kind () == TyTy::TypeKind::TUPLE;
     107          900 :   if (!is_valid_type)
     108              :     {
     109            2 :       rust_error_at (expr.get_tuple_expr ().get_locus (),
     110              :                      "Expected Tuple or ADT got: %s",
     111            2 :                      resolved->as_string ().c_str ());
     112            2 :       return;
     113              :     }
     114              : 
     115          898 :   if (resolved->get_kind () == TyTy::TypeKind::TUPLE)
     116              :     {
     117          151 :       TyTy::TupleType *tuple = static_cast<TyTy::TupleType *> (resolved);
     118          151 :       TupleIndex index = expr.get_tuple_index ();
     119          151 :       if ((size_t) index >= tuple->num_fields ())
     120              :         {
     121            1 :           rust_error_at (expr.get_locus (), ErrorCode::E0609,
     122              :                          "no field %qi on type %qs", index,
     123            1 :                          resolved->get_name ().c_str ());
     124            1 :           return;
     125              :         }
     126              : 
     127          150 :       auto field_tyty = tuple->get_field ((size_t) index);
     128          150 :       if (field_tyty == nullptr)
     129              :         {
     130            0 :           rust_error_at (expr.get_locus (),
     131              :                          "failed to lookup field type at index %i", index);
     132            0 :           return;
     133              :         }
     134              : 
     135          150 :       infered = field_tyty;
     136          150 :       return;
     137              :     }
     138              : 
     139          747 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (resolved);
     140          747 :   if (!adt->is_tuple_struct ())
     141              :     {
     142            2 :       rust_error_at (expr.get_locus (),
     143              :                      "expected tuple or tuple struct, found %qs",
     144            2 :                      adt->get_name ().c_str ());
     145            2 :       return;
     146              :     }
     147          745 :   rust_assert (adt->number_of_variants () == 1);
     148              : 
     149          745 :   TyTy::VariantDef *variant = adt->get_variants ().at (0);
     150          745 :   TupleIndex index = expr.get_tuple_index ();
     151          745 :   if ((size_t) index >= variant->num_fields ())
     152              :     {
     153            0 :       rust_error_at (expr.get_locus (), "unknown field at index %i", index);
     154            0 :       return;
     155              :     }
     156              : 
     157          745 :   auto field_tyty = variant->get_field_at_index ((size_t) index);
     158          745 :   if (field_tyty == nullptr)
     159              :     {
     160            0 :       rust_error_at (expr.get_locus (),
     161              :                      "failed to lookup field type at index %i", index);
     162            0 :       return;
     163              :     }
     164              : 
     165          745 :   infered = field_tyty->get_field_type ();
     166              : }
     167              : 
     168              : void
     169          567 : TypeCheckExpr::visit (HIR::TupleExpr &expr)
     170              : {
     171          567 :   if (expr.is_unit ())
     172              :     {
     173          151 :       infered = TyTy::TupleType::get_unit_type ();
     174          151 :       return;
     175              :     }
     176              : 
     177          416 :   std::vector<TyTy::TyVar> fields;
     178         1388 :   for (auto &elem : expr.get_tuple_elems ())
     179              :     {
     180          972 :       auto field_ty = TypeCheckExpr::Resolve (*elem);
     181          972 :       fields.emplace_back (field_ty->get_ref ());
     182              :     }
     183          832 :   infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (),
     184          832 :                                  expr.get_locus (), fields);
     185          416 : }
     186              : 
     187              : void
     188            3 : TypeCheckExpr::visit (HIR::BoxExpr &expr)
     189              : {
     190            3 :   auto owned_box_defid
     191            3 :     = mappings.get_lang_item (LangItem::Kind::OWNED_BOX, expr.get_locus ());
     192              : 
     193            3 :   HIR::Item *item = mappings.lookup_defid (owned_box_defid).value ();
     194            3 :   TyTy::BaseType *item_type = nullptr;
     195              : 
     196            3 :   bool ok
     197            3 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
     198            3 :   rust_assert (ok);
     199            3 :   if (item_type->get_kind () != TyTy::TypeKind::ADT)
     200              :     {
     201            0 :       rust_error_at (item->get_locus (), ErrorCode::E0718,
     202              :                      "%qs language item must be applied to a struct",
     203              :                      "owned_box");
     204            2 :       return;
     205              :     }
     206            3 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
     207            3 :   if (!adt->is_tuple_struct () && !adt->is_struct_struct ())
     208              :     {
     209            1 :       rust_error_at (item->get_locus (), ErrorCode::E0718,
     210              :                      "%qs language item must be applied to a struct",
     211              :                      "owned_box");
     212            1 :       return;
     213              :     }
     214              : 
     215              :   // this is at least one generic item
     216            2 :   if (adt->get_num_substitutions () < 1)
     217              :     {
     218            1 :       rust_error_at (expr.get_locus (),
     219              :                      "%qs lang item must be applied to a struct with at least "
     220              :                      "1 generic argument",
     221              :                      "owned_box");
     222            1 :       return;
     223              :     }
     224              : 
     225            1 :   TyTy::BaseType *inner_ty = TypeCheckExpr::Resolve (expr.get_expr ());
     226            1 :   if (inner_ty->get_kind () == TyTy::TypeKind::ERROR)
     227              :     {
     228            0 :       infered = inner_ty;
     229            0 :       return;
     230              :     }
     231              : 
     232            1 :   auto lookup = SubstMapper::InferSubst (adt, expr.get_locus ());
     233            1 :   rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
     234            1 :   TyTy::ADTType *adt_box = static_cast<TyTy::ADTType *> (lookup);
     235              : 
     236            1 :   TyTy::BaseType *infer = adt_box->get_substs ().at (0).get_param_ty ();
     237              : 
     238            2 :   unify_site (expr.get_mappings ().get_hirid (),
     239            1 :               TyTy::TyWithLocation (infer, expr.get_locus ()),
     240            1 :               TyTy::TyWithLocation (inner_ty, expr.get_locus ()),
     241              :               expr.get_locus ());
     242              : 
     243            1 :   infered = adt_box;
     244              : }
     245              : 
     246              : void
     247          531 : TypeCheckExpr::visit (HIR::ReturnExpr &expr)
     248              : {
     249          531 :   if (!context->have_function_context ())
     250              :     {
     251            1 :       rust_error_at (expr.get_locus (), ErrorCode::E0572,
     252              :                      "return statement outside of function body");
     253            1 :       infered = new TyTy::ErrorType (expr.get_mappings ().get_hirid ());
     254            1 :       return;
     255              :     }
     256              : 
     257          530 :   auto fn_return_tyty = context->peek_return_type ();
     258          530 :   location_t expr_locus = expr.has_return_expr ()
     259          530 :                             ? expr.get_expr ().get_locus ()
     260           32 :                             : expr.get_locus ();
     261              : 
     262              :   // Push expected type so the resolver of the return expression
     263              :   // inference before checking its arguments which is needed
     264              :   // for things like:
     265              :   //
     266              :   //    return Try::from_error(...)
     267              :   //
     268              :   // Where Self has to bind from the fn return type before the param
     269              :   // projection can be normalized.
     270          530 :   TyTy::BaseType *expr_ty;
     271          530 :   if (expr.has_return_expr ())
     272              :     {
     273          498 :       context->push_expected_type (fn_return_tyty);
     274          498 :       expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
     275          498 :       context->pop_expected_type ();
     276              :     }
     277              :   else
     278           32 :     expr_ty = TyTy::TupleType::get_unit_type ();
     279              : 
     280         1060 :   coercion_site (expr.get_mappings ().get_hirid (),
     281          530 :                  TyTy::TyWithLocation (fn_return_tyty),
     282          530 :                  TyTy::TyWithLocation (expr_ty, expr_locus), expr.get_locus ());
     283              : 
     284          530 :   infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
     285              : }
     286              : 
     287              : void
     288        12571 : TypeCheckExpr::visit (HIR::CallExpr &expr)
     289              : {
     290        12571 :   TyTy::BaseType *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ());
     291              : 
     292        12571 :   rust_debug_loc (expr.get_locus (), "resolved_call_expr to: {%s}",
     293        12571 :                   function_tyty->get_name ().c_str ());
     294              : 
     295        12571 :   TyTy::VariantDef &variant = TyTy::VariantDef::get_error_node ();
     296        12571 :   if (function_tyty->get_kind () == TyTy::TypeKind::ADT)
     297              :     {
     298         1817 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (function_tyty);
     299         1817 :       if (adt->is_enum ())
     300              :         {
     301              :           // lookup variant id
     302          895 :           HirId variant_id;
     303          895 :           bool ok = context->lookup_variant_definition (
     304          895 :             expr.get_fnexpr ().get_mappings ().get_hirid (), &variant_id);
     305              : 
     306          895 :           if (!ok)
     307              :             {
     308            1 :               rust_error_at (expr.get_locus (), ErrorCode::E0423,
     309              :                              "expected function, tuple struct or tuple "
     310              :                              "variant, found enum");
     311            1 :               return;
     312              :             }
     313              : 
     314          894 :           TyTy::VariantDef *lookup_variant = nullptr;
     315          894 :           ok = adt->lookup_variant_by_id (variant_id, &lookup_variant);
     316          894 :           rust_assert (ok);
     317              : 
     318          894 :           variant = std::move (*lookup_variant->clone ());
     319              :         }
     320              :       else
     321              :         {
     322          922 :           rust_assert (adt->number_of_variants () == 1);
     323          922 :           variant = std::move (*adt->get_variants ().at (0)->clone ());
     324              :         }
     325         1816 :       infered
     326         1816 :         = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
     327         1816 :       return;
     328              :     }
     329              : 
     330        10754 :   bool resolved_fn_trait_call
     331        10754 :     = resolve_fn_trait_call (expr, function_tyty, &infered);
     332        10754 :   if (resolved_fn_trait_call)
     333              :     return;
     334              : 
     335        10688 :   bool valid_tyty
     336        10728 :     = function_tyty->is<TyTy::FnType> () || function_tyty->is<TyTy::FnPtr> ();
     337        10688 :   if (!valid_tyty)
     338              :     {
     339           11 :       bool emit_error = !function_tyty->is<TyTy::ErrorType> ();
     340           11 :       if (emit_error)
     341              :         {
     342            2 :           rich_location r (line_table, expr.get_locus ());
     343            2 :           rust_error_at (r, ErrorCode::E0618, "expected function, found %<%s%>",
     344            2 :                          function_tyty->get_name ().c_str ());
     345            2 :         }
     346           11 :       return;
     347              :     }
     348              : 
     349        10677 :   infered = TyTy::TypeCheckCallExpr::go (function_tyty, expr, variant, context);
     350              : 
     351              :   // Pre-GATS: associated types were PlaceholderType; post-GATS they are
     352              :   // ProjectionType, this hHandle both so the isize special-case still fires
     353        10677 :   auto discriminant_type_lookup
     354        10677 :     = mappings.lookup_lang_item (LangItem::Kind::DISCRIMINANT_TYPE);
     355        10677 :   bool is_discriminant_type = false;
     356        10677 :   if (discriminant_type_lookup)
     357              :     {
     358          824 :       if (auto *p = infered->try_as<TyTy::PlaceholderType> ())
     359            0 :         is_discriminant_type
     360            0 :           = p->get_def_id () == discriminant_type_lookup.value ();
     361        11501 :       else if (auto *p = infered->try_as<TyTy::ProjectionType> ())
     362            0 :         is_discriminant_type
     363            0 :           = p->get_item_defid () == discriminant_type_lookup.value ();
     364              :     }
     365            0 :   if (is_discriminant_type)
     366              :     {
     367              :       // This is a special case: discriminant_value returns the repr of the
     368              :       // enum. We don't currently support repr on enum yet, so the default
     369              :       // is always isize.
     370            0 :       bool ok = context->lookup_builtin ("isize", &infered);
     371            0 :       rust_assert (ok);
     372              : 
     373            0 :       rust_assert (function_tyty->is<TyTy::FnType> ());
     374            0 :       auto &fn = *static_cast<TyTy::FnType *> (function_tyty);
     375            0 :       rust_assert (fn.has_substitutions ());
     376            0 :       rust_assert (fn.get_num_type_params () == 1);
     377            0 :       auto &mapping = fn.get_substs ().at (0);
     378            0 :       auto param_ty = mapping.get_param_ty ();
     379              : 
     380            0 :       if (!param_ty->can_resolve ())
     381              :         {
     382            0 :           rust_internal_error_at (expr.get_locus (),
     383              :                                   "something wrong computing return type");
     384              :           return;
     385              :         }
     386              : 
     387            0 :       auto resolved = param_ty->resolve ();
     388            0 :       if (resolved->is<TyTy::ADTType> ())
     389              :         {
     390            0 :           const auto &adt = *static_cast<TyTy::ADTType *> (resolved);
     391            0 :           infered = adt.get_repr_options ().repr;
     392            0 :           rust_assert (infered != nullptr);
     393              :         }
     394              :     }
     395              : }
     396              : 
     397              : void
     398         2499 : TypeCheckExpr::visit (HIR::AssignmentExpr &expr)
     399              : {
     400         2499 :   infered = TyTy::TupleType::get_unit_type ();
     401              : 
     402         2499 :   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     403         2499 :   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
     404              : 
     405         4998 :   coercion_site (expr.get_mappings ().get_hirid (),
     406         2499 :                  TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     407         2499 :                  TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     408              :                  expr.get_locus ());
     409         2499 : }
     410              : 
     411              : void
     412          677 : TypeCheckExpr::visit (HIR::CompoundAssignmentExpr &expr)
     413              : {
     414          677 :   infered = TyTy::TupleType::get_unit_type ();
     415              : 
     416          677 :   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     417          677 :   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
     418              : 
     419              :   // we dont care about the result of the unify from a compound assignment
     420              :   // since this is a unit-type expr
     421         1354 :   coercion_site (expr.get_mappings ().get_hirid (),
     422          677 :                  TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     423          677 :                  TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     424              :                  expr.get_locus ());
     425              : 
     426          677 :   auto lang_item_type
     427          677 :     = LangItem::CompoundAssignmentOperatorToLangItem (expr.get_expr_type ());
     428          677 :   bool operator_overloaded
     429          677 :     = resolve_operator_overload (lang_item_type, expr, lhs, rhs);
     430          677 :   if (operator_overloaded)
     431              :     return;
     432              : 
     433          663 :   bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ());
     434          663 :   bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ());
     435          663 :   bool valid = valid_lhs && valid_rhs;
     436          663 :   if (!valid)
     437              :     {
     438            0 :       rust_error_at (expr.get_locus (),
     439              :                      "cannot apply operator %qs to types %s and %s",
     440            0 :                      expr.get_operator_str ().c_str (),
     441            0 :                      lhs->as_string ().c_str (), rhs->as_string ().c_str ());
     442            0 :       return;
     443              :     }
     444              : }
     445              : 
     446              : void
     447        20596 : TypeCheckExpr::visit (HIR::LiteralExpr &expr)
     448              : {
     449        20596 :   infered = resolve_literal (expr.get_mappings (), expr.get_literal (),
     450              :                              expr.get_locus ());
     451        20596 : }
     452              : 
     453              : void
     454         3386 : TypeCheckExpr::visit (HIR::ArithmeticOrLogicalExpr &expr)
     455              : {
     456         3386 :   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     457         3386 :   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
     458              : 
     459         3386 :   auto lang_item_type = LangItem::OperatorToLangItem (expr.get_expr_type ());
     460         3386 :   bool operator_overloaded
     461         3386 :     = resolve_operator_overload (lang_item_type, expr, lhs, rhs);
     462         3386 :   if (operator_overloaded)
     463              :     return;
     464              : 
     465         3217 :   bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ());
     466         3217 :   bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ());
     467         3217 :   bool valid = valid_lhs && valid_rhs;
     468         3217 :   if (!valid)
     469              :     {
     470            6 :       rust_error_at (expr.get_locus (),
     471              :                      "cannot apply operator %qs to types %s and %s",
     472            6 :                      expr.get_operator_str ().c_str (),
     473            6 :                      lhs->as_string ().c_str (), rhs->as_string ().c_str ());
     474            3 :       return;
     475              :     }
     476              : 
     477         3214 :   switch (expr.get_expr_type ())
     478              :     {
     479           69 :     case ArithmeticOrLogicalOperator::LEFT_SHIFT:
     480           69 :     case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
     481           69 :       {
     482           69 :         TyTy::TyWithLocation from (rhs, expr.get_rhs ().get_locus ());
     483           69 :         TyTy::TyWithLocation to (lhs, expr.get_lhs ().get_locus ());
     484           69 :         infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
     485              :                              expr.get_locus ());
     486              :       }
     487           69 :       break;
     488              : 
     489         3145 :     default:
     490         3145 :       {
     491         6290 :         infered = unify_site (
     492         3145 :           expr.get_mappings ().get_hirid (),
     493         3145 :           TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     494         3145 :           TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     495              :           expr.get_locus ());
     496              :       }
     497         3145 :       break;
     498              :     }
     499              : }
     500              : 
     501              : void
     502         3536 : TypeCheckExpr::visit (HIR::ComparisonExpr &expr)
     503              : {
     504         3536 :   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     505         3536 :   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
     506              : 
     507         3536 :   auto borrowed_rhs
     508         3536 :     = new TyTy::ReferenceType (mappings.get_next_hir_id (),
     509         3536 :                                TyTy::TyVar (rhs->get_ref ()), Mutability::Imm);
     510         3536 :   context->insert_implicit_type (borrowed_rhs->get_ref (), borrowed_rhs);
     511              : 
     512         3536 :   auto seg_name = LangItem::ComparisonToSegment (expr.get_expr_type ());
     513         7072 :   auto segment = HIR::PathIdentSegment (seg_name);
     514         3536 :   auto lang_item_type = LangItem::ComparisonToLangItem (expr.get_expr_type ());
     515              : 
     516         3536 :   bool operator_overloaded
     517         3536 :     = resolve_operator_overload (lang_item_type, expr, lhs, borrowed_rhs,
     518              :                                  segment);
     519         3536 :   if (operator_overloaded)
     520          955 :     return;
     521              : 
     522         5162 :   unify_site (expr.get_mappings ().get_hirid (),
     523         2581 :               TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     524         2581 :               TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     525              :               expr.get_locus ());
     526              : 
     527         2581 :   bool ok = context->lookup_builtin ("bool", &infered);
     528         2581 :   rust_assert (ok);
     529         3536 : }
     530              : 
     531              : void
     532          403 : TypeCheckExpr::visit (HIR::LazyBooleanExpr &expr)
     533              : {
     534          403 :   auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ());
     535          403 :   auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ());
     536              : 
     537              :   // we expect the lhs and rhs must be bools at this point
     538          403 :   TyTy::BaseType *boolean_node = nullptr;
     539          403 :   bool ok = context->lookup_builtin ("bool", &boolean_node);
     540          403 :   rust_assert (ok);
     541              : 
     542              :   // verify the lhs and rhs before unifying together
     543          806 :   lhs = unify_site (expr.get_mappings ().get_hirid (),
     544              :                     TyTy::TyWithLocation (boolean_node,
     545          403 :                                           expr.get_lhs ().get_locus ()),
     546          403 :                     TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     547              :                     expr.get_locus ());
     548              : 
     549          806 :   rhs = unify_site (expr.get_mappings ().get_hirid (),
     550              :                     TyTy::TyWithLocation (boolean_node,
     551          403 :                                           expr.get_rhs ().get_locus ()),
     552          403 :                     TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     553              :                     expr.get_locus ());
     554              : 
     555          403 :   infered
     556          806 :     = unify_site (expr.get_mappings ().get_hirid (),
     557          403 :                   TyTy::TyWithLocation (lhs, expr.get_lhs ().get_locus ()),
     558          403 :                   TyTy::TyWithLocation (rhs, expr.get_rhs ().get_locus ()),
     559              :                   expr.get_locus ());
     560          403 : }
     561              : 
     562              : void
     563          687 : TypeCheckExpr::visit (HIR::NegationExpr &expr)
     564              : {
     565          687 :   auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
     566              : 
     567              :   // check for operator overload
     568          687 :   auto lang_item_type
     569          687 :     = LangItem::NegationOperatorToLangItem (expr.get_expr_type ());
     570          687 :   bool operator_overloaded
     571          687 :     = resolve_operator_overload (lang_item_type, expr, negated_expr_ty,
     572              :                                  nullptr);
     573          687 :   if (operator_overloaded)
     574              :     return;
     575              : 
     576              :   // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators
     577          673 :   switch (expr.get_expr_type ())
     578              :     {
     579          408 :     case NegationOperator::NEGATE:
     580          408 :       {
     581          408 :         bool valid
     582          408 :           = (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
     583          268 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
     584          268 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::FLOAT)
     585          266 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::ISIZE)
     586          263 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::USIZE)
     587          263 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
     588          262 :                 && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
     589              :                     == TyTy::InferType::INTEGRAL))
     590          409 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
     591            0 :                 && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
     592          672 :                     == TyTy::InferType::FLOAT));
     593            1 :         if (!valid)
     594              :           {
     595            1 :             rust_error_at (expr.get_locus (), "cannot apply unary - to %s",
     596            1 :                            negated_expr_ty->as_string ().c_str ());
     597            1 :             return;
     598              :           }
     599              :       }
     600              :       break;
     601              : 
     602          265 :     case NegationOperator::NOT:
     603          265 :       {
     604          265 :         bool valid
     605          265 :           = (negated_expr_ty->get_kind () == TyTy::TypeKind::BOOL)
     606           59 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::INT)
     607           52 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::UINT)
     608          275 :             || (negated_expr_ty->get_kind () == TyTy::TypeKind::INFER
     609            9 :                 && (((TyTy::InferType *) negated_expr_ty)->get_infer_kind ()
     610          672 :                     == TyTy::InferType::INTEGRAL));
     611            1 :         if (!valid)
     612              :           {
     613            1 :             rust_error_at (expr.get_locus (), "cannot apply unary %<!%> to %s",
     614            1 :                            negated_expr_ty->as_string ().c_str ());
     615            1 :             return;
     616              :           }
     617              :       }
     618              :       break;
     619              :     }
     620              : 
     621          671 :   infered = negated_expr_ty->clone ();
     622          671 :   infered->append_reference (negated_expr_ty->get_ref ());
     623              : }
     624              : 
     625              : void
     626         1229 : TypeCheckExpr::visit (HIR::IfExpr &expr)
     627              : {
     628         1229 :   TyTy::BaseType *bool_ty = nullptr;
     629         1229 :   bool ok = context->lookup_builtin ("bool", &bool_ty);
     630         1229 :   rust_assert (ok);
     631              : 
     632         1229 :   TyTy::BaseType *cond_type = TypeCheckExpr::Resolve (expr.get_if_condition ());
     633              : 
     634         2458 :   unify_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty),
     635              :               TyTy::TyWithLocation (cond_type,
     636         1229 :                                     expr.get_if_condition ().get_locus ()),
     637              :               expr.get_locus ());
     638              : 
     639         1229 :   TyTy::BaseType *block_type = TypeCheckExpr::Resolve (expr.get_if_block ());
     640              : 
     641         1229 :   TyTy::BaseType *unit_ty = nullptr;
     642         1229 :   ok = context->lookup_builtin ("()", &unit_ty);
     643         1229 :   rust_assert (ok);
     644              : 
     645         1229 :   infered
     646         2458 :     = coercion_site (expr.get_mappings ().get_hirid (),
     647         1229 :                      TyTy::TyWithLocation (unit_ty),
     648              :                      TyTy::TyWithLocation (block_type,
     649         1229 :                                            expr.get_if_block ().get_locus ()),
     650              :                      expr.get_locus ());
     651         1229 : }
     652              : 
     653              : void
     654         1261 : TypeCheckExpr::visit (HIR::IfExprConseqElse &expr)
     655              : {
     656         1261 :   TyTy::BaseType *bool_ty = nullptr;
     657         1261 :   bool ok = context->lookup_builtin ("bool", &bool_ty);
     658         1261 :   rust_assert (ok);
     659              : 
     660         1261 :   TyTy::BaseType *cond_type = TypeCheckExpr::Resolve (expr.get_if_condition ());
     661              : 
     662         2522 :   unify_site (expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (bool_ty),
     663              :               TyTy::TyWithLocation (cond_type,
     664         1261 :                                     expr.get_if_condition ().get_locus ()),
     665              :               expr.get_locus ());
     666              : 
     667         1261 :   auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ());
     668         1261 :   auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ());
     669              : 
     670         1261 :   if (if_blk_resolved->get_kind () == TyTy::NEVER)
     671           40 :     infered = else_blk_resolved;
     672         1221 :   else if (else_blk_resolved->get_kind () == TyTy::NEVER)
     673            7 :     infered = if_blk_resolved;
     674              :   else
     675              :     {
     676         1214 :       infered
     677         2428 :         = unify_site (expr.get_mappings ().get_hirid (),
     678              :                       TyTy::TyWithLocation (if_blk_resolved,
     679         1214 :                                             expr.get_if_block ().get_locus ()),
     680              :                       TyTy::TyWithLocation (
     681         1214 :                         else_blk_resolved, expr.get_else_block ().get_locus ()),
     682              :                       expr.get_locus ());
     683              :     }
     684         1261 : }
     685              : 
     686              : void
     687         3662 : TypeCheckExpr::visit (HIR::UnsafeBlockExpr &expr)
     688              : {
     689         3662 :   infered = TypeCheckExpr::Resolve (expr.get_block_expr ());
     690         3662 : }
     691              : 
     692              : void
     693        23218 : TypeCheckExpr::visit (HIR::BlockExpr &expr)
     694              : {
     695        23218 :   bool has_label = expr.has_label ();
     696        23218 :   if (expr.has_label ())
     697            3 :     context->push_new_loop_context (expr.get_mappings ().get_hirid (),
     698              :                                     expr.get_locus ());
     699              : 
     700              :   // Forward the caller's expected type to the block's tail expression only.
     701        23218 :   TyTy::BaseType *outer_expected = context->peek_expected_type ();
     702        23218 :   context->push_expected_type (nullptr);
     703              : 
     704        47408 :   for (auto &s : expr.get_statements ())
     705              :     {
     706        24190 :       if (!s->is_item ())
     707        23762 :         continue;
     708              : 
     709          428 :       TypeCheckStmt::Resolve (*s);
     710              :     }
     711              : 
     712        47408 :   for (auto &s : expr.get_statements ())
     713              :     {
     714        24190 :       if (s->is_item ())
     715          428 :         continue;
     716              : 
     717        23762 :       auto resolved = TypeCheckStmt::Resolve (*s);
     718        23762 :       if (resolved == nullptr)
     719              :         {
     720            0 :           rust_error_at (s->get_locus (), "failure to resolve type");
     721            0 :           context->pop_expected_type ();
     722            0 :           if (has_label)
     723            0 :             context->pop_loop_context ();
     724            0 :           return;
     725              :         }
     726              : 
     727        23762 :       if (s->is_unit_check_needed () && !resolved->is_unit ())
     728              :         {
     729            6 :           auto unit = TyTy::TupleType::get_unit_type ();
     730           12 :           unify_site (s->get_mappings ().get_hirid (),
     731            6 :                       TyTy::TyWithLocation (unit),
     732            6 :                       TyTy::TyWithLocation (resolved), s->get_locus ());
     733              :         }
     734              :     }
     735              : 
     736        23218 :   context->pop_expected_type ();
     737              : 
     738        23218 :   TyTy::BaseType *tail_expr_type = nullptr;
     739        23218 :   if (expr.has_expr ())
     740              :     {
     741        16445 :       context->push_expected_type (outer_expected);
     742        16445 :       tail_expr_type = TypeCheckExpr::Resolve (expr.get_final_expr ());
     743        16445 :       context->pop_expected_type ();
     744              :     }
     745              : 
     746        23218 :   TyTy::BaseType *label_context_type = nullptr;
     747        23218 :   bool label_context_type_infered = false;
     748        23218 :   if (has_label)
     749              :     {
     750            3 :       label_context_type = context->pop_loop_context ();
     751              : 
     752            3 :       label_context_type_infered
     753            3 :         = (label_context_type->get_kind () != TyTy::TypeKind::INFER)
     754            3 :           || ((label_context_type->get_kind () == TyTy::TypeKind::INFER)
     755            3 :               && (((TyTy::InferType *) label_context_type)->get_infer_kind ()
     756              :                   != TyTy::InferType::GENERAL));
     757              :     }
     758              : 
     759        23218 :   if (tail_expr_type != nullptr)
     760              :     {
     761        16445 :       if (label_context_type_infered)
     762              :         {
     763            2 :           if (tail_expr_type->get_kind () == TyTy::TypeKind::NEVER)
     764            0 :             infered = label_context_type;
     765              :           else
     766            4 :             infered = unify_site (
     767            2 :               expr.get_mappings ().get_hirid (),
     768            2 :               TyTy::TyWithLocation (label_context_type),
     769              :               TyTy::TyWithLocation (tail_expr_type,
     770            2 :                                     expr.get_final_expr ().get_locus ()),
     771              :               expr.get_locus ());
     772              :         }
     773              :       else
     774        16443 :         infered = tail_expr_type;
     775              :     }
     776         6773 :   else if (label_context_type_infered)
     777            1 :     infered = label_context_type;
     778         6772 :   else if (expr.is_tail_reachable ())
     779         6321 :     infered = TyTy::TupleType::get_unit_type ();
     780              :   else
     781              :     {
     782              :       // FIXME this seems wrong
     783          451 :       infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
     784              :     }
     785              : }
     786              : 
     787              : void
     788          689 : TypeCheckExpr::visit (HIR::AnonConst &expr)
     789              : {
     790          689 :   if (!expr.is_deferred ())
     791              :     {
     792          677 :       infered = TypeCheckExpr::Resolve (expr.get_inner_expr ());
     793          677 :       return;
     794              :     }
     795              : 
     796           12 :   TyTy::TyVar var
     797           12 :     = TyTy::TyVar::get_implicit_const_infer_var (expr.get_locus ());
     798           12 :   infered = var.get_tyty ();
     799              : }
     800              : 
     801              : void
     802           15 : TypeCheckExpr::visit (HIR::ConstBlock &expr)
     803              : {
     804           15 :   infered = TypeCheckExpr::Resolve (expr.get_const_expr ());
     805           15 : }
     806              : 
     807              : void
     808           66 : TypeCheckExpr::visit (HIR::RangeFromToExpr &expr)
     809              : {
     810           66 :   auto lang_item_type = LangItem::Kind::RANGE;
     811              : 
     812           66 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
     813              :   // we need to have it maybe
     814           66 :   if (!lang_item_defined)
     815              :     {
     816            0 :       rust_internal_error_at (expr.get_locus (),
     817              :                               "unable to find relevant lang item: %s",
     818            0 :                               LangItem::ToString (lang_item_type).c_str ());
     819              :       return;
     820              :     }
     821           66 :   DefId respective_lang_item_id = lang_item_defined.value ();
     822              : 
     823              :   // look it up and it _must_ be a struct definition
     824           66 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
     825              : 
     826           66 :   TyTy::BaseType *item_type = nullptr;
     827           66 :   bool ok
     828           66 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
     829           66 :   rust_assert (ok);
     830           66 :   rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
     831           66 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
     832              : 
     833              :   // this is a single generic item lets assert that
     834           66 :   rust_assert (adt->get_num_substitutions () == 1);
     835              : 
     836              :   // resolve the range expressions and these types must unify then we use that
     837              :   // type to substitute into the ADT
     838           66 :   TyTy::BaseType *from_ty = TypeCheckExpr::Resolve (expr.get_from_expr ());
     839           66 :   TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ());
     840              : 
     841          132 :   TyTy::BaseType *unified = unify_site (
     842           66 :     expr.get_mappings ().get_hirid (),
     843           66 :     TyTy::TyWithLocation (from_ty, expr.get_from_expr ().get_locus ()),
     844           66 :     TyTy::TyWithLocation (to_ty, expr.get_to_expr ().get_locus ()),
     845           66 :     expr.get_locus ());
     846              : 
     847              :   // substitute it in
     848           66 :   std::vector<TyTy::SubstitutionArg> subst_mappings;
     849           66 :   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
     850           66 :   subst_mappings.emplace_back (param_ref, unified);
     851              : 
     852           66 :   TyTy::SubstitutionArgumentMappings subst (
     853           66 :     subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
     854           66 :     expr.get_locus ());
     855           66 :   infered = SubstMapperInternal::Resolve (adt, subst);
     856           66 : }
     857              : 
     858              : void
     859            7 : TypeCheckExpr::visit (HIR::RangeFromExpr &expr)
     860              : {
     861            7 :   auto lang_item_type = LangItem::Kind::RANGE_FROM;
     862              : 
     863            7 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
     864              :   // we need to have it maybe
     865            7 :   if (!lang_item_defined)
     866              :     {
     867            0 :       rust_internal_error_at (expr.get_locus (),
     868              :                               "unable to find relevant lang item: %s",
     869            0 :                               LangItem::ToString (lang_item_type).c_str ());
     870              :       return;
     871              :     }
     872            7 :   DefId &respective_lang_item_id = lang_item_defined.value ();
     873              : 
     874              :   // look it up and it _must_ be a struct definition
     875            7 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
     876              : 
     877            7 :   TyTy::BaseType *item_type = nullptr;
     878            7 :   bool ok
     879            7 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
     880            7 :   rust_assert (ok);
     881            7 :   rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
     882            7 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
     883              : 
     884              :   // this is a single generic item lets assert that
     885            7 :   rust_assert (adt->get_num_substitutions () == 1);
     886              : 
     887              :   // resolve the range expressions and these types must unify then we use that
     888              :   // type to substitute into the ADT
     889            7 :   TyTy::BaseType *from_ty = TypeCheckExpr::Resolve (expr.get_from_expr ());
     890              : 
     891              :   // substitute it in
     892            7 :   std::vector<TyTy::SubstitutionArg> subst_mappings;
     893            7 :   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
     894            7 :   subst_mappings.emplace_back (param_ref, from_ty);
     895              : 
     896            7 :   TyTy::SubstitutionArgumentMappings subst (
     897            7 :     subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
     898            7 :     expr.get_locus ());
     899            7 :   infered = SubstMapperInternal::Resolve (adt, subst);
     900            7 : }
     901              : 
     902              : void
     903            7 : TypeCheckExpr::visit (HIR::RangeToExpr &expr)
     904              : {
     905            7 :   auto lang_item_type = LangItem::Kind::RANGE_TO;
     906              : 
     907            7 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
     908              :   // we need to have it maybe
     909            7 :   if (!lang_item_defined)
     910              :     {
     911            0 :       rust_internal_error_at (expr.get_locus (),
     912              :                               "unable to find relevant lang item: %s",
     913            0 :                               LangItem::ToString (lang_item_type).c_str ());
     914              :       return;
     915              :     }
     916              : 
     917            7 :   DefId &respective_lang_item_id = lang_item_defined.value ();
     918              :   // look it up and it _must_ be a struct definition
     919            7 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
     920              : 
     921            7 :   TyTy::BaseType *item_type = nullptr;
     922            7 :   bool ok
     923            7 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
     924            7 :   rust_assert (ok);
     925            7 :   rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
     926            7 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
     927              : 
     928              :   // this is a single generic item lets assert that
     929            7 :   rust_assert (adt->get_num_substitutions () == 1);
     930              : 
     931              :   // resolve the range expressions and these types must unify then we use that
     932              :   // type to substitute into the ADT
     933            7 :   TyTy::BaseType *from_ty = TypeCheckExpr::Resolve (expr.get_to_expr ());
     934              : 
     935              :   // substitute it in
     936            7 :   std::vector<TyTy::SubstitutionArg> subst_mappings;
     937            7 :   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
     938            7 :   subst_mappings.emplace_back (param_ref, from_ty);
     939              : 
     940            7 :   TyTy::SubstitutionArgumentMappings subst (
     941            7 :     subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
     942            7 :     expr.get_locus ());
     943            7 :   infered = SubstMapperInternal::Resolve (adt, subst);
     944            7 : }
     945              : 
     946              : void
     947           27 : typecheck_inline_asm_operand (HIR::InlineAsm &expr)
     948              : {
     949           27 :   const auto &operands = expr.get_operands ();
     950           27 :   using RegisterType = AST::InlineAsmOperand::RegisterType;
     951           56 :   for (auto &operand : operands)
     952              :     {
     953           29 :       switch (operand.get_register_type ())
     954              :         {
     955           10 :         case RegisterType::In:
     956           10 :           {
     957           10 :             auto in = operand.get_in ();
     958           10 :             TypeCheckExpr::Resolve (*in.expr);
     959           10 :             break;
     960           10 :           }
     961           17 :         case RegisterType::Out:
     962           17 :           {
     963           17 :             auto out = operand.get_out ();
     964           17 :             TypeCheckExpr::Resolve (*out.expr);
     965           17 :             break;
     966           17 :           }
     967            0 :         case RegisterType::InOut:
     968            0 :           {
     969            0 :             auto in_out = operand.get_in_out ();
     970            0 :             TypeCheckExpr::Resolve (*in_out.expr);
     971            0 :             break;
     972            0 :           }
     973            2 :         case RegisterType::SplitInOut:
     974            2 :           {
     975            2 :             auto split_in_out = operand.get_split_in_out ();
     976            2 :             TypeCheckExpr::Resolve (*split_in_out.in_expr);
     977            2 :             TypeCheckExpr::Resolve (*split_in_out.out_expr);
     978            2 :             break;
     979            2 :           }
     980            0 :         case RegisterType::Const:
     981            0 :           {
     982            0 :             auto anon_const = operand.get_const ().anon_const;
     983            0 :             TypeCheckExpr::Resolve (anon_const.get_inner_expr ());
     984            0 :             break;
     985            0 :           }
     986            0 :         case RegisterType::Sym:
     987            0 :           {
     988            0 :             auto sym = operand.get_sym ();
     989            0 :             TypeCheckExpr::Resolve (*sym.expr);
     990            0 :             break;
     991            0 :           }
     992            0 :         case RegisterType::Label:
     993            0 :           {
     994            0 :             auto label = operand.get_label ();
     995            0 :             TypeCheckExpr::Resolve (*label.expr);
     996            0 :             break;
     997            0 :           }
     998              :         }
     999              :     }
    1000           27 : }
    1001              : void
    1002           27 : TypeCheckExpr::visit (HIR::InlineAsm &expr)
    1003              : {
    1004           27 :   typecheck_inline_asm_operand (expr);
    1005              : 
    1006              :   // NOTE: Hoise out if we have noreturn as an option
    1007              :   // to return a never type
    1008              :   // TODO : new keyword for memory seems sooooo shaky
    1009           27 :   if (expr.options.count (AST::InlineAsm::Option::NORETURN) == 1)
    1010            1 :     infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
    1011              :   else
    1012           26 :     infered = TyTy::TupleType::get_unit_type ();
    1013           27 : }
    1014              : 
    1015              : void
    1016            2 : TypeCheckExpr::visit (HIR::LlvmInlineAsm &expr)
    1017              : {
    1018            4 :   for (auto &i : expr.inputs)
    1019            2 :     TypeCheckExpr::Resolve (*i.expr);
    1020              : 
    1021            2 :   for (auto &o : expr.outputs)
    1022            0 :     TypeCheckExpr::Resolve (*o.expr);
    1023              : 
    1024              :   // Black box hint is unit type
    1025            2 :   infered = TyTy::TupleType::get_unit_type ();
    1026            2 : }
    1027              : 
    1028              : void
    1029           15 : TypeCheckExpr::visit (HIR::OffsetOf &expr)
    1030              : {
    1031           15 :   TypeCheckType::Resolve (expr.get_type ());
    1032              : 
    1033              :   // FIXME: Does offset_of always return a usize?
    1034           15 :   TyTy::BaseType *size_ty;
    1035           15 :   bool ok = context->lookup_builtin ("usize", &size_ty);
    1036           15 :   rust_assert (ok);
    1037              : 
    1038           15 :   infered = size_ty;
    1039           15 : }
    1040              : 
    1041              : void
    1042            0 : TypeCheckExpr::visit (HIR::RangeFullExpr &expr)
    1043              : {
    1044            0 :   auto lang_item_type = LangItem::Kind::RANGE_FULL;
    1045              : 
    1046            0 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
    1047              :   // we need to have it maybe
    1048            0 :   if (!lang_item_defined)
    1049              :     {
    1050            0 :       rust_internal_error_at (expr.get_locus (),
    1051              :                               "unable to find relevant lang item: %s",
    1052            0 :                               LangItem::ToString (lang_item_type).c_str ());
    1053              :       return;
    1054              :     }
    1055            0 :   DefId &respective_lang_item_id = lang_item_defined.value ();
    1056              : 
    1057              :   // look it up and it _must_ be a struct definition
    1058            0 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
    1059              : 
    1060            0 :   TyTy::BaseType *item_type = nullptr;
    1061            0 :   bool ok
    1062            0 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
    1063            0 :   rust_assert (ok);
    1064            0 :   rust_assert (item_type->is_unit ());
    1065              : 
    1066            0 :   infered = item_type;
    1067              : }
    1068              : 
    1069              : void
    1070            7 : TypeCheckExpr::visit (HIR::RangeFromToInclExpr &expr)
    1071              : {
    1072            7 :   auto lang_item_type = LangItem::Kind::RANGE_INCLUSIVE;
    1073              : 
    1074            7 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
    1075              :   // we need to have it maybe
    1076            7 :   if (!lang_item_defined)
    1077              :     {
    1078            0 :       rust_internal_error_at (expr.get_locus (),
    1079              :                               "unable to find relevant lang item: %s",
    1080            0 :                               LangItem::ToString (lang_item_type).c_str ());
    1081              :       return;
    1082              :     }
    1083            7 :   DefId respective_lang_item_id = lang_item_defined.value ();
    1084              : 
    1085              :   // look it up and it _must_ be a struct definition
    1086            7 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
    1087              : 
    1088            7 :   TyTy::BaseType *item_type = nullptr;
    1089            7 :   bool ok
    1090            7 :     = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
    1091            7 :   rust_assert (ok);
    1092            7 :   rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
    1093            7 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
    1094              : 
    1095              :   // this is a single generic item lets assert that
    1096            7 :   rust_assert (adt->get_num_substitutions () == 1);
    1097              : 
    1098              :   // resolve the range expressions and these types must unify then we use that
    1099              :   // type to substitute into the ADT
    1100            7 :   TyTy::BaseType *from_ty = TypeCheckExpr::Resolve (expr.get_from_expr ());
    1101            7 :   TyTy::BaseType *to_ty = TypeCheckExpr::Resolve (expr.get_to_expr ());
    1102           14 :   TyTy::BaseType *unified = unify_site (
    1103            7 :     expr.get_mappings ().get_hirid (),
    1104            7 :     TyTy::TyWithLocation (from_ty, expr.get_from_expr ().get_locus ()),
    1105            7 :     TyTy::TyWithLocation (to_ty, expr.get_to_expr ().get_locus ()),
    1106            7 :     expr.get_locus ());
    1107              : 
    1108              :   // substitute it in
    1109            7 :   std::vector<TyTy::SubstitutionArg> subst_mappings;
    1110            7 :   const TyTy::SubstitutionParamMapping *param_ref = &adt->get_substs ().at (0);
    1111            7 :   subst_mappings.emplace_back (param_ref, unified);
    1112              : 
    1113            7 :   TyTy::SubstitutionArgumentMappings subst (
    1114            7 :     subst_mappings, {}, adt->get_substitution_arguments ().get_regions (),
    1115            7 :     expr.get_locus ());
    1116            7 :   infered = SubstMapperInternal::Resolve (adt, subst);
    1117            7 : }
    1118              : 
    1119              : void
    1120          291 : TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
    1121              : {
    1122          291 :   auto array_expr_ty = TypeCheckExpr::Resolve (expr.get_array_expr ());
    1123          291 :   if (array_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
    1124          289 :     return;
    1125              : 
    1126          290 :   auto index_expr_ty = TypeCheckExpr::Resolve (expr.get_index_expr ());
    1127          290 :   if (index_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
    1128              :     return;
    1129              : 
    1130              :   // first attempt to use direct array index logic
    1131          290 :   auto direct_array_expr_ty = array_expr_ty;
    1132          290 :   if (direct_array_expr_ty->get_kind () == TyTy::TypeKind::REF)
    1133              :     {
    1134              :       // lets try and deref it since rust allows this
    1135           29 :       auto ref = static_cast<TyTy::ReferenceType *> (direct_array_expr_ty);
    1136           29 :       auto base = ref->get_base ();
    1137           29 :       if (base->get_kind () == TyTy::TypeKind::ARRAY)
    1138          290 :         direct_array_expr_ty = base;
    1139              :     }
    1140              : 
    1141          290 :   TyTy::BaseType *size_ty;
    1142          290 :   bool ok = context->lookup_builtin ("usize", &size_ty);
    1143          290 :   rust_assert (ok);
    1144              : 
    1145          290 :   bool maybe_simple_array_access
    1146          290 :     = types_compatable (TyTy::TyWithLocation (index_expr_ty),
    1147          290 :                         TyTy::TyWithLocation (size_ty), expr.get_locus (),
    1148              :                         false);
    1149          290 :   if (maybe_simple_array_access
    1150          290 :       && direct_array_expr_ty->get_kind () == TyTy::TypeKind::ARRAY)
    1151              :     {
    1152          450 :       unify_site (expr.get_index_expr ().get_mappings ().get_hirid (),
    1153          225 :                   TyTy::TyWithLocation (size_ty),
    1154              :                   TyTy::TyWithLocation (index_expr_ty,
    1155          225 :                                         expr.get_index_expr ().get_locus ()),
    1156              :                   expr.get_locus ());
    1157              : 
    1158          225 :       TyTy::ArrayType *array_type
    1159              :         = static_cast<TyTy::ArrayType *> (direct_array_expr_ty);
    1160          225 :       infered = array_type->get_element_type ()->clone ();
    1161          225 :       return;
    1162              :     }
    1163              : 
    1164              :   // is this a case of core::ops::index?
    1165           65 :   auto lang_item_type = LangItem::Kind::INDEX;
    1166           65 :   bool operator_overloaded
    1167           65 :     = resolve_operator_overload (lang_item_type, expr, array_expr_ty,
    1168              :                                  index_expr_ty);
    1169           65 :   if (operator_overloaded)
    1170              :     {
    1171              :       // index and index mut always return a reference to the element
    1172           63 :       TyTy::BaseType *resolved = infered;
    1173           63 :       rust_assert (resolved->get_kind () == TyTy::TypeKind::REF);
    1174           63 :       TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (resolved);
    1175              : 
    1176           63 :       infered = ref->get_base ()->clone ();
    1177           63 :       return;
    1178              :     }
    1179              : 
    1180              :   // error[E0277]: the type `[{integer}]` cannot be indexed by `u32`
    1181            2 :   rich_location r (line_table, expr.get_locus ());
    1182            2 :   r.add_range (expr.get_array_expr ().get_locus ());
    1183            2 :   r.add_range (expr.get_index_expr ().get_locus ());
    1184            2 :   rust_error_at (r, ErrorCode::E0277, "the type %qs cannot be indexed by %qs",
    1185            4 :                  array_expr_ty->get_name ().c_str (),
    1186            2 :                  index_expr_ty->get_name ().c_str ());
    1187            2 : }
    1188              : 
    1189              : void
    1190          433 : TypeCheckExpr::visit (HIR::ArrayExpr &expr)
    1191              : {
    1192          433 :   auto &elements = expr.get_internal_elements ();
    1193              : 
    1194          433 :   TyTy::BaseType *expected_ty = nullptr;
    1195          433 :   bool ok = context->lookup_builtin ("usize", &expected_ty);
    1196          433 :   rust_assert (ok);
    1197              : 
    1198          433 :   HIR::Expr *capacity_expr = nullptr;
    1199          433 :   TyTy::BaseType *element_type = nullptr;
    1200          433 :   TyTy::BaseType *capacity_type = nullptr;
    1201          433 :   switch (elements.get_array_expr_type ())
    1202              :     {
    1203          123 :     case HIR::ArrayElems::ArrayExprType::COPIED:
    1204          123 :       {
    1205          123 :         HIR::ArrayElemsCopied &elems
    1206              :           = static_cast<HIR::ArrayElemsCopied &> (elements);
    1207          123 :         element_type = TypeCheckExpr::Resolve (elems.get_elem_to_copy ());
    1208              : 
    1209          123 :         auto capacity_expr_ty
    1210          123 :           = TypeCheckExpr::Resolve (elems.get_num_copies_expr ());
    1211          123 :         if (capacity_expr_ty->is<TyTy::ErrorType> ())
    1212            7 :           return;
    1213              : 
    1214          120 :         context->insert_type (elems.get_num_copies_expr ().get_mappings (),
    1215              :                               expected_ty);
    1216              : 
    1217          240 :         auto result = unify_site (
    1218          120 :           expr.get_mappings ().get_hirid (), TyTy::TyWithLocation (expected_ty),
    1219              :           TyTy::TyWithLocation (capacity_expr_ty,
    1220          120 :                                 elems.get_num_copies_expr ().get_locus ()),
    1221              :           expr.get_locus ());
    1222          120 :         if (result->is<TyTy::ErrorType> ())
    1223              :           return;
    1224              : 
    1225          116 :         capacity_expr = &elems.get_num_copies_expr ();
    1226          116 :         capacity_type = expected_ty;
    1227              :       }
    1228          116 :       break;
    1229              : 
    1230          310 :     case HIR::ArrayElems::ArrayExprType::VALUES:
    1231          310 :       {
    1232          310 :         HIR::ArrayElemsValues &elems
    1233              :           = static_cast<HIR::ArrayElemsValues &> (elements);
    1234              : 
    1235          310 :         std::vector<TyTy::BaseType *> types;
    1236         1827 :         for (auto &elem : elems.get_values ())
    1237              :           {
    1238         1517 :             types.push_back (TypeCheckExpr::Resolve (*elem));
    1239              :           }
    1240              : 
    1241              :         // this is a LUB
    1242          310 :         element_type
    1243          310 :           = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
    1244         1827 :         for (auto &type : types)
    1245              :           {
    1246         1517 :             element_type
    1247         1517 :               = unify_site (expr.get_mappings ().get_hirid (),
    1248         1517 :                             TyTy::TyWithLocation (element_type),
    1249         1517 :                             TyTy::TyWithLocation (type, type->get_locus ()),
    1250              :                             expr.get_locus ());
    1251              :           }
    1252              : 
    1253          310 :         auto crate_num = mappings.get_current_crate ();
    1254          310 :         Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID,
    1255          310 :                                        mappings.get_next_hir_id (crate_num),
    1256          310 :                                        UNKNOWN_LOCAL_DEFID);
    1257          310 :         std::string capacity_str = std::to_string (elems.get_num_elements ());
    1258          310 :         capacity_expr = new HIR::LiteralExpr (mapping, capacity_str,
    1259              :                                               HIR::Literal::LitType::INT,
    1260              :                                               PrimitiveCoreType::CORETYPE_USIZE,
    1261          930 :                                               UNDEF_LOCATION, {});
    1262              : 
    1263              :         // mark the type for this implicit node
    1264          310 :         context->insert_type (mapping, expected_ty);
    1265          310 :         capacity_type = expected_ty;
    1266          310 :       }
    1267          310 :       break;
    1268              :     }
    1269              : 
    1270          426 :   rust_assert (capacity_expr);
    1271          426 :   rust_assert (capacity_type);
    1272          426 :   auto ctx = Compile::Context::get ();
    1273          426 :   tree capacity_value
    1274          426 :     = Compile::HIRCompileBase::query_compile_const_expr (ctx, capacity_type,
    1275              :                                                          *capacity_expr);
    1276              : 
    1277              :   // Create ConstValueType with ref == ty_ref (both pointing to capacity_expr)
    1278              :   // ty_ref gets updated during substitution via set_ty_ref()
    1279          426 :   HirId capacity_expr_id = capacity_expr->get_mappings ().get_hirid ();
    1280          426 :   auto const_type
    1281              :     = new TyTy::ConstValueType (capacity_value, expected_ty, capacity_expr_id,
    1282          426 :                                 capacity_expr_id);
    1283              : 
    1284              :   // Insert the ConstValueType at its ref
    1285          426 :   context->insert_type (capacity_expr->get_mappings (),
    1286          426 :                         const_type->as_base_type ());
    1287              : 
    1288          426 :   infered
    1289          852 :     = new TyTy::ArrayType (expr.get_mappings ().get_hirid (), expr.get_locus (),
    1290              :                            TyTy::TyVar (
    1291          426 :                              const_type->as_base_type ()->get_ty_ref ()),
    1292          852 :                            TyTy::TyVar (element_type->get_ref ()));
    1293              : }
    1294              : 
    1295              : // empty struct
    1296              : void
    1297           81 : TypeCheckExpr::visit (HIR::StructExprStruct &struct_expr)
    1298              : {
    1299           81 :   HIR::PathInExpression &path = struct_expr.get_struct_name ();
    1300              : 
    1301           81 :   TyTy::BaseType *struct_path_ty = TypeCheckExpr::Resolve (path);
    1302           81 :   if (struct_path_ty->get_kind () != TyTy::TypeKind::ADT)
    1303              :     {
    1304            0 :       rust_error_at (path.get_locus (), "expected an ADT type for constructor");
    1305            1 :       return;
    1306              :     }
    1307              : 
    1308           81 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_path_ty);
    1309           81 :   TyTy::VariantDef *variant;
    1310              : 
    1311              :   // unwrap and type check the variant if it's an enum
    1312           81 :   if (adt->is_enum ())
    1313              :     {
    1314            3 :       HirId variant_id;
    1315            3 :       bool ok = context->lookup_variant_definition (
    1316            3 :         struct_expr.get_struct_name ().get_mappings ().get_hirid (),
    1317              :         &variant_id);
    1318            3 :       if (!ok)
    1319              :         {
    1320            0 :           rich_location r (line_table, struct_expr.get_locus ());
    1321            0 :           r.add_range (struct_expr.get_struct_name ().get_locus ());
    1322            0 :           rust_error_at (
    1323            0 :             struct_expr.get_struct_name ().get_locus (), ErrorCode::E0574,
    1324              :             "expected a struct, variant or union type, found enum %qs",
    1325            0 :             adt->get_name ().c_str ());
    1326            0 :           return;
    1327            0 :         }
    1328              : 
    1329            3 :       ok = adt->lookup_variant_by_id (variant_id, &variant);
    1330            3 :       rust_assert (ok);
    1331              :     }
    1332              :   else
    1333              :     {
    1334           78 :       rust_assert (adt->number_of_variants () == 1);
    1335           78 :       variant = adt->get_variants ().at (0);
    1336              :     }
    1337              : 
    1338           81 :   if (!variant->get_fields ().empty ())
    1339              :     {
    1340            1 :       std::vector<std::string> field_names;
    1341            4 :       for (auto &field : variant->get_fields ())
    1342            3 :         field_names.push_back (field->get_name ());
    1343            1 :       Error missing_fields_error
    1344              :         = TypeCheckStructExpr::make_missing_field_error (
    1345            1 :           struct_expr.get_locus (), field_names, struct_path_ty->get_name ());
    1346              :       // We might want to return or handle these in the future emit for now.
    1347            1 :       missing_fields_error.emit ();
    1348            1 :       return;
    1349            1 :     }
    1350              : 
    1351           80 :   infered = struct_path_ty;
    1352              : }
    1353              : 
    1354              : void
    1355         1371 : TypeCheckExpr::visit (HIR::StructExprStructFields &struct_expr)
    1356              : {
    1357         1371 :   infered = TypeCheckStructExpr::Resolve (struct_expr);
    1358         1371 : }
    1359              : 
    1360              : void
    1361          314 : TypeCheckExpr::visit (HIR::GroupedExpr &expr)
    1362              : {
    1363          314 :   infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ());
    1364          314 : }
    1365              : 
    1366              : void
    1367         5055 : TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
    1368              : {
    1369         5055 :   auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ());
    1370              : 
    1371              :   // Box<T> autoderef
    1372         5055 :   if (auto try_struct_base = TyTy::try_get_box_inner_type (struct_base))
    1373              :     {
    1374            1 :       struct_base = *try_struct_base;
    1375              :     }
    1376              : 
    1377              :   // FIXME does this require autoderef here?
    1378         5055 :   if (struct_base->get_kind () == TyTy::TypeKind::REF)
    1379              :     {
    1380         3465 :       TyTy::ReferenceType *r = static_cast<TyTy::ReferenceType *> (struct_base);
    1381         3465 :       struct_base = r->get_base ();
    1382              :     }
    1383              : 
    1384         5055 :   bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT;
    1385         5055 :   if (!is_valid_type)
    1386              :     {
    1387            0 :       rust_error_at (expr.get_locus (), "expected algebraic data type got %qs",
    1388            0 :                      struct_base->get_name ().c_str ());
    1389            4 :       return;
    1390              :     }
    1391              : 
    1392         5055 :   TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (struct_base);
    1393         5055 :   rust_assert (adt->number_of_variants () > 0);
    1394         5055 :   TyTy::VariantDef *vaiant = adt->get_variants ().at (0);
    1395              : 
    1396         5055 :   TyTy::StructFieldType *lookup = nullptr;
    1397         5055 :   bool found = vaiant->lookup_field (expr.get_field_name ().as_string (),
    1398              :                                      &lookup, nullptr);
    1399         5055 :   if (!found || adt->is_enum ())
    1400              :     {
    1401            4 :       rich_location r (line_table, expr.get_locus ());
    1402            4 :       r.add_range (expr.get_field_name ().get_locus ());
    1403            4 :       rust_error_at (r, ErrorCode::E0609, "no field %qs on type %qs",
    1404            8 :                      expr.get_field_name ().as_string ().c_str (),
    1405            4 :                      adt->get_name ().c_str ());
    1406            4 :       return;
    1407            4 :     }
    1408              : 
    1409         5051 :   infered = lookup->get_field_type ();
    1410              : }
    1411              : 
    1412              : bool
    1413           43 : is_default_fn (const MethodCandidate &candidate)
    1414              : {
    1415           43 :   if (candidate.candidate.is_impl_candidate ())
    1416              :     {
    1417           43 :       auto *item = candidate.candidate.item.impl.impl_item;
    1418              : 
    1419           43 :       if (item->get_impl_item_type () == HIR::ImplItem::FUNCTION)
    1420              :         {
    1421           43 :           auto &fn = static_cast<HIR::Function &> (*item);
    1422              : 
    1423           43 :           return fn.is_default ();
    1424              :         }
    1425              :     }
    1426              : 
    1427              :   return false;
    1428              : }
    1429              : 
    1430              : void
    1431            2 : emit_ambiguous_resolution_error (HIR::MethodCallExpr &expr,
    1432              :                                  std::set<MethodCandidate> &candidates)
    1433              : {
    1434            2 :   rich_location r (line_table, expr.get_method_name ().get_locus ());
    1435            2 :   std::string rich_msg = "multiple "
    1436            6 :                          + expr.get_method_name ().get_segment ().to_string ()
    1437            2 :                          + " found";
    1438              : 
    1439              :   // We have to filter out default candidates
    1440            6 :   for (auto &c : candidates)
    1441            4 :     if (!is_default_fn (c))
    1442            4 :       r.add_range (c.candidate.locus);
    1443              : 
    1444            2 :   r.add_fixit_replace (rich_msg.c_str ());
    1445              : 
    1446            2 :   rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
    1447            6 :                  expr.get_method_name ().get_segment ().to_string ().c_str ());
    1448            2 : }
    1449              : 
    1450              : // We are allowed to have multiple candidates if they are all specializable
    1451              : // functions or if all of them except one are specializable functions.
    1452              : // In the later case, we just return a valid candidate without erroring out
    1453              : // about ambiguity. If there are two or more specialized functions, then we
    1454              : // error out.
    1455              : //
    1456              : // FIXME: The first case is not handled at the moment, so we error out
    1457              : tl::optional<const MethodCandidate &>
    1458           16 : handle_multiple_candidates (HIR::MethodCallExpr &expr,
    1459              :                             std::set<MethodCandidate> &candidates)
    1460              : {
    1461           16 :   auto all_default = true;
    1462           16 :   tl::optional<const MethodCandidate &> found = tl::nullopt;
    1463              : 
    1464           53 :   for (auto &c : candidates)
    1465              :     {
    1466           39 :       if (!is_default_fn (c))
    1467              :         {
    1468           18 :           all_default = false;
    1469              : 
    1470              :           // We haven't found a final candidate yet, so we can select
    1471              :           // this one. However, if we already have a candidate, then
    1472              :           // that means there are multiple non-default candidates - we
    1473              :           // must error out
    1474           18 :           if (!found)
    1475              :             {
    1476              :               found = c;
    1477              :             }
    1478              :           else
    1479              :             {
    1480            2 :               emit_ambiguous_resolution_error (expr, candidates);
    1481            2 :               return tl::nullopt;
    1482              :             }
    1483              :         }
    1484              :     }
    1485              : 
    1486              :   // None of the candidates were a non-default (specialized) function, so we
    1487              :   // error out
    1488           14 :   if (all_default)
    1489              :     {
    1490            0 :       rust_sorry_at (expr.get_locus (),
    1491              :                      "cannot resolve method calls to non-specialized methods "
    1492              :                      "(all function candidates are %qs)",
    1493              :                      "default");
    1494            0 :       return tl::nullopt;
    1495              :     }
    1496              : 
    1497           14 :   return found;
    1498              : }
    1499              : 
    1500              : void
    1501         3046 : TypeCheckExpr::visit (HIR::MethodCallExpr &expr)
    1502              : {
    1503         3046 :   auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ());
    1504         3046 :   if (receiver_tyty->get_kind () == TyTy::TypeKind::ERROR)
    1505              :     {
    1506            1 :       rust_error_at (expr.get_receiver ().get_locus (),
    1507              :                      "failed to resolve receiver in MethodCallExpr");
    1508           12 :       return;
    1509              :     }
    1510              : 
    1511         3045 :   rust_debug_loc (expr.get_locus (), "attempting to resolve method for %s",
    1512         3045 :                   receiver_tyty->debug_str ().c_str ());
    1513         3045 :   auto candidates
    1514              :     = MethodResolver::Probe (receiver_tyty,
    1515         3045 :                              expr.get_method_name ().get_segment ());
    1516         3045 :   if (candidates.empty ())
    1517              :     {
    1518            7 :       rich_location richloc (line_table, expr.get_method_name ().get_locus ());
    1519            7 :       richloc.add_fixit_replace ("method not found");
    1520            7 :       rust_error_at (
    1521              :         richloc, ErrorCode::E0599,
    1522              :         "no method named %qs found in the current scope",
    1523           14 :         expr.get_method_name ().get_segment ().to_string ().c_str ());
    1524            7 :       return;
    1525            7 :     }
    1526              : 
    1527         3038 :   tl::optional<const MethodCandidate &> candidate = *candidates.begin ();
    1528              : 
    1529         3038 :   if (candidates.size () > 1)
    1530           16 :     candidate = handle_multiple_candidates (expr, candidates);
    1531              : 
    1532         3038 :   if (!candidate)
    1533              :     return;
    1534              : 
    1535         3036 :   auto found_candidate = *candidate;
    1536              : 
    1537         6072 :   rust_debug_loc (expr.get_method_name ().get_locus (),
    1538              :                   "resolved method to: {%u} {%s} with [%lu] adjustments",
    1539         3036 :                   found_candidate.candidate.ty->get_ref (),
    1540         3036 :                   found_candidate.candidate.ty->debug_str ().c_str (),
    1541         3036 :                   (unsigned long) found_candidate.adjustments.size ());
    1542              : 
    1543              :   // Get the adjusted self
    1544         3036 :   Adjuster adj (receiver_tyty);
    1545         3036 :   TyTy::BaseType *adjusted_self = adj.adjust_type (found_candidate.adjustments);
    1546         3036 :   rust_debug ("receiver: %s adjusted self %s",
    1547              :               receiver_tyty->debug_str ().c_str (),
    1548              :               adjusted_self->debug_str ().c_str ());
    1549              : 
    1550              :   // store the adjustments for code-generation to know what to do which must be
    1551              :   // stored onto the receiver to so as we don't trigger duplicate deref mappings
    1552              :   // ICE when an argument is a method call
    1553         3036 :   HirId autoderef_mappings_id
    1554         3036 :     = expr.get_receiver ().get_mappings ().get_hirid ();
    1555         3036 :   context->insert_autoderef_mappings (autoderef_mappings_id,
    1556              :                                       std::move (found_candidate.adjustments));
    1557              : 
    1558         3036 :   PathProbeCandidate &resolved_candidate = found_candidate.candidate;
    1559         3036 :   TyTy::BaseType *lookup_tyty = found_candidate.candidate.ty;
    1560         3036 :   NodeId resolved_node_id
    1561         3036 :     = resolved_candidate.is_impl_candidate ()
    1562         3036 :         ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
    1563         2069 :             .get_nodeid ()
    1564          967 :         : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
    1565              : 
    1566         3036 :   if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
    1567              :     {
    1568            0 :       rich_location r (line_table, expr.get_method_name ().get_locus ());
    1569            0 :       r.add_range (resolved_candidate.locus);
    1570            0 :       rust_error_at (r, "associated impl item is not a method");
    1571            0 :       return;
    1572            0 :     }
    1573              : 
    1574         3036 :   TyTy::BaseType *lookup = lookup_tyty;
    1575         3036 :   TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
    1576         6072 :   if (!fn->is_method ())
    1577              :     {
    1578            0 :       rich_location r (line_table, expr.get_method_name ().get_locus ());
    1579            0 :       r.add_range (resolved_candidate.locus);
    1580            0 :       rust_error_at (r, "associated function is not a method");
    1581            0 :       return;
    1582            0 :     }
    1583              : 
    1584         3036 :   rust_debug_loc (expr.get_locus (), "resolved method call to: {%u} {%s}",
    1585         3036 :                   found_candidate.candidate.ty->get_ref (),
    1586         3036 :                   found_candidate.candidate.ty->debug_str ().c_str ());
    1587              : 
    1588         3036 :   if (resolved_candidate.is_impl_candidate ())
    1589              :     {
    1590         2069 :       auto infer_arguments = TyTy::SubstitutionArgumentMappings::empty ();
    1591         2069 :       infer_arguments.get_mut_regions ()
    1592         2069 :         = fn->get_used_arguments ().get_regions ();
    1593         2069 :       HIR::ImplBlock &impl = *resolved_candidate.item.impl.parent;
    1594         2069 :       TyTy::BaseType *impl_self_infer
    1595         2069 :         = TypeCheckItem::ResolveImplBlockSelfWithInference (impl,
    1596              :                                                             expr.get_locus (),
    1597              :                                                             &infer_arguments);
    1598         2069 :       if (impl_self_infer->get_kind () == TyTy::TypeKind::ERROR)
    1599              :         {
    1600            0 :           rich_location r (line_table, expr.get_locus ());
    1601            0 :           r.add_range (impl.get_type ().get_locus ());
    1602            0 :           rust_error_at (
    1603              :             r, "failed to resolve impl type for method call resolution");
    1604            0 :           return;
    1605            0 :         }
    1606              : 
    1607         2069 :       if (!infer_arguments.is_empty ())
    1608          554 :         lookup = SubstMapperInternal::Resolve (lookup, infer_arguments);
    1609         2069 :     }
    1610              : 
    1611              :   // apply any remaining generic arguments
    1612         3036 :   if (expr.get_method_name ().has_generic_args ())
    1613              :     {
    1614           29 :       HIR::GenericArgs &args = expr.get_method_name ().get_generic_args ();
    1615           29 :       rust_debug_loc (args.get_locus (),
    1616              :                       "applying generic arguments to method_call: {%s}",
    1617           29 :                       lookup->debug_str ().c_str ());
    1618              : 
    1619           29 :       lookup
    1620           29 :         = SubstMapper::Resolve (lookup, expr.get_method_name ().get_locus (),
    1621              :                                 &args);
    1622           29 :       if (lookup->get_kind () == TyTy::TypeKind::ERROR)
    1623              :         return;
    1624              :     }
    1625         3007 :   else if (lookup->needs_generic_substitutions ())
    1626              :     {
    1627          873 :       rust_debug ("method needs inference: {%s}",
    1628              :                   lookup->debug_str ().c_str ());
    1629          873 :       lookup = SubstMapper::InferSubst (lookup,
    1630          873 :                                         expr.get_method_name ().get_locus ());
    1631              :     }
    1632              : 
    1633         3035 :   rust_debug ("type-checking method_call: {%s}", lookup->debug_str ().c_str ());
    1634              : 
    1635         3035 :   TyTy::BaseType *function_ret_tyty
    1636         3035 :     = TyTy::TypeCheckMethodCallExpr::go (static_cast<TyTy::FnType *> (lookup),
    1637              :                                          expr, adjusted_self, context);
    1638         3035 :   if (function_ret_tyty == nullptr
    1639         3035 :       || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
    1640              :     {
    1641            0 :       rust_error_at (expr.get_locus (),
    1642              :                      "failed to lookup type to MethodCallExpr");
    1643            0 :       return;
    1644              :     }
    1645              : 
    1646              :   // store the expected fntype
    1647         3035 :   context->insert_type (expr.get_method_name ().get_mappings (), lookup);
    1648              : 
    1649         3035 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    1650              : 
    1651         3035 :   nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
    1652         3035 :                     Resolver2_0::Definition (resolved_node_id),
    1653              :                     Resolver2_0::Namespace::Values);
    1654              : 
    1655              :   // return the result of the function back
    1656         3035 :   infered = function_ret_tyty;
    1657         3046 : }
    1658              : 
    1659              : void
    1660          127 : TypeCheckExpr::visit (HIR::LoopExpr &expr)
    1661              : {
    1662          127 :   context->push_new_loop_context (expr.get_mappings ().get_hirid (),
    1663              :                                   expr.get_locus ());
    1664          127 :   TyTy::BaseType *block_expr = TypeCheckExpr::Resolve (expr.get_loop_block ());
    1665          127 :   if (!block_expr->is_unit ())
    1666              :     {
    1667            0 :       rust_error_at (expr.get_loop_block ().get_locus (),
    1668              :                      "expected %<()%> got %s",
    1669            0 :                      block_expr->as_string ().c_str ());
    1670            0 :       return;
    1671              :     }
    1672              : 
    1673          127 :   TyTy::BaseType *loop_context_type = context->pop_loop_context ();
    1674              : 
    1675          127 :   bool loop_context_type_infered
    1676          127 :     = (loop_context_type->get_kind () != TyTy::TypeKind::INFER)
    1677          127 :       || ((loop_context_type->get_kind () == TyTy::TypeKind::INFER)
    1678          118 :           && (((TyTy::InferType *) loop_context_type)->get_infer_kind ()
    1679          238 :               != TyTy::InferType::GENERAL));
    1680              : 
    1681          127 :   infered = loop_context_type_infered ? loop_context_type
    1682          111 :                                       : TyTy::TupleType::get_unit_type ();
    1683              : }
    1684              : 
    1685              : void
    1686           78 : TypeCheckExpr::visit (HIR::WhileLoopExpr &expr)
    1687              : {
    1688           78 :   context->push_new_while_loop_context (expr.get_mappings ().get_hirid ());
    1689           78 :   TyTy::BaseType *predicate_type
    1690           78 :     = TypeCheckExpr::Resolve (expr.get_predicate_expr ());
    1691           78 :   if (predicate_type->get_kind () != TyTy::TypeKind::BOOL
    1692           78 :       && predicate_type->get_kind () != TyTy::TypeKind::NEVER)
    1693              :     {
    1694            0 :       rust_error_at (expr.get_predicate_expr ().get_locus (),
    1695              :                      "expected boolean expression in %<while%> condition");
    1696            0 :       context->pop_loop_context ();
    1697            0 :       return;
    1698              :     }
    1699           78 :   TyTy::BaseType *block_expr = TypeCheckExpr::Resolve (expr.get_loop_block ());
    1700           78 :   if (!block_expr->is_unit ())
    1701              :     {
    1702            0 :       rust_error_at (expr.get_loop_block ().get_locus (),
    1703              :                      "expected %<()%> got %s",
    1704            0 :                      block_expr->as_string ().c_str ());
    1705            0 :       context->pop_loop_context ();
    1706            0 :       return;
    1707              :     }
    1708           78 :   context->pop_loop_context ();
    1709           78 :   infered = TyTy::TupleType::get_unit_type ();
    1710              : }
    1711              : 
    1712              : void
    1713           91 : TypeCheckExpr::visit (HIR::BreakExpr &expr)
    1714              : {
    1715           91 :   if (!context->have_loop_context ())
    1716              :     {
    1717            2 :       rust_error_at (expr.get_locus (), ErrorCode::E0268,
    1718              :                      "%<break%> outside of a loop or labeled block");
    1719            2 :       return;
    1720              :     }
    1721              : 
    1722           89 :   if (expr.has_break_expr ())
    1723              :     {
    1724           23 :       TyTy::BaseType *break_expr_tyty
    1725           23 :         = TypeCheckExpr::Resolve (expr.get_expr ());
    1726              : 
    1727           23 :       TyTy::BaseType *loop_context = context->peek_loop_context ();
    1728           23 :       if (loop_context->get_kind () == TyTy::TypeKind::ERROR)
    1729              :         {
    1730            4 :           rust_error_at (
    1731              :             expr.get_locus (), ErrorCode::E0571,
    1732              :             "can only %<break%> with a value inside a %<loop%> block");
    1733            4 :           return;
    1734              :         }
    1735              : 
    1736           19 :       TyTy::BaseType *unified_ty
    1737           38 :         = unify_site (expr.get_mappings ().get_hirid (),
    1738           19 :                       TyTy::TyWithLocation (loop_context),
    1739              :                       TyTy::TyWithLocation (break_expr_tyty,
    1740           19 :                                             expr.get_expr ().get_locus ()),
    1741              :                       expr.get_locus ());
    1742           19 :       context->swap_head_loop_context (unified_ty);
    1743              :     }
    1744              : 
    1745           85 :   infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
    1746              : }
    1747              : 
    1748              : void
    1749           16 : TypeCheckExpr::visit (HIR::ContinueExpr &expr)
    1750              : {
    1751           16 :   if (!context->have_loop_context ())
    1752              :     {
    1753            3 :       rust_error_at (expr.get_locus (), ErrorCode::E0268,
    1754              :                      "%<continue%> outside of a loop");
    1755            3 :       return;
    1756              :     }
    1757           13 :   infered = new TyTy::NeverType (expr.get_mappings ().get_hirid ());
    1758              : }
    1759              : 
    1760              : void
    1761         2027 : TypeCheckExpr::visit (HIR::BorrowExpr &expr)
    1762              : {
    1763         2027 :   TyTy::BaseType *resolved_base = TypeCheckExpr::Resolve (expr.get_expr ());
    1764         2027 :   if (resolved_base->is<TyTy::ErrorType> ())
    1765              :     return;
    1766              : 
    1767              :   // In Rust this is valid because of DST's
    1768              :   //
    1769              :   // fn test() {
    1770              :   //     let a:&str = "TEST 1";
    1771              :   //     let b:&str = &"TEST 2";
    1772              :   // }
    1773         2026 :   if (resolved_base->get_kind () == TyTy::TypeKind::REF)
    1774              :     {
    1775           43 :       const TyTy::ReferenceType *ref
    1776              :         = static_cast<const TyTy::ReferenceType *> (resolved_base);
    1777              : 
    1778              :       // this might end up being a more generic is_dyn object check but lets
    1779              :       // double check dyn traits type-layout first
    1780           43 :       if (ref->is_dyn_str_type ())
    1781              :         {
    1782            9 :           infered = resolved_base;
    1783            9 :           return;
    1784              :         }
    1785              :     }
    1786              : 
    1787         2017 :   if (expr.is_raw_borrow ())
    1788              :     {
    1789            4 :       infered = new TyTy::PointerType (expr.get_mappings ().get_hirid (),
    1790            4 :                                        TyTy::TyVar (resolved_base->get_ref ()),
    1791            8 :                                        expr.get_mut ());
    1792              : 
    1793            4 :       return;
    1794              :     }
    1795              : 
    1796         2013 :   infered = new TyTy::ReferenceType (expr.get_mappings ().get_hirid (),
    1797         2013 :                                      TyTy::TyVar (resolved_base->get_ref ()),
    1798         4026 :                                      expr.get_mut ());
    1799              : }
    1800              : 
    1801              : void
    1802         3918 : TypeCheckExpr::visit (HIR::DereferenceExpr &expr)
    1803              : {
    1804         3918 :   TyTy::BaseType *resolved_base = TypeCheckExpr::Resolve (expr.get_expr ());
    1805              : 
    1806         3918 :   rust_debug_loc (expr.get_locus (), "attempting deref operator overload");
    1807         3918 :   auto lang_item_type = LangItem::Kind::DEREF;
    1808         3918 :   bool operator_overloaded
    1809         3918 :     = resolve_operator_overload (lang_item_type, expr, resolved_base, nullptr);
    1810         3918 :   if (operator_overloaded)
    1811              :     {
    1812              :       // operator overloaded deref always refurns a reference type lets assert
    1813              :       // this
    1814           49 :       rust_assert (infered->get_kind () == TyTy::TypeKind::REF);
    1815           49 :       resolved_base = infered;
    1816              :     }
    1817              : 
    1818         3918 :   bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF
    1819         3918 :                        || resolved_base->get_kind () == TyTy::TypeKind::POINTER;
    1820              : 
    1821         3918 :   auto try_owned_box = TyTy::try_get_box_inner_type (resolved_base);
    1822              : 
    1823         3918 :   if (!is_valid_type && !try_owned_box)
    1824              :     {
    1825            0 :       rust_error_at (expr.get_locus (), "expected reference type got %s",
    1826            0 :                      resolved_base->as_string ().c_str ());
    1827            0 :       return;
    1828              :     }
    1829              : 
    1830         3918 :   if (try_owned_box)
    1831              :     {
    1832            1 :       infered = (*try_owned_box)->clone ();
    1833              :     }
    1834         3917 :   else if (resolved_base->get_kind () == TyTy::TypeKind::REF)
    1835              :     {
    1836         3720 :       TyTy::ReferenceType *ref_base
    1837              :         = static_cast<TyTy::ReferenceType *> (resolved_base);
    1838         3720 :       infered = ref_base->get_base ()->clone ();
    1839              :     }
    1840              :   else
    1841              :     {
    1842          197 :       TyTy::PointerType *ref_base
    1843              :         = static_cast<TyTy::PointerType *> (resolved_base);
    1844          197 :       infered = ref_base->get_base ()->clone ();
    1845              :     }
    1846              : }
    1847              : 
    1848              : void
    1849         5221 : TypeCheckExpr::visit (HIR::TypeCastExpr &expr)
    1850              : {
    1851         5221 :   TyTy::BaseType *expr_to_convert
    1852         5221 :     = TypeCheckExpr::Resolve (expr.get_casted_expr ());
    1853         5221 :   TyTy::BaseType *tyty_to_convert_to
    1854         5221 :     = TypeCheckType::Resolve (expr.get_type_to_convert_to ());
    1855              : 
    1856         5221 :   TyTy::TyWithLocation from (expr_to_convert,
    1857         5221 :                              expr.get_casted_expr ().get_locus ());
    1858         5221 :   TyTy::TyWithLocation to (tyty_to_convert_to,
    1859         5221 :                            expr.get_type_to_convert_to ().get_locus ());
    1860         5221 :   infered = cast_site (expr.get_mappings ().get_hirid (), from, to,
    1861              :                        expr.get_locus ());
    1862         5221 : }
    1863              : 
    1864              : void
    1865         1105 : TypeCheckExpr::visit (HIR::MatchExpr &expr)
    1866              : {
    1867              :   // this needs to perform a least upper bound coercion on the blocks and then
    1868              :   // unify the scruintee and arms
    1869         1105 :   TyTy::BaseType *scrutinee_tyty
    1870         1105 :     = TypeCheckExpr::Resolve (expr.get_scrutinee_expr ());
    1871              : 
    1872              :   // https://github.com/Rust-GCC/gccrs/issues/3231#issuecomment-2462660048
    1873              :   // https://github.com/rust-lang/rust/blob/3d1dba830a564d1118361345d7ada47a05241f45/compiler/rustc_hir_typeck/src/_match.rs#L32-L36
    1874         1105 :   if (!expr.has_match_arms ())
    1875              :     {
    1876              :       // this is a special case where rustc returns !
    1877            5 :       TyTy::BaseType *lookup = nullptr;
    1878            5 :       bool ok = context->lookup_builtin ("!", &lookup);
    1879            5 :       rust_assert (ok);
    1880            5 :       infered = lookup->clone ();
    1881            5 :       return;
    1882              :     }
    1883              : 
    1884         1100 :   bool saw_error = false;
    1885         1100 :   std::vector<TyTy::BaseType *> kase_block_tys;
    1886         3655 :   for (auto &kase : expr.get_match_cases ())
    1887              :     {
    1888              :       // lets check the arms
    1889         2555 :       HIR::MatchArm &kase_arm = kase.get_arm ();
    1890         2555 :       auto &pattern = kase_arm.get_pattern ();
    1891         2555 :       TyTy::BaseType *kase_arm_ty
    1892         2555 :         = TypeCheckPattern::Resolve (*pattern, scrutinee_tyty);
    1893         2555 :       if (kase_arm_ty->get_kind () == TyTy ::TypeKind::ERROR)
    1894              :         {
    1895           12 :           saw_error = true;
    1896           12 :           continue;
    1897              :         }
    1898              : 
    1899         5086 :       TyTy::BaseType *checked_kase = unify_site (
    1900         2543 :         expr.get_mappings ().get_hirid (),
    1901              :         TyTy::TyWithLocation (scrutinee_tyty,
    1902         2543 :                               expr.get_scrutinee_expr ().get_locus ()),
    1903         2543 :         TyTy::TyWithLocation (kase_arm_ty, pattern->get_locus ()),
    1904              :         expr.get_locus ());
    1905         2543 :       if (checked_kase->get_kind () == TyTy::TypeKind::ERROR)
    1906              :         {
    1907            0 :           saw_error = true;
    1908            0 :           continue;
    1909              :         }
    1910              : 
    1911              :       // check the kase type
    1912         2543 :       TyTy::BaseType *kase_block_ty = TypeCheckExpr::Resolve (kase.get_expr ());
    1913         2543 :       kase_block_tys.push_back (kase_block_ty);
    1914              :     }
    1915         1100 :   if (saw_error)
    1916              :     return;
    1917              : 
    1918         1094 :   if (kase_block_tys.size () == 0)
    1919              :     {
    1920            0 :       infered = TyTy::TupleType::get_unit_type ();
    1921            0 :       return;
    1922              :     }
    1923              : 
    1924              :   // this is a LUB
    1925         1094 :   infered = kase_block_tys.at (0);
    1926         2536 :   for (size_t i = 1; i < kase_block_tys.size (); i++)
    1927              :     {
    1928         1442 :       TyTy::BaseType *kase_ty = kase_block_tys.at (i);
    1929         1442 :       infered
    1930         1442 :         = coercion_site (expr.get_mappings ().get_hirid (),
    1931         1442 :                          TyTy::TyWithLocation (infered),
    1932         1442 :                          TyTy::TyWithLocation (kase_ty), expr.get_locus ());
    1933              :     }
    1934         1100 : }
    1935              : 
    1936              : void
    1937           65 : TypeCheckExpr::visit (HIR::ClosureExpr &expr)
    1938              : {
    1939           65 :   std::vector<TyTy::SubstitutionParamMapping> subst_refs;
    1940           65 :   HirId ref = expr.get_mappings ().get_hirid ();
    1941           65 :   DefId id = expr.get_mappings ().get_defid ();
    1942           65 :   RustIdent ident{CanonicalPath::create_empty (), expr.get_locus ()};
    1943              : 
    1944           65 :   if (context->have_function_context ())
    1945              :     {
    1946           64 :       TypeCheckContextItem current_context = context->peek_context ();
    1947           64 :       TyTy::FnType *current_context_fndecl
    1948           64 :         = current_context.get_context_type ();
    1949              : 
    1950           64 :       ident = RustIdent{current_context_fndecl->get_ident ().path,
    1951           64 :                         expr.get_locus ()};
    1952              : 
    1953           64 :       subst_refs = current_context_fndecl->clone_substs ();
    1954              :     }
    1955              : 
    1956           65 :   std::vector<TyTy::TyVar> parameter_types;
    1957          125 :   for (auto &p : expr.get_params ())
    1958              :     {
    1959           60 :       TyTy::BaseType *param_tyty = nullptr;
    1960           60 :       if (p.has_type_given ())
    1961              :         {
    1962           58 :           param_tyty = TypeCheckType::Resolve (p.get_type ());
    1963              :         }
    1964              :       else
    1965              :         {
    1966            2 :           param_tyty = ClosureParamInfer::Resolve (p.get_pattern ());
    1967              :         }
    1968              : 
    1969           60 :       TyTy::TyVar param_ty (param_tyty->get_ref ());
    1970           60 :       parameter_types.push_back (param_ty);
    1971              : 
    1972           60 :       TypeCheckPattern::Resolve (p.get_pattern (), param_ty.get_tyty ());
    1973              :     }
    1974              : 
    1975              :   // we generate an implicit hirid for the closure args
    1976           65 :   HirId implicit_args_id = mappings.get_next_hir_id ();
    1977           65 :   TyTy::TupleType *closure_args
    1978              :     = new TyTy::TupleType (implicit_args_id, expr.get_locus (),
    1979           65 :                            parameter_types);
    1980           65 :   context->insert_implicit_type (closure_args->get_ref (), closure_args);
    1981              : 
    1982           65 :   location_t result_type_locus = expr.has_return_type ()
    1983           65 :                                    ? expr.get_return_type ().get_locus ()
    1984           65 :                                    : expr.get_locus ();
    1985           65 :   TyTy::TyVar result_type
    1986           65 :     = expr.has_return_type ()
    1987           65 :         ? TyTy::TyVar (
    1988              :           TypeCheckType::Resolve (expr.get_return_type ())->get_ref ())
    1989           65 :         : TyTy::TyVar::get_implicit_infer_var (expr.get_locus ());
    1990              : 
    1991              :   // resolve the block
    1992           65 :   location_t closure_expr_locus = expr.get_expr ().get_locus ();
    1993           65 :   TyTy::BaseType *closure_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ());
    1994          130 :   coercion_site (expr.get_mappings ().get_hirid (),
    1995              :                  TyTy::TyWithLocation (result_type.get_tyty (),
    1996           65 :                                        result_type_locus),
    1997           65 :                  TyTy::TyWithLocation (closure_expr_ty, closure_expr_locus),
    1998              :                  expr.get_locus ());
    1999              : 
    2000              :   // generate the closure type
    2001           65 :   NodeId closure_node_id = expr.get_mappings ().get_nodeid ();
    2002              : 
    2003              :   // Resolve closure captures
    2004              : 
    2005           65 :   std::set<NodeId> captures;
    2006              : 
    2007           65 :   if (auto opt_cap
    2008           65 :       = Analysis::Mappings::get ().lookup_captures (closure_node_id))
    2009           42 :     for (auto cap : opt_cap.value ())
    2010           21 :       captures.insert (cap);
    2011              : 
    2012           65 :   infered = new TyTy::ClosureType (ref, id, ident, closure_args, result_type,
    2013          130 :                                    subst_refs, captures);
    2014              : 
    2015              :   // FIXME
    2016              :   // all closures automatically inherit the appropriate fn trait. Lets just
    2017              :   // assume FnOnce for now. I think this is based on the return type of the
    2018              :   // closure
    2019              : 
    2020           65 :   LangItem::Kind lang_item_type = LangItem::Kind::FN_ONCE;
    2021              : 
    2022           65 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
    2023           65 :   if (!lang_item_defined)
    2024              :     {
    2025              :       // FIXME
    2026              :       // we need to have a unified way or error'ing when we are missing lang
    2027              :       // items that is useful
    2028            0 :       rust_fatal_error (expr.get_locus (), "unable to find lang item: %qs",
    2029            0 :                         LangItem::ToString (lang_item_type).c_str ());
    2030              :     }
    2031           65 :   DefId &respective_lang_item_id = lang_item_defined.value ();
    2032              : 
    2033              :   // these lang items are always traits
    2034           65 :   HIR::Item *item = mappings.lookup_defid (respective_lang_item_id).value ();
    2035           65 :   rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
    2036           65 :   HIR::Trait *trait_item = static_cast<HIR::Trait *> (item);
    2037              : 
    2038           65 :   TraitReference *trait = TraitResolver::Resolve (*trait_item);
    2039           65 :   rust_assert (!trait->is_error ());
    2040              : 
    2041           65 :   TyTy::TypeBoundPredicate predicate (*trait, BoundPolarity::RegularBound,
    2042           65 :                                       expr.get_locus ());
    2043              : 
    2044              :   // resolve the trait bound where the <(Args)> are the parameter tuple type
    2045           65 :   HIR::GenericArgs args = HIR::GenericArgs::create_empty (expr.get_locus ());
    2046              : 
    2047              :   // lets generate an implicit Type so that it resolves to the implict tuple
    2048              :   // type we have created
    2049           65 :   auto crate_num = mappings.get_current_crate ();
    2050           65 :   Analysis::NodeMapping mapping (crate_num, expr.get_mappings ().get_nodeid (),
    2051           65 :                                  implicit_args_id, UNKNOWN_LOCAL_DEFID);
    2052           65 :   HIR::TupleType *implicit_tuple
    2053              :     = new HIR::TupleType (mapping,
    2054              :                           {} // we dont need to fill this out because it will
    2055              :                              // auto resolve because the hir id's match
    2056              :                           ,
    2057           65 :                           expr.get_locus ());
    2058           65 :   args.get_type_args ().emplace_back (implicit_tuple);
    2059              : 
    2060              :   // apply the arguments
    2061           65 :   predicate.apply_generic_arguments (&args, false, false);
    2062              : 
    2063              :   // finally inherit the trait bound
    2064          130 :   infered->inherit_bounds ({predicate});
    2065           65 : }
    2066              : 
    2067              : bool
    2068        12277 : TypeCheckExpr::resolve_operator_overload (
    2069              :   LangItem::Kind lang_item_type, HIR::OperatorExprMeta expr,
    2070              :   TyTy::BaseType *lhs, TyTy::BaseType *rhs,
    2071              :   HIR::PathIdentSegment specified_segment)
    2072              : {
    2073              :   // look up lang item for arithmetic type
    2074        12277 :   std::string associated_item_name = LangItem::ToString (lang_item_type);
    2075              : 
    2076        12277 :   auto lang_item_defined = mappings.lookup_lang_item (lang_item_type);
    2077              :   // probe for the lang-item
    2078        12277 :   if (!lang_item_defined)
    2079              :     return false;
    2080              : 
    2081         2716 :   DefId &respective_lang_item_id = lang_item_defined.value ();
    2082         2716 :   auto def_lookup = mappings.lookup_defid (respective_lang_item_id);
    2083         2716 :   rust_assert (def_lookup.has_value ());
    2084              : 
    2085         2716 :   HIR::Item *def_item = def_lookup.value ();
    2086         2716 :   rust_assert (def_item->get_item_kind () == HIR::Item::ItemKind::Trait);
    2087         2716 :   HIR::Trait &trait = *static_cast<HIR::Trait *> (def_item);
    2088         2716 :   TraitReference *defid_trait_reference = TraitResolver::Resolve (trait);
    2089         2716 :   rust_assert (!defid_trait_reference->is_error ());
    2090              : 
    2091              :   // we might be in a static or const context and unknown is fine
    2092         2716 :   TypeCheckContextItem current_context = TypeCheckContextItem::get_error ();
    2093         2716 :   if (context->have_function_context ())
    2094              :     {
    2095         2708 :       current_context = context->peek_context ();
    2096              :     }
    2097              : 
    2098         2716 :   auto segment = specified_segment.is_error ()
    2099         3730 :                    ? HIR::PathIdentSegment (associated_item_name)
    2100         2716 :                    : specified_segment;
    2101         2716 :   auto candidates = MethodResolver::Probe (lhs, segment);
    2102              : 
    2103              :   // remove any recursive candidates
    2104         2716 :   std::set<MethodCandidate> resolved_candidates;
    2105         5448 :   for (auto &c : candidates)
    2106              :     {
    2107         2732 :       const TyTy::BaseType *candidate_type = c.candidate.ty;
    2108         2732 :       rust_assert (candidate_type->get_kind () == TyTy::TypeKind::FNDEF);
    2109              : 
    2110         2732 :       const TyTy::FnType &fn
    2111              :         = *static_cast<const TyTy::FnType *> (candidate_type);
    2112              : 
    2113         2732 :       DefId current_fn_defid = current_context.get_defid ();
    2114         5464 :       bool recursive_candidated = fn.get_id () == current_fn_defid;
    2115         1537 :       if (!recursive_candidated)
    2116              :         {
    2117         1537 :           resolved_candidates.insert (c);
    2118              :         }
    2119              :     }
    2120              : 
    2121         2716 :   std::vector<TyTy::BaseType *> select_args = {};
    2122         2716 :   if (rhs != nullptr)
    2123         2490 :     select_args = {rhs};
    2124         2716 :   auto selected_candidates
    2125         2716 :     = MethodResolver::Select (resolved_candidates, lhs, select_args);
    2126              : 
    2127         2716 :   bool have_implementation_for_lang_item = selected_candidates.size () > 0;
    2128         2716 :   if (!have_implementation_for_lang_item)
    2129              :     return false;
    2130              : 
    2131         1422 :   if (selected_candidates.size () > 1)
    2132              :     {
    2133            8 :       auto infer
    2134            8 :         = TyTy::TyVar::get_implicit_infer_var (expr.get_locus ()).get_tyty ();
    2135            8 :       auto trait_subst = defid_trait_reference->get_trait_substs ();
    2136            8 :       rust_assert (trait_subst.size () > 0);
    2137              : 
    2138            8 :       TyTy::TypeBoundPredicate pred (respective_lang_item_id, trait_subst,
    2139              :                                      BoundPolarity::RegularBound,
    2140            8 :                                      expr.get_locus ());
    2141              : 
    2142            8 :       std::vector<TyTy::SubstitutionArg> mappings;
    2143            8 :       auto &self_param_mapping = trait_subst[0];
    2144            8 :       mappings.emplace_back (&self_param_mapping, lhs);
    2145              : 
    2146            8 :       if (rhs != nullptr)
    2147              :         {
    2148            8 :           rust_assert (trait_subst.size () == 2);
    2149            8 :           auto &rhs_param_mapping = trait_subst[1];
    2150            8 :           mappings.emplace_back (&rhs_param_mapping, lhs);
    2151              :         }
    2152              : 
    2153            8 :       std::map<std::string, TyTy::BaseType *> binding_args;
    2154            8 :       binding_args["Output"] = infer;
    2155              : 
    2156            8 :       TyTy::SubstitutionArgumentMappings arg_mappings (mappings, binding_args,
    2157            8 :                                                        TyTy::RegionParamList (
    2158            8 :                                                          trait_subst.size ()),
    2159           16 :                                                        expr.get_locus ());
    2160            8 :       pred.apply_argument_mappings (arg_mappings, false);
    2161              : 
    2162           16 :       infer->inherit_bounds ({pred});
    2163           16 :       DeferredOpOverload defer (expr.get_mappings ().get_hirid (),
    2164           16 :                                 lang_item_type, specified_segment, pred, expr);
    2165            8 :       context->insert_deferred_operator_overload (std::move (defer));
    2166              : 
    2167            8 :       if (rhs != nullptr)
    2168           16 :         lhs = unify_site (expr.get_mappings ().get_hirid (),
    2169            8 :                           TyTy::TyWithLocation (lhs),
    2170            8 :                           TyTy::TyWithLocation (rhs), expr.get_locus ());
    2171              : 
    2172           16 :       infered = unify_site (expr.get_mappings ().get_hirid (),
    2173            8 :                             TyTy::TyWithLocation (lhs),
    2174            8 :                             TyTy::TyWithLocation (infer), expr.get_locus ());
    2175            8 :       return true;
    2176            8 :     }
    2177              : 
    2178              :   // Get the adjusted self
    2179         1414 :   MethodCandidate candidate = *selected_candidates.begin ();
    2180         1414 :   Adjuster adj (lhs);
    2181         1414 :   TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
    2182              : 
    2183              :   // store the adjustments for code-generation to know what to do
    2184         1414 :   context->insert_autoderef_mappings (expr.get_lvalue_mappings ().get_hirid (),
    2185              :                                       std::move (candidate.adjustments));
    2186              : 
    2187         1414 :   PathProbeCandidate &resolved_candidate = candidate.candidate;
    2188         1414 :   TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
    2189         1414 :   NodeId resolved_node_id
    2190         1414 :     = resolved_candidate.is_impl_candidate ()
    2191         1414 :         ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
    2192         1012 :             .get_nodeid ()
    2193          402 :         : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
    2194              : 
    2195         1414 :   rust_assert (lookup_tyty->get_kind () == TyTy::TypeKind::FNDEF);
    2196         1414 :   TyTy::BaseType *lookup = lookup_tyty;
    2197         1414 :   TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
    2198         2828 :   rust_assert (fn->is_method ());
    2199              : 
    2200         1816 :   rust_debug ("is_impl_item_candidate: %s",
    2201              :               resolved_candidate.is_impl_candidate () ? "true" : "false");
    2202              : 
    2203              :   // in the case where we resolve to a trait bound we have to be careful we are
    2204              :   // able to do so there is a case where we are currently resolving the deref
    2205              :   // operator overload function which is generic and this might resolve to the
    2206              :   // trait item of deref which is not valid as its just another recursive case
    2207         1414 :   if (current_context.get_type () == TypeCheckContextItem::ItemType::IMPL_ITEM)
    2208              :     {
    2209          771 :       auto &impl_item = current_context.get_impl_item ();
    2210          771 :       HIR::ImplBlock *parent = impl_item.first;
    2211          771 :       HIR::Function *fn = impl_item.second;
    2212              : 
    2213          771 :       bool is_deref = lang_item_type == LangItem::Kind::DEREF
    2214          771 :                       || lang_item_type == LangItem::Kind::DEREF_MUT;
    2215         3084 :       bool is_deref_match = fn->get_function_name ().as_string ().compare (
    2216         1542 :                               LangItem::ToString (LangItem::Kind::DEREF))
    2217              :                               == 0
    2218         2167 :                             || fn->get_function_name ().as_string ().compare (
    2219         1396 :                                  LangItem::ToString (LangItem::Kind::DEREF_MUT))
    2220              :                                  == 0;
    2221              : 
    2222          771 :       bool is_recursive_op
    2223         1542 :         = fn->get_function_name ().as_string ().compare (associated_item_name)
    2224              :             == 0
    2225          771 :           || (is_deref && is_deref_match);
    2226          771 :       if (parent->has_trait_ref () && is_recursive_op)
    2227              :         {
    2228          335 :           TraitReference *trait_reference
    2229          335 :             = TraitResolver::Lookup (parent->get_trait_ref ());
    2230          335 :           if (!trait_reference->is_error ())
    2231              :             {
    2232          335 :               TyTy::BaseType *lookup = nullptr;
    2233          335 :               bool ok = context->lookup_type (fn->get_mappings ().get_hirid (),
    2234              :                                               &lookup);
    2235          335 :               rust_assert (ok);
    2236          335 :               rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
    2237              : 
    2238          335 :               TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
    2239          670 :               rust_assert (fntype->is_method ());
    2240              : 
    2241          335 :               bool is_lang_item_impl
    2242          335 :                 = trait_reference->get_mappings ().get_defid ()
    2243          337 :                     == respective_lang_item_id
    2244            2 :                   || (is_deref && is_deref_match);
    2245          335 :               bool self_is_lang_item_self
    2246          335 :                 = fntype->get_self_type ()->is_equal (*adjusted_self);
    2247          335 :               bool recursive_operator_overload
    2248              :                 = is_lang_item_impl && self_is_lang_item_self;
    2249              : 
    2250          335 :               if (recursive_operator_overload)
    2251          150 :                 return false;
    2252              :             }
    2253              :         }
    2254              :     }
    2255              : 
    2256              :   // we found a valid operator overload
    2257         1264 :   rust_debug_loc (expr.get_locus (), "resolved operator overload to: {%u} {%s}",
    2258         1264 :                   candidate.candidate.ty->get_ref (),
    2259         1264 :                   candidate.candidate.ty->debug_str ().c_str ());
    2260              : 
    2261              :   // handle generics
    2262         1264 :   if (lookup->needs_generic_substitutions ())
    2263          381 :     lookup = SubstMapper::InferSubst (lookup, expr.get_locus ());
    2264              : 
    2265              :   // type check the arguments if required
    2266         1264 :   TyTy::FnType *type = static_cast<TyTy::FnType *> (lookup);
    2267         1264 :   rust_assert (type->num_params () > 0);
    2268         1264 :   auto &fnparam = type->param_at (0);
    2269              : 
    2270              :   // typecheck the self
    2271         2528 :   unify_site (expr.get_mappings ().get_hirid (),
    2272         1264 :               TyTy::TyWithLocation (fnparam.get_type ()),
    2273         1264 :               TyTy::TyWithLocation (adjusted_self), expr.get_locus ());
    2274         1264 :   if (rhs == nullptr)
    2275              :     {
    2276           63 :       rust_assert (type->num_params () == 1);
    2277              :     }
    2278              :   else
    2279              :     {
    2280         1201 :       rust_assert (type->num_params () == 2);
    2281         1201 :       auto &fnparam = type->param_at (1);
    2282         2402 :       unify_site (expr.get_mappings ().get_hirid (),
    2283         1201 :                   TyTy::TyWithLocation (fnparam.get_type ()),
    2284         1201 :                   TyTy::TyWithLocation (rhs), expr.get_locus ());
    2285              :     }
    2286              : 
    2287         1264 :   rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
    2288         1264 :   fn = static_cast<TyTy::FnType *> (lookup);
    2289         1264 :   fn->monomorphize ();
    2290              : 
    2291              :   // get the return type
    2292         1264 :   TyTy::BaseType *function_ret_tyty
    2293         1264 :     = type->get_return_type ()->monomorphized_clone ();
    2294              : 
    2295              :   // store the expected fntype
    2296         1264 :   context->insert_operator_overload (expr.get_mappings ().get_hirid (), type);
    2297              : 
    2298              :   // set up the resolved name on the path
    2299         1264 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    2300              : 
    2301         1264 :   nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
    2302         1264 :                     Resolver2_0::Definition (resolved_node_id),
    2303              :                     Resolver2_0::Namespace::Types);
    2304              : 
    2305              :   // return the result of the function back
    2306         1264 :   infered = function_ret_tyty;
    2307              : 
    2308         1264 :   return true;
    2309         4130 : }
    2310              : 
    2311              : HIR::PathIdentSegment
    2312        10754 : TypeCheckExpr::resolve_possible_fn_trait_call_method_name (
    2313              :   const TyTy::BaseType &receiver,
    2314              :   TyTy::TypeBoundPredicate *associated_predicate)
    2315              : {
    2316              :   // FIXME
    2317              :   // the logic to map the FnTrait to their respective call trait-item is
    2318              :   // duplicated over in the backend/rust-compile-expr.cc
    2319        10781 :   for (const auto &bound : receiver.get_specified_bounds ())
    2320              :     {
    2321           93 :       bool found_fn = bound.get_name ().compare ("Fn") == 0;
    2322           93 :       bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
    2323           93 :       bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
    2324              : 
    2325           93 :       if (found_fn)
    2326              :         {
    2327            0 :           *associated_predicate = bound;
    2328            0 :           return HIR::PathIdentSegment ("call");
    2329              :         }
    2330           93 :       else if (found_fn_mut)
    2331              :         {
    2332            0 :           *associated_predicate = bound;
    2333            0 :           return HIR::PathIdentSegment ("call_mut");
    2334              :         }
    2335           93 :       else if (found_fn_once)
    2336              :         {
    2337           66 :           *associated_predicate = bound;
    2338           66 :           return HIR::PathIdentSegment ("call_once");
    2339              :         }
    2340              :     }
    2341              : 
    2342        10688 :   if (receiver.is<TyTy::ReferenceType> ())
    2343              :     {
    2344            0 :       const auto &ref = static_cast<const TyTy::ReferenceType &> (receiver);
    2345            0 :       const auto &underlying = *ref.get_base ();
    2346            0 :       for (const auto &bound : underlying.get_specified_bounds ())
    2347              :         {
    2348            0 :           bool found_fn = bound.get_name ().compare ("Fn") == 0;
    2349            0 :           bool found_fn_mut = bound.get_name ().compare ("FnMut") == 0;
    2350            0 :           bool found_fn_once = bound.get_name ().compare ("FnOnce") == 0;
    2351              : 
    2352            0 :           if (found_fn)
    2353              :             {
    2354            0 :               *associated_predicate = bound;
    2355            0 :               return HIR::PathIdentSegment ("call");
    2356              :             }
    2357            0 :           else if (found_fn_mut)
    2358              :             {
    2359            0 :               *associated_predicate = bound;
    2360            0 :               return HIR::PathIdentSegment ("call_mut");
    2361              :             }
    2362            0 :           else if (found_fn_once)
    2363              :             {
    2364            0 :               *associated_predicate = bound;
    2365            0 :               return HIR::PathIdentSegment ("call_once");
    2366              :             }
    2367              :         }
    2368              :     }
    2369              : 
    2370              :   // nothing
    2371        10688 :   *associated_predicate = TyTy::TypeBoundPredicate::error ();
    2372        10688 :   return HIR::PathIdentSegment ("");
    2373              : }
    2374              : 
    2375              : bool
    2376        10754 : TypeCheckExpr::resolve_fn_trait_call (HIR::CallExpr &expr,
    2377              :                                       TyTy::BaseType *receiver_tyty,
    2378              :                                       TyTy::BaseType **result)
    2379              : {
    2380              :   // we turn this into a method call expr
    2381              :   // TODO: add implicit self argument (?)
    2382        10754 :   auto associated_predicate = TyTy::TypeBoundPredicate::error ();
    2383        10754 :   HIR::PathIdentSegment method_name
    2384              :     = resolve_possible_fn_trait_call_method_name (*receiver_tyty,
    2385        10754 :                                                   &associated_predicate);
    2386        10754 :   if (method_name.is_error () || associated_predicate.is_error ())
    2387        10688 :     return false;
    2388              : 
    2389           66 :   auto candidates = MethodResolver::Probe (receiver_tyty, method_name);
    2390           66 :   if (candidates.empty ())
    2391              :     return false;
    2392              : 
    2393           66 :   if (candidates.size () > 1)
    2394              :     {
    2395            0 :       rich_location r (line_table, expr.get_locus ());
    2396            0 :       for (auto &c : candidates)
    2397            0 :         r.add_range (c.candidate.locus);
    2398              : 
    2399            0 :       rust_error_at (
    2400              :         r, "multiple candidates found for function trait method call %qs",
    2401            0 :         method_name.to_string ().c_str ());
    2402            0 :       return false;
    2403            0 :     }
    2404              : 
    2405              :   // FnOnce::Output is normalized lazily by normalize_projection's closure
    2406              :   // special-case; no explicit setup is required here.
    2407              : 
    2408           66 :   auto candidate = *candidates.begin ();
    2409           66 :   rust_debug_loc (expr.get_locus (),
    2410              :                   "resolved call-expr to fn trait: {%u} {%s}",
    2411           66 :                   candidate.candidate.ty->get_ref (),
    2412           66 :                   candidate.candidate.ty->debug_str ().c_str ());
    2413              : 
    2414              :   // Get the adjusted self
    2415           66 :   Adjuster adj (receiver_tyty);
    2416           66 :   TyTy::BaseType *adjusted_self = adj.adjust_type (candidate.adjustments);
    2417              : 
    2418              :   // store the adjustments for code-generation to know what to do which must be
    2419              :   // stored onto the receiver to so as we don't trigger duplicate deref mappings
    2420              :   // ICE when an argument is a method call
    2421           66 :   HIR::Expr &fnexpr = expr.get_fnexpr ();
    2422           66 :   HirId autoderef_mappings_id = fnexpr.get_mappings ().get_hirid ();
    2423           66 :   context->insert_autoderef_mappings (autoderef_mappings_id,
    2424              :                                       std::move (candidate.adjustments));
    2425              : 
    2426           66 :   PathProbeCandidate &resolved_candidate = candidate.candidate;
    2427           66 :   TyTy::BaseType *lookup_tyty = candidate.candidate.ty;
    2428           66 :   NodeId resolved_node_id
    2429           66 :     = resolved_candidate.is_impl_candidate ()
    2430           66 :         ? resolved_candidate.item.impl.impl_item->get_impl_mappings ()
    2431            0 :             .get_nodeid ()
    2432           66 :         : resolved_candidate.item.trait.item_ref->get_mappings ().get_nodeid ();
    2433              : 
    2434           66 :   if (lookup_tyty->get_kind () != TyTy::TypeKind::FNDEF)
    2435              :     {
    2436            0 :       rich_location r (line_table, expr.get_locus ());
    2437            0 :       r.add_range (resolved_candidate.locus);
    2438            0 :       rust_error_at (r, "associated impl item is not a method");
    2439            0 :       return false;
    2440            0 :     }
    2441              : 
    2442           66 :   TyTy::BaseType *lookup = lookup_tyty;
    2443           66 :   TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
    2444          132 :   if (!fn->is_method ())
    2445              :     {
    2446            0 :       rich_location r (line_table, expr.get_locus ());
    2447            0 :       r.add_range (resolved_candidate.locus);
    2448            0 :       rust_error_at (r, "associated function is not a method");
    2449            0 :       return false;
    2450            0 :     }
    2451              : 
    2452              :   // fn traits only support tuple argument passing so we need to implicitly set
    2453              :   // this up to get the same type checking we get in the rest of the pipeline
    2454              : 
    2455           66 :   std::vector<TyTy::TyVar> call_args;
    2456          132 :   for (auto &arg : expr.get_arguments ())
    2457              :     {
    2458           66 :       TyTy::BaseType *a = TypeCheckExpr::Resolve (*arg);
    2459           66 :       call_args.emplace_back (a->get_ref ());
    2460              :     }
    2461              : 
    2462              :   // crate implicit tuple
    2463           66 :   HirId implicit_arg_id = mappings.get_next_hir_id ();
    2464           66 :   Analysis::NodeMapping mapping (mappings.get_current_crate (), UNKNOWN_NODEID,
    2465           66 :                                  implicit_arg_id, UNKNOWN_LOCAL_DEFID);
    2466              : 
    2467           66 :   TyTy::TupleType *tuple
    2468           66 :     = new TyTy::TupleType (implicit_arg_id, expr.get_locus (), call_args);
    2469           66 :   context->insert_implicit_type (implicit_arg_id, tuple);
    2470              : 
    2471           66 :   std::vector<TyTy::Argument> args;
    2472           66 :   args.emplace_back (mapping, tuple,
    2473           66 :                      expr.get_locus () /*FIXME is there a better location*/);
    2474              : 
    2475           66 :   TyTy::BaseType *function_ret_tyty
    2476           66 :     = TyTy::TypeCheckMethodCallExpr::go (fn, expr.get_mappings (), args,
    2477              :                                          expr.get_locus (), expr.get_locus (),
    2478              :                                          adjusted_self, context);
    2479           66 :   if (function_ret_tyty == nullptr
    2480           66 :       || function_ret_tyty->get_kind () == TyTy::TypeKind::ERROR)
    2481              :     {
    2482            0 :       rust_error_at (expr.get_locus (),
    2483              :                      "failed check fn trait call-expr MethodCallExpr");
    2484            0 :       return false;
    2485              :     }
    2486              : 
    2487              :   // store the expected fntype
    2488           66 :   context->insert_operator_overload (expr.get_mappings ().get_hirid (), fn);
    2489              : 
    2490              :   // set up the resolved name on the path
    2491           66 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
    2492              : 
    2493              :   // TODO: What namespace to use for inserting and looking up here? It's a trait
    2494              :   // call, so NS::Types is right?
    2495              : 
    2496           66 :   auto existing = nr_ctx.lookup (expr.get_mappings ().get_nodeid (),
    2497              :                                  Resolver2_0::Namespace::Types);
    2498           66 :   if (existing)
    2499            9 :     rust_assert (*existing == resolved_node_id);
    2500              :   else
    2501           57 :     nr_ctx.map_usage (Resolver2_0::Usage (expr.get_mappings ().get_nodeid ()),
    2502           57 :                       Resolver2_0::Definition (resolved_node_id),
    2503              :                       Resolver2_0::Namespace::Types);
    2504              : 
    2505              :   // return the result of the function back
    2506           66 :   auto mono = function_ret_tyty->monomorphized_clone ();
    2507           66 :   *result = mono;
    2508              : 
    2509           66 :   return true;
    2510        10952 : }
    2511              : 
    2512              : bool
    2513         7760 : TypeCheckExpr::validate_arithmetic_type (
    2514              :   const TyTy::BaseType *tyty, HIR::ArithmeticOrLogicalExpr::ExprType expr_type)
    2515              : {
    2516         7760 :   auto type = tyty->destructure ();
    2517         7760 :   if (type->get_kind () == TyTy::TypeKind::CONST)
    2518              :     {
    2519           15 :       auto base_const = type->as_const_type ();
    2520           15 :       type = base_const->get_specified_type ();
    2521              :     }
    2522              : 
    2523              :   // https://doc.rust-lang.org/reference/expressions/operator-expr.html#arithmetic-and-logical-binary-operators
    2524              :   // this will change later when traits are added
    2525         7760 :   switch (expr_type)
    2526              :     {
    2527         6580 :     case ArithmeticOrLogicalOperator::ADD:
    2528         6580 :     case ArithmeticOrLogicalOperator::SUBTRACT:
    2529         6580 :     case ArithmeticOrLogicalOperator::MULTIPLY:
    2530         6580 :     case ArithmeticOrLogicalOperator::DIVIDE:
    2531         6580 :     case ArithmeticOrLogicalOperator::MODULUS:
    2532         6580 :       return (type->get_kind () == TyTy::TypeKind::INT)
    2533         5025 :              || (type->get_kind () == TyTy::TypeKind::UINT)
    2534         4179 :              || (type->get_kind () == TyTy::TypeKind::FLOAT)
    2535         3795 :              || (type->get_kind () == TyTy::TypeKind::USIZE)
    2536         3177 :              || (type->get_kind () == TyTy::TypeKind::ISIZE)
    2537         3109 :              || (type->get_kind () == TyTy::TypeKind::INFER
    2538         3106 :                  && (((const TyTy::InferType *) type)->get_infer_kind ()
    2539              :                      == TyTy::InferType::INTEGRAL))
    2540         6620 :              || (type->get_kind () == TyTy::TypeKind::INFER
    2541           37 :                  && (((const TyTy::InferType *) type)->get_infer_kind ()
    2542              :                      == TyTy::InferType::FLOAT));
    2543              : 
    2544              :       // integers or bools
    2545         1014 :     case ArithmeticOrLogicalOperator::BITWISE_AND:
    2546         1014 :     case ArithmeticOrLogicalOperator::BITWISE_OR:
    2547         1014 :     case ArithmeticOrLogicalOperator::BITWISE_XOR:
    2548         1014 :       return (type->get_kind () == TyTy::TypeKind::INT)
    2549          965 :              || (type->get_kind () == TyTy::TypeKind::UINT)
    2550          171 :              || (type->get_kind () == TyTy::TypeKind::USIZE)
    2551          164 :              || (type->get_kind () == TyTy::TypeKind::ISIZE)
    2552          164 :              || (type->get_kind () == TyTy::TypeKind::BOOL)
    2553         1136 :              || (type->get_kind () == TyTy::TypeKind::INFER
    2554          122 :                  && (((const TyTy::InferType *) type)->get_infer_kind ()
    2555              :                      == TyTy::InferType::INTEGRAL));
    2556              : 
    2557              :       // integers only
    2558          166 :     case ArithmeticOrLogicalOperator::LEFT_SHIFT:
    2559          166 :     case ArithmeticOrLogicalOperator::RIGHT_SHIFT:
    2560          166 :       return (type->get_kind () == TyTy::TypeKind::INT)
    2561          151 :              || (type->get_kind () == TyTy::TypeKind::UINT)
    2562           93 :              || (type->get_kind () == TyTy::TypeKind::USIZE)
    2563           91 :              || (type->get_kind () == TyTy::TypeKind::ISIZE)
    2564          257 :              || (type->get_kind () == TyTy::TypeKind::INFER
    2565           91 :                  && (((const TyTy::InferType *) type)->get_infer_kind ()
    2566              :                      == TyTy::InferType::INTEGRAL));
    2567              :     }
    2568              : 
    2569            0 :   rust_unreachable ();
    2570              :   return false;
    2571              : }
    2572              : 
    2573              : } // namespace Resolver
    2574              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.