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