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.7 % 1342 1191
Test Date: 2025-08-30 13:27:53 Functions: 98.1 % 52 51
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-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.