LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-type.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 86.5 % 608 526
Test Date: 2026-10-24 16:24:59 Functions: 60.0 % 45 27
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-hir-type-check-type.h"
      20              : #include "options.h"
      21              : #include "optional.h"
      22              : #include "rich-location.h"
      23              : #include "rust-hir-map.h"
      24              : #include "rust-hir-trait-resolve.h"
      25              : #include "rust-hir-type-check-expr.h"
      26              : #include "rust-hir-path-probe-type.h"
      27              : #include "rust-finalized-name-resolution-context.h"
      28              : #include "rust-mapping-common.h"
      29              : #include "rust-rib.h"
      30              : #include "rust-substitution-mapper.h"
      31              : #include "rust-type-util.h"
      32              : #include "rust-system.h"
      33              : #include "rust-compile-base.h"
      34              : #include "rust-resolve-builtins.h"
      35              : #include "rust-tyty.h"
      36              : #include "text-range-label.h"
      37              : 
      38              : namespace Rust {
      39              : namespace Resolver {
      40              : 
      41              : HIR::GenericArgs
      42            0 : TypeCheckResolveGenericArguments::resolve (HIR::TypePathSegment &segment)
      43              : {
      44            0 :   TypeCheckResolveGenericArguments resolver (segment.get_locus ());
      45            0 :   switch (segment.get_type ())
      46              :     {
      47            0 :     case HIR::TypePathSegment::SegmentType::GENERIC:
      48            0 :       resolver.visit (static_cast<HIR::TypePathSegmentGeneric &> (segment));
      49            0 :       break;
      50              : 
      51              :     default:
      52              :       break;
      53              :     }
      54            0 :   return resolver.args;
      55            0 : }
      56              : 
      57              : void
      58            0 : TypeCheckResolveGenericArguments::visit (HIR::TypePathSegmentGeneric &generic)
      59              : {
      60            0 :   args = generic.get_generic_args ();
      61            0 : }
      62              : 
      63              : TyTy::BaseType *
      64       138692 : TypeCheckType::Resolve (HIR::Type &type, ResolutionMode mode)
      65              : {
      66              :   // is it already resolved?
      67       138692 :   auto context = TypeCheckContext::get ();
      68       138692 :   TyTy::BaseType *resolved = nullptr;
      69       138692 :   bool already_resolved
      70       138692 :     = context->lookup_type (type.get_mappings ().get_hirid (), &resolved);
      71       138692 :   if (already_resolved && mode == ResolutionMode::REFERENCE)
      72        69215 :     return resolved;
      73              : 
      74        69477 :   TypeCheckType resolver (type.get_mappings ().get_hirid (), mode);
      75        69477 :   type.accept_vis (resolver);
      76        69476 :   rust_assert (resolver.translated != nullptr);
      77        69476 :   resolver.context->insert_type (type.get_mappings (), resolver.translated);
      78        69476 :   return resolver.translated;
      79        69476 : }
      80              : 
      81              : void
      82           66 : TypeCheckType::visit (HIR::BareFunctionType &fntype)
      83              : {
      84           66 :   auto binder_pin = context->push_lifetime_binder ();
      85           68 :   for (auto &lifetime_param : fntype.get_for_lifetimes ())
      86              :     {
      87            2 :       context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
      88              :     }
      89              : 
      90           66 :   TyTy::BaseType *return_type;
      91           66 :   if (fntype.has_return_type ())
      92              :     {
      93           46 :       return_type = TypeCheckType::Resolve (fntype.get_return_type ());
      94              :     }
      95              :   else
      96              :     {
      97              :       // needs a new implicit ID
      98           20 :       HirId ref = mappings.get_next_hir_id ();
      99           20 :       return_type = TyTy::TupleType::get_unit_type ();
     100           20 :       context->insert_implicit_type (ref, return_type);
     101              :     }
     102              : 
     103           66 :   std::vector<TyTy::TyVar> params;
     104           66 :   params.reserve (fntype.get_function_params ().size ());
     105              : 
     106          117 :   for (auto &param : fntype.get_function_params ())
     107              :     {
     108           51 :       TyTy::BaseType *ptype = TypeCheckType::Resolve (param.get_type ());
     109           51 :       params.emplace_back (ptype->get_ref ());
     110              :     }
     111              : 
     112           66 :   translated
     113          132 :     = new TyTy::FnPtr (fntype.get_mappings ().get_hirid (), fntype.get_locus (),
     114              :                        std::move (params),
     115           66 :                        TyTy::TyVar (return_type->get_ref ()),
     116           66 :                        fntype.get_function_qualifiers ().get_abi (),
     117          264 :                        fntype.get_function_qualifiers ().get_unsafety ());
     118           66 : }
     119              : 
     120              : void
     121          516 : TypeCheckType::visit (HIR::TupleType &tuple)
     122              : {
     123          516 :   if (tuple.is_unit_type ())
     124              :     {
     125           97 :       translated = TyTy::TupleType::get_unit_type ();
     126           97 :       return;
     127              :     }
     128              : 
     129          419 :   std::vector<TyTy::TyVar> fields;
     130          419 :   fields.reserve (tuple.get_elems ().size ());
     131              : 
     132         1212 :   for (auto &elem : tuple.get_elems ())
     133              :     {
     134          793 :       auto field_ty = TypeCheckType::Resolve (*elem);
     135          793 :       fields.emplace_back (field_ty->get_ref ());
     136              :     }
     137              : 
     138          838 :   translated = new TyTy::TupleType (tuple.get_mappings ().get_hirid (),
     139         1257 :                                     tuple.get_locus (), fields);
     140          419 : }
     141              : 
     142              : void
     143        54399 : TypeCheckType::visit (HIR::TypePath &path)
     144              : {
     145              :   // this can happen so we need to look up the root then resolve the
     146              :   // remaining segments if possible
     147        54399 :   bool wasBigSelf = false;
     148        54399 :   size_t offset = 0;
     149        54399 :   TyTy::BaseType *root = resolve_root_path (path, &offset, &wasBigSelf);
     150        54399 :   if (root->get_kind () == TyTy::TypeKind::ERROR)
     151              :     {
     152            9 :       rust_debug_loc (path.get_locus (), "failed to resolve type-path type");
     153        53252 :       return;
     154              :     }
     155              : 
     156        54390 :   TyTy::BaseType *path_type = root;
     157        54390 :   if (mode == ResolutionMode::REFERENCE)
     158              :     {
     159              :       // A recursive path must keep referring to the in-progress nominal ADT.
     160              :       // Cloning its currently empty variant list would leave a permanently
     161              :       // incomplete snapshot in the recursive field.
     162        53030 :       auto *root_adt = root->try_as<TyTy::ADTType> ();
     163         6144 :       bool recursive_root
     164         6144 :         = root_adt != nullptr && root_adt->get_variants ().empty ();
     165        52995 :       if (!recursive_root)
     166              :         {
     167        52995 :           path_type = root->clone ();
     168        52995 :           path_type->set_ref (path.get_mappings ().get_hirid ());
     169              :         }
     170        53030 :       context->insert_implicit_type (path.get_mappings ().get_hirid (),
     171              :                                      path_type);
     172              :     }
     173              : 
     174        54390 :   bool fully_resolved = offset >= path.get_segments ().size ();
     175        54390 :   if (fully_resolved)
     176              :     {
     177        53243 :       translated = path_type;
     178        53243 :       rust_debug_loc (path.get_locus (), "root resolved type-path to: [%s]",
     179              :                       translated->debug_str ().c_str ());
     180              :       return;
     181              :     }
     182              : 
     183         1147 :   translated
     184         1147 :     = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
     185         1147 :                         offset, path_type, path.get_mappings (),
     186         1147 :                         path.get_locus (), wasBigSelf);
     187              : 
     188         1147 :   if (auto p = translated->try_as<TyTy::ProjectionType> ())
     189         1144 :     translated
     190         1144 :       = normalize_projection (p, path.get_locus (), false /*emit errors*/,
     191              :                               false /*unify self*/);
     192              : 
     193         1147 :   rust_debug_loc (path.get_locus (), "resolved type-path to: [%s]",
     194              :                   translated->debug_str ().c_str ());
     195              : }
     196              : 
     197              : void
     198          249 : TypeCheckType::visit (HIR::QualifiedPathInType &path)
     199              : {
     200          249 :   HIR::QualifiedPathType qual_path_type = path.get_path_type ();
     201          249 :   TyTy::BaseType *root = TypeCheckType::Resolve (qual_path_type.get_type ());
     202          249 :   if (root->get_kind () == TyTy::TypeKind::ERROR)
     203              :     {
     204            0 :       rust_debug_loc (path.get_locus (), "failed to resolve the root");
     205              :       return;
     206              :     }
     207              : 
     208          249 :   if (!qual_path_type.has_as_clause ())
     209              :     {
     210            1 :       translated
     211            1 :         = resolve_segments (path.get_mappings ().get_hirid (),
     212              :                             path.get_segments (), 0, translated,
     213            1 :                             path.get_mappings (), path.get_locus (), false);
     214              : 
     215            1 :       return;
     216              :     }
     217              : 
     218              :   // Resolve the trait now
     219          248 :   auto &trait_path_ref = qual_path_type.get_trait ();
     220          248 :   TraitReference *trait_ref = TraitResolver::Resolve (trait_path_ref);
     221          248 :   if (trait_ref->is_error ())
     222              :     return;
     223              : 
     224              :   // get the predicate for the bound
     225          248 :   auto specified_bound
     226              :     = get_predicate_from_bound (qual_path_type.get_trait (),
     227          248 :                                 qual_path_type.get_type (),
     228          248 :                                 BoundPolarity::RegularBound, true);
     229          248 :   if (specified_bound.is_error ())
     230              :     return;
     231              : 
     232              :   // inherit the bound
     233          248 :   root->inherit_bound (specified_bound);
     234              : 
     235              :   // lookup the associated item from the specified bound
     236          248 :   HIR::TypePathSegment &item_seg = path.get_associated_segment ();
     237          248 :   HIR::PathIdentSegment item_seg_identifier = item_seg.get_ident_segment ();
     238          248 :   tl::optional<TyTy::TypeBoundPredicateItem> item
     239          248 :     = specified_bound.lookup_associated_item (item_seg_identifier.to_string ());
     240          248 :   if (!item.has_value ())
     241              :     {
     242            1 :       std::string item_seg_ident_name, rich_msg;
     243            1 :       item_seg_ident_name = qual_path_type.get_trait ().to_string ();
     244            2 :       rich_msg = "not found in `" + item_seg_ident_name + "`";
     245              : 
     246            1 :       rich_location richloc (line_table, item_seg.get_locus ());
     247            1 :       richloc.add_fixit_replace (rich_msg.c_str ());
     248              : 
     249            2 :       rust_error_at (richloc, ErrorCode::E0576,
     250              :                      "cannot find associated type %qs in trait %qs",
     251            1 :                      item_seg_identifier.to_string ().c_str (),
     252              :                      item_seg_ident_name.c_str ());
     253            1 :       return;
     254            1 :     }
     255              : 
     256              :   // Build projection via the predicates own rebasing helper so the
     257              :   // projection's substitutions are populated with the trait-coord args from
     258              :   // the qualified path:
     259              :   //   (<Bar<i32> as Foo<i32>>::A -> Projection Self=Bar<i32>, T=i32)
     260          247 :   TyTy::BaseType *rebased_item = item->get_tyty_for_receiver (root);
     261          247 :   if (auto *proj = rebased_item->try_as<TyTy::ProjectionType> ())
     262          247 :     translated
     263          247 :       = normalize_projection (proj, path.get_locus (), false /*emit errors*/,
     264              :                               false /*unify self*/);
     265              :   else
     266              :     translated = rebased_item;
     267              : 
     268              :   // turbo-fish segment path::<ty>
     269          247 :   if (item_seg.get_type () == HIR::TypePathSegment::SegmentType::GENERIC)
     270              :     {
     271            7 :       auto &generic_seg = static_cast<HIR::TypePathSegmentGeneric &> (item_seg);
     272              : 
     273              :       // turbo-fish segment path::<ty>
     274            7 :       if (generic_seg.has_generic_args ())
     275              :         {
     276            7 :           if (!translated->has_substitutions_defined ())
     277              :             {
     278            0 :               rust_error_at (item_seg.get_locus (),
     279              :                              "substitutions not supported for %s",
     280            0 :                              translated->as_string ().c_str ());
     281            0 :               translated
     282            0 :                 = new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     283            0 :               return;
     284              :             }
     285            7 :           translated
     286            7 :             = SubstMapper::Resolve (translated, path.get_locus (),
     287            7 :                                     &generic_seg.get_generic_args (),
     288            7 :                                     context->regions_from_generic_args (
     289            7 :                                       generic_seg.get_generic_args ()));
     290              : 
     291              :           // unwrap the sweets
     292            7 :           if (auto *proj = translated->try_as<TyTy::ProjectionType> ())
     293            7 :             if (!proj->is_trait_position () && proj->get () != nullptr)
     294            7 :               translated = proj->get ();
     295              :         }
     296              :     }
     297              : 
     298              :   // continue on as a path-in-expression
     299          247 :   bool fully_resolved = path.get_segments ().empty ();
     300          247 :   if (fully_resolved)
     301              :     return;
     302              : 
     303            0 :   translated
     304            0 :     = resolve_segments (path.get_mappings ().get_hirid (), path.get_segments (),
     305            0 :                         0, translated, path.get_mappings (), path.get_locus (),
     306              :                         false);
     307          497 : }
     308              : 
     309              : TyTy::BaseType *
     310        54399 : TypeCheckType::resolve_root_path (HIR::TypePath &path, size_t *offset,
     311              :                                   bool *wasBigSelf)
     312              : {
     313        54399 :   TyTy::BaseType *root_tyty = nullptr;
     314        54399 :   *offset = 0;
     315              : 
     316       107306 :   for (size_t i = 0; i < path.get_num_segments (); i++)
     317              :     {
     318        55856 :       std::unique_ptr<HIR::TypePathSegment> &seg = path.get_segments ().at (i);
     319              : 
     320        55856 :       bool have_more_segments = (path.get_num_segments () - 1 != i);
     321        55856 :       bool is_root = *offset == 0;
     322        55856 :       NodeId ast_node_id = seg->get_mappings ().get_nodeid ();
     323              : 
     324              :       // then lookup the reference_node_id
     325        55856 :       NodeId ref_node_id = UNKNOWN_NODEID;
     326              : 
     327        55856 :       if (seg->is_lang_item ())
     328           50 :         ref_node_id = Analysis::Mappings::get ().get_lang_item_node (
     329           50 :           seg->get_lang_item ());
     330              :       else
     331              :         {
     332        55806 :           auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     333              : 
     334              :           // assign the ref_node_id if we've found something
     335        55806 :           nr_ctx.lookup (ast_node_id, Resolver2_0::Namespace::Types)
     336       110466 :             .map ([&ref_node_id] (NodeId resolved) { ref_node_id = resolved; });
     337              : 
     338              :           // TODO: Should we add a special method to the name resolver to handle
     339              :           // that case? Resolving something in the Types NS when we want to
     340              :           // prioritize builtin types over modules or other conflicting things?
     341       111612 :           if (auto builtin_type_id
     342        55806 :               = Resolver2_0::Builtins::find_builtin_node_id (seg->to_string ()))
     343        28586 :             if (mappings.is_module (ref_node_id))
     344            2 :               ref_node_id = builtin_type_id.value ();
     345              :         }
     346              : 
     347              :       // ref_node_id is the NodeId that the segments refers to.
     348        55856 :       if (ref_node_id == UNKNOWN_NODEID)
     349              :         {
     350         1146 :           if (is_root)
     351              :             {
     352            0 :               rust_error_at (seg->get_locus (),
     353              :                              "unknown reference for resolved name: %qs",
     354            0 :                              seg->to_string ().c_str ());
     355            0 :               return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     356              :             }
     357         1146 :           else if (root_tyty == nullptr)
     358              :             {
     359            1 :               rust_error_at (seg->get_locus (),
     360              :                              "unknown reference for resolved name: %qs",
     361            1 :                              seg->to_string ().c_str ());
     362            1 :               return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     363              :             }
     364              :           return root_tyty;
     365              :         }
     366              : 
     367        54710 :       if (seg->is_ident_only () && seg->to_string () == "Self")
     368         9593 :         *wasBigSelf = true;
     369              : 
     370              :       // node back to HIR
     371        54710 :       tl::optional<HirId> hid = mappings.lookup_node_to_hir (ref_node_id);
     372        54710 :       if (!hid.has_value ())
     373              :         {
     374            0 :           if (is_root)
     375              :             {
     376            0 :               rust_error_at (seg->get_locus (), "789 reverse lookup failure");
     377            0 :               rust_debug_loc (
     378              :                 seg->get_locus (),
     379              :                 "failure with [%s] mappings [%s] ref_node_id [%u]",
     380              :                 seg->to_string ().c_str (),
     381              :                 seg->get_mappings ().as_string ().c_str (), ref_node_id);
     382              : 
     383            0 :               return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     384              :             }
     385              : 
     386              :           return root_tyty;
     387              :         }
     388        54710 :       auto ref = hid.value ();
     389              : 
     390        54710 :       auto seg_is_module = mappings.hir.modules.lookup (ref).has_value ();
     391        54710 :       auto seg_is_crate = mappings.is_local_hirid_crate (ref);
     392        54710 :       if (seg_is_module || seg_is_crate)
     393              :         {
     394              :           // A::B::C::this_is_a_module::D::E::F
     395              :           //          ^^^^^^^^^^^^^^^^
     396              :           //          Currently handling this.
     397          312 :           if (have_more_segments)
     398              :             {
     399          312 :               (*offset)++;
     400          312 :               continue;
     401              :             }
     402              : 
     403              :           // In the case of :
     404              :           // A::B::C::this_is_a_module
     405              :           //          ^^^^^^^^^^^^^^^^
     406              :           // This is an error, we are not expecting a module.
     407            0 :           rust_error_at (seg->get_locus (), "expected value, got module");
     408              : 
     409            0 :           return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     410              :         }
     411              : 
     412        54398 :       TyTy::BaseType *lookup = nullptr;
     413        54398 :       if (!query_type (ref, &lookup))
     414              :         {
     415            1 :           if (is_root || root_tyty == nullptr)
     416              :             {
     417            1 :               rust_error_at (seg->get_locus (),
     418              :                              "failed to resolve type path segment: %qs",
     419            1 :                              seg->to_string ().c_str ());
     420            1 :               return new TyTy::ErrorType (path.get_mappings ().get_hirid ());
     421              :             }
     422              : 
     423              :           return root_tyty;
     424              :         }
     425              : 
     426              :       // if we have a previous segment type
     427        54397 :       if (root_tyty != nullptr)
     428              :         {
     429              :           // if this next segment needs substitution we must apply the
     430              :           // previous type arguments
     431              :           //
     432              :           // such as: GenericStruct::<_>::new(123, 456)
     433            0 :           if (lookup->needs_generic_substitutions ())
     434              :             {
     435            0 :               if (!root_tyty->needs_generic_substitutions ())
     436              :                 {
     437            0 :                   auto used_args_in_prev_segment
     438            0 :                     = GetUsedSubstArgs::From (root_tyty);
     439            0 :                   lookup
     440            0 :                     = SubstMapperInternal::Resolve (lookup,
     441              :                                                     used_args_in_prev_segment);
     442            0 :                 }
     443              :             }
     444              :         }
     445              : 
     446              :       // turbo-fish segment path::<ty>
     447        54397 :       if (seg->is_generic_segment ())
     448              :         {
     449         2126 :           auto &generic_segment
     450         2126 :             = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
     451              : 
     452         2126 :           auto regions = context->regions_from_generic_args (
     453         2126 :             generic_segment.get_generic_args ());
     454         2126 :           lookup = SubstMapper::Resolve (lookup, path.get_locus (),
     455         2126 :                                          &generic_segment.get_generic_args (),
     456              :                                          regions);
     457         2126 :           if (lookup->get_kind () == TyTy::TypeKind::ERROR)
     458            4 :             return new TyTy::ErrorType (seg->get_mappings ().get_hirid ());
     459         2126 :         }
     460        52271 :       else if (lookup->needs_generic_substitutions ())
     461              :         {
     462          186 :           HIR::GenericArgs empty
     463          186 :             = HIR::GenericArgs::create_empty (path.get_locus ());
     464          186 :           lookup
     465          186 :             = SubstMapper::Resolve (lookup, path.get_locus (), &empty,
     466          186 :                                     context->regions_from_generic_args (empty));
     467          186 :         }
     468              : 
     469        54393 :       *offset = *offset + 1;
     470        54393 :       root_tyty = lookup;
     471              : 
     472              :       // this enforces the proper get_segments checks to take place
     473       106988 :       auto *maybe_adt = root_tyty->try_as<const TyTy::ADTType> ();
     474         6144 :       if (maybe_adt && maybe_adt->is_enum ())
     475              :         return root_tyty;
     476              :     }
     477              : 
     478              :   return root_tyty;
     479              : }
     480              : 
     481              : bool
     482          976 : TypeCheckType::resolve_associated_type (const std::string &search,
     483              :                                         TypeCheckBlockContextItem &ctx,
     484              :                                         TyTy::BaseType **result)
     485              : {
     486          976 :   if (ctx.is_trait_block ())
     487              :     {
     488          810 :       HIR::Trait &trait = ctx.get_trait ();
     489          926 :       for (auto &item : trait.get_trait_items ())
     490              :         {
     491          893 :           if (item->get_item_kind () != HIR::TraitItem::TraitItemKind::TYPE)
     492           36 :             continue;
     493              : 
     494          857 :           if (item->trait_identifier () == search)
     495              :             {
     496          777 :               HirId item_id = item->get_mappings ().get_hirid ();
     497          777 :               if (query_type (item_id, result))
     498          976 :                 return true;
     499              :             }
     500              :         }
     501              : 
     502              :       // FIXME
     503              :       // query any parent trait?
     504              : 
     505              :       return false;
     506              :     }
     507              : 
     508              :   // look for any segment in here which matches
     509          166 :   HIR::ImplBlock &block = ctx.get_impl_block ();
     510          209 :   for (auto &item : block.get_impl_items ())
     511              :     {
     512          185 :       if (item->get_impl_item_type () != HIR::ImplItem::TYPE_ALIAS)
     513           26 :         continue;
     514              : 
     515          159 :       if (item->get_impl_item_name () == search)
     516              :         {
     517          142 :           HirId item_id = item->get_impl_mappings ().get_hirid ();
     518          142 :           if (query_type (item_id, result))
     519          976 :             return true;
     520              :         }
     521              :     }
     522              : 
     523              :   return false;
     524              : }
     525              : 
     526              : bool
     527         1147 : TypeCheckType::try_resolve_contextual_self_associated_type (
     528              :   const HIR::TypePathSegment &segment, bool first_segment,
     529              :   bool ty_seg_is_big_self, TyTy::BaseType **result)
     530              : {
     531         1147 :   if (!first_segment || !ty_seg_is_big_self
     532         1147 :       || !context->block_context ().is_in_context ())
     533              :     return false;
     534              : 
     535          976 :   TypeCheckBlockContextItem ctx = context->block_context ().peek ();
     536          976 :   return resolve_associated_type (segment.to_string (), ctx, result);
     537              : }
     538              : 
     539              : TyTy::BaseType *
     540         1148 : TypeCheckType::resolve_segments (
     541              :   HirId expr_id, std::vector<std::unique_ptr<HIR::TypePathSegment>> &segments,
     542              :   size_t offset, TyTy::BaseType *tyseg,
     543              :   const Analysis::NodeMapping &expr_mappings, location_t expr_locus,
     544              :   bool tySegIsBigSelf)
     545              : {
     546         2292 :   for (size_t i = offset; i < segments.size (); i++)
     547              :     {
     548         1147 :       auto &seg = segments.at (i);
     549         1147 :       const auto &ident_segment = seg->get_ident_segment ();
     550         1147 :       bool first_segment = i == offset;
     551         1147 :       TyTy::BaseType *associated_type = nullptr;
     552              : 
     553         1147 :       bool selfResolveOk
     554         1147 :         = try_resolve_contextual_self_associated_type (*seg, first_segment,
     555              :                                                        tySegIsBigSelf,
     556              :                                                        &associated_type);
     557         1147 :       if (selfResolveOk)
     558              :         {
     559          919 :           tyseg = associated_type;
     560              :         }
     561              :       else
     562              :         {
     563          228 :           if (auto adt = tyseg->try_as<TyTy::ADTType> ())
     564              :             {
     565           16 :               if (adt->is_enum ())
     566              :                 {
     567            2 :                   rich_location r (line_table, seg->get_locus ());
     568            2 :                   text_range_label label ("enum declared here");
     569              : 
     570            2 :                   auto item_lookup = mappings.lookup_defid (adt->get_id ());
     571            2 :                   if (item_lookup.has_value ())
     572              :                     {
     573            2 :                       auto &item = item_lookup.value ();
     574            2 :                       r.add_range (item->get_locus (), SHOW_RANGE_WITHOUT_CARET,
     575              :                                    &label);
     576              :                     }
     577              : 
     578            2 :                   TyTy::VariantDef *v;
     579            4 :                   if (adt->lookup_variant (ident_segment.to_string (), &v))
     580              :                     {
     581            2 :                       rust_error_at (
     582              :                         r, ErrorCode::E0573,
     583              :                         "expected type, found variant of %<%s::%s%>",
     584            4 :                         adt->get_name ().c_str (),
     585            2 :                         v->get_identifier ().c_str ());
     586            2 :                       return new TyTy::ErrorType (expr_id);
     587              :                     }
     588            2 :                 }
     589              :             }
     590              : 
     591          226 :           auto result = TypePathProbe::Probe (tyseg, ident_segment);
     592          226 :           auto &candidates = result.type_candidates;
     593              : 
     594          226 :           if (candidates.empty ())
     595              :             {
     596            2 :               rust_error_at (seg->get_locus (),
     597              :                              "failed to resolve path segment %<%s%> as a type",
     598            1 :                              ident_segment.to_string ().c_str ());
     599            1 :               return new TyTy::ErrorType (expr_id);
     600              :             }
     601              : 
     602          225 :           if (candidates.size () > 1)
     603              :             {
     604            0 :               ReportMultipleCandidateError::Report (candidates, ident_segment,
     605              :                                                     seg->get_locus ());
     606            0 :               return new TyTy::ErrorType (expr_id);
     607              :             }
     608              : 
     609          225 :           auto &candidate = *candidates.begin ();
     610          225 :           tyseg = candidate.ty;
     611          226 :         }
     612              : 
     613         1144 :       if (seg->is_generic_segment ())
     614              :         {
     615           20 :           auto &generic_segment
     616           20 :             = static_cast<HIR::TypePathSegmentGeneric &> (*seg);
     617              : 
     618           20 :           std::vector<TyTy::Region> regions;
     619            0 :           for (auto &lifetime :
     620           20 :                generic_segment.get_generic_args ().get_lifetime_args ())
     621              :             {
     622            0 :               auto region = context->lookup_and_resolve_lifetime (lifetime);
     623            0 :               if (!region.has_value ())
     624              :                 {
     625            0 :                   rust_error_at (lifetime.get_locus (),
     626              :                                  "failed to resolve lifetime");
     627            0 :                   return new TyTy::ErrorType (expr_id);
     628              :                 }
     629            0 :               regions.push_back (region.value ());
     630              :             }
     631              : 
     632           20 :           tyseg = SubstMapper::Resolve (tyseg, expr_locus,
     633           20 :                                         &generic_segment.get_generic_args (),
     634              :                                         regions);
     635           20 :           if (tyseg->get_kind () == TyTy::TypeKind::ERROR)
     636            0 :             return new TyTy::ErrorType (expr_id);
     637           20 :         }
     638              :     }
     639              : 
     640              :   return tyseg;
     641              : }
     642              : 
     643              : void
     644          227 : TypeCheckType::visit (HIR::TraitObjectType &type)
     645              : {
     646          227 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     647          467 :   for (auto &bound : type.get_type_param_bounds ())
     648              :     {
     649              :       // TODO: here we need to check if there are additional bounds that aren't
     650              :       // auto traits. this is an error. for example, `dyn A + Sized + Sync` is
     651              :       // okay, because Sized and Sync are both auto traits but `dyn A + Copy +
     652              :       // Clone` is not okay and should error out.
     653              : 
     654          240 :       if (bound->get_bound_type ()
     655              :           != HIR::TypeParamBound::BoundType::TRAITBOUND)
     656            7 :         continue;
     657              : 
     658          233 :       HIR::TypeParamBound &b = *bound.get ();
     659          233 :       HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
     660              : 
     661          233 :       auto binder_pin = context->push_lifetime_binder ();
     662          240 :       for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
     663              :         {
     664            7 :           context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
     665              :         }
     666              : 
     667          233 :       TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
     668              :         trait_bound.get_path (),
     669          233 :         tl::nullopt /*this will setup a PLACEHOLDER for self*/);
     670              : 
     671          233 :       if (!predicate.is_error ()
     672          233 :           && predicate.is_object_safe (true, type.get_locus ()))
     673          231 :         specified_bounds.push_back (std::move (predicate));
     674          233 :     }
     675              : 
     676              :   // The dyn_drop lint: a trait object with a `Drop` bound is pointless, as
     677              :   // values are dropped automatically regardless of the bound.
     678          227 :   if (flag_unused_check_2_0)
     679            1 :     if (auto drop = mappings.lookup_lang_item (LangItem::Kind::DROP))
     680            2 :       for (auto &bound : specified_bounds)
     681            2 :         if (bound.get_id () == drop.value ())
     682            1 :           rust_warning_at (type.get_locus (), OPT_Wunused,
     683              :                            "this trait object has a %<Drop%> bound, which has "
     684              :                            "no effect");
     685              : 
     686          227 :   RustIdent ident{CanonicalPath::create_empty (), type.get_locus ()};
     687          227 :   translated
     688          227 :     = new TyTy::DynamicObjectType (type.get_mappings ().get_hirid (), ident,
     689          454 :                                    std::move (specified_bounds));
     690          227 : }
     691              : 
     692              : void
     693            5 : TypeCheckType::visit (HIR::ParenthesisedType &type)
     694              : {
     695              :   // I think this really needs to be a tuple.. but will sort that out when we
     696              :   // fix the parser issue
     697            5 :   translated = TypeCheckType::Resolve (type.get_type_in_parens ());
     698            5 : }
     699              : 
     700              : void
     701          800 : TypeCheckType::visit (HIR::ArrayType &type)
     702              : {
     703          800 :   auto element_type = TypeCheckType::Resolve (type.get_element_type ());
     704          800 :   context->push_const_context ();
     705          800 :   auto capacity_type = TypeCheckExpr::Resolve (type.get_size_expr ());
     706          799 :   context->pop_const_context ();
     707              : 
     708          799 :   if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
     709            0 :     return;
     710              : 
     711          799 :   TyTy::BaseType *expected_ty = nullptr;
     712          799 :   bool ok = context->lookup_builtin ("usize", &expected_ty);
     713          799 :   rust_assert (ok);
     714              : 
     715          799 :   TyTy::BaseConstType *const_type = nullptr;
     716          799 :   if (capacity_type->get_kind () == TyTy::TypeKind::CONST)
     717              :     {
     718           43 :       const_type = capacity_type->as_const_type ();
     719              : 
     720           86 :       unify_site (type.get_size_expr ().get_mappings ().get_hirid (),
     721           43 :                   TyTy::TyWithLocation (expected_ty),
     722              :                   TyTy::TyWithLocation (const_type->get_specified_type (),
     723           43 :                                         type.get_size_expr ().get_locus ()),
     724           43 :                   type.get_size_expr ().get_locus ());
     725              :     }
     726              :   else
     727              :     {
     728          756 :       HirId size_id = type.get_size_expr ().get_mappings ().get_hirid ();
     729          756 :       TyTy::BaseType *result
     730         1512 :         = unify_site (size_id, TyTy::TyWithLocation (expected_ty),
     731              :                       TyTy::TyWithLocation (capacity_type,
     732          756 :                                             type.get_size_expr ().get_locus ()),
     733          756 :                       type.get_size_expr ().get_locus ());
     734              : 
     735          756 :       if (result->is<TyTy::ErrorType> ())
     736            2 :         const_type = new TyTy::ConstErrorType (expected_ty, size_id, size_id);
     737              :       else
     738              :         {
     739          754 :           auto ctx = Compile::Context::get ();
     740          754 :           tree capacity_expr
     741          754 :             = Compile::HIRCompileBase::query_compile_const_expr (
     742              :               ctx, capacity_type, type.get_size_expr ());
     743              : 
     744          754 :           const_type = new TyTy::ConstValueType (capacity_expr, expected_ty,
     745         1508 :                                                  size_id, size_id);
     746              :         }
     747              : 
     748          756 :       context->insert_type (type.get_size_expr ().get_mappings (),
     749          756 :                             const_type->as_base_type ());
     750              :     }
     751              : 
     752          799 :   translated
     753          799 :     = new TyTy::ArrayType (type.get_mappings ().get_hirid (), type.get_locus (),
     754              :                            TyTy::TyVar (
     755          799 :                              const_type->as_base_type ()->get_ref ()),
     756         2397 :                            TyTy::TyVar (element_type->get_ref ()));
     757              : }
     758              : 
     759              : void
     760          916 : TypeCheckType::visit (HIR::SliceType &type)
     761              : {
     762          916 :   TyTy::BaseType *base = TypeCheckType::Resolve (type.get_element_type ());
     763          916 :   translated
     764          916 :     = new TyTy::SliceType (type.get_mappings ().get_hirid (), type.get_locus (),
     765         1832 :                            TyTy::TyVar (base->get_ref ()));
     766          916 : }
     767              : void
     768         4717 : TypeCheckType::visit (HIR::ReferenceType &type)
     769              : {
     770         4717 :   TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
     771         4717 :   rust_assert (type.has_lifetime ());
     772         4717 :   auto region = context->lookup_and_resolve_lifetime (type.get_lifetime ());
     773         4717 :   if (!region.has_value ())
     774              :     {
     775            2 :       rust_error_at (type.get_locus (), "failed to resolve lifetime");
     776            2 :       translated = new TyTy::ErrorType (type.get_mappings ().get_hirid ());
     777            2 :       return;
     778              :     }
     779        14145 :   translated = new TyTy::ReferenceType (type.get_mappings ().get_hirid (),
     780         4715 :                                         TyTy::TyVar (base->get_ref ()),
     781         9430 :                                         type.get_mut (), region.value ());
     782              : }
     783              : 
     784              : void
     785         7116 : TypeCheckType::visit (HIR::RawPointerType &type)
     786              : {
     787         7116 :   TyTy::BaseType *base = TypeCheckType::Resolve (type.get_base_type ());
     788         7116 :   translated
     789        14232 :     = new TyTy::PointerType (type.get_mappings ().get_hirid (),
     790         7116 :                              TyTy::TyVar (base->get_ref ()), type.get_mut ());
     791         7116 : }
     792              : 
     793              : void
     794          227 : TypeCheckType::visit (HIR::InferredType &type)
     795              : {
     796          454 :   translated = new TyTy::InferType (type.get_mappings ().get_hirid (),
     797              :                                     TyTy::InferType::InferTypeKind::GENERAL,
     798              :                                     TyTy::InferType::TypeHint::Default (),
     799          454 :                                     type.get_locus ());
     800          227 : }
     801              : 
     802              : void
     803          198 : TypeCheckType::visit (HIR::NeverType &type)
     804              : {
     805          198 :   TyTy::BaseType *lookup = nullptr;
     806          198 :   bool ok = context->lookup_builtin ("!", &lookup);
     807          198 :   rust_assert (ok);
     808              : 
     809          198 :   translated = lookup->clone ();
     810          198 : }
     811              : 
     812              : void
     813           41 : TypeCheckType::visit (HIR::ImplTraitType &type)
     814              : {
     815           41 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
     816           85 :   for (auto &bound : type.get_type_param_bounds ())
     817              :     {
     818           44 :       if (bound->get_bound_type ()
     819              :           != HIR::TypeParamBound::BoundType::TRAITBOUND)
     820            2 :         continue;
     821              : 
     822           42 :       HIR::TypeParamBound &b = *bound.get ();
     823           42 :       HIR::TraitBound &trait_bound = static_cast<HIR::TraitBound &> (b);
     824              : 
     825           42 :       auto binder_pin = context->push_lifetime_binder ();
     826           42 :       for (auto &lifetime_param : trait_bound.get_for_lifetimes ())
     827              :         {
     828            0 :           context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
     829              :         }
     830              : 
     831           42 :       TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
     832              :         trait_bound.get_path (),
     833           42 :         tl::nullopt /*this will setup a PLACEHOLDER for self*/);
     834              : 
     835           42 :       if (!predicate.is_error ()
     836           42 :           && predicate.is_object_safe (true, type.get_locus ()))
     837           42 :         specified_bounds.push_back (std::move (predicate));
     838           42 :     }
     839              : 
     840          123 :   translated = new TyTy::OpaqueType (type.get_locus (),
     841           41 :                                      type.get_mappings ().get_hirid (),
     842           41 :                                      specified_bounds);
     843           41 : }
     844              : 
     845              : TyTy::ParamType *
     846        12924 : TypeResolveGenericParam::Resolve (HIR::GenericParam &param,
     847              :                                   bool resolve_trait_bounds, bool apply_sized)
     848              : {
     849        12924 :   TypeResolveGenericParam resolver (apply_sized, resolve_trait_bounds);
     850        12924 :   switch (param.get_kind ())
     851              :     {
     852        12924 :     case HIR::GenericParam::GenericKind::TYPE:
     853        12924 :       resolver.visit (static_cast<HIR::TypeParam &> (param));
     854        12924 :       break;
     855              : 
     856            0 :     case HIR::GenericParam::GenericKind::CONST:
     857            0 :       resolver.visit (static_cast<HIR::ConstGenericParam &> (param));
     858            0 :       break;
     859              : 
     860            0 :     case HIR::GenericParam::GenericKind::LIFETIME:
     861            0 :       resolver.visit (static_cast<HIR::LifetimeParam &> (param));
     862            0 :       break;
     863              :     }
     864        12924 :   return resolver.resolved;
     865        12924 : }
     866              : 
     867              : void
     868         8044 : TypeResolveGenericParam::ApplyAnyTraitBounds (HIR::TypeParam &param,
     869              :                                               TyTy::ParamType *pty)
     870              : {
     871         8044 :   TypeResolveGenericParam resolver (true, true);
     872         8044 :   resolver.apply_trait_bounds (param, pty);
     873         8044 : }
     874              : 
     875              : void
     876            0 : TypeResolveGenericParam::visit (HIR::LifetimeParam &param)
     877              : {
     878              :   // nothing to do
     879            0 : }
     880              : 
     881              : void
     882            0 : TypeResolveGenericParam::visit (HIR::ConstGenericParam &param)
     883              : {
     884              :   // TODO
     885            0 : }
     886              : 
     887              : void
     888        12924 : TypeResolveGenericParam::visit (HIR::TypeParam &param)
     889              : {
     890        12924 :   if (param.has_type ())
     891          408 :     TypeCheckType::Resolve (param.get_type ());
     892              : 
     893        25848 :   resolved = new TyTy::ParamType (param.get_type_representation ().as_string (),
     894              :                                   param.get_locus (),
     895        12924 :                                   param.get_mappings ().get_hirid (),
     896        38772 :                                   param.get_mappings ().get_hirid (), {});
     897              : 
     898        12924 :   if (resolve_trait_bounds)
     899         4986 :     apply_trait_bounds (param, resolved);
     900        12924 : }
     901              : 
     902              : void
     903        13030 : TypeResolveGenericParam::apply_trait_bounds (HIR::TypeParam &param,
     904              :                                              TyTy::ParamType *pty)
     905              : {
     906        13030 :   std::unique_ptr<HIR::Type> implicit_self_bound = nullptr;
     907        13030 :   if (param.has_type_param_bounds ())
     908              :     {
     909              :       // We need two possible parameter types. One with no Bounds and one with
     910              :       // the bounds. the Self type for the bounds cannot itself contain the
     911              :       // bounds otherwise it will be a trait cycle
     912         1380 :       HirId implicit_id = mappings.get_next_hir_id ();
     913         1380 :       TyTy::ParamType *p
     914         1380 :         = new TyTy::ParamType (param.get_type_representation ().as_string (),
     915              :                                param.get_locus (), implicit_id,
     916              :                                pty->get_decl_id (),
     917         2760 :                                {} /*empty specified bounds*/);
     918         1380 :       context->insert_implicit_type (implicit_id, p);
     919              : 
     920              :       // generate an implicit HIR Type we can apply to the predicate
     921         1380 :       Analysis::NodeMapping mappings (param.get_mappings ().get_crate_num (),
     922         1380 :                                       param.get_mappings ().get_nodeid (),
     923              :                                       implicit_id,
     924         1380 :                                       param.get_mappings ().get_local_defid ());
     925         2760 :       implicit_self_bound = std::make_unique<HIR::TypePath> (
     926         4140 :         HIR::TypePath (mappings, {}, BUILTINS_LOCATION, false));
     927              :     }
     928              : 
     929        13030 :   std::map<DefId, std::vector<TyTy::TypeBoundPredicate>> predicates;
     930              : 
     931              :   // https://doc.rust-lang.org/std/marker/trait.Sized.html
     932              :   // All type parameters have an implicit bound of Sized. The special syntax
     933              :   // ?Sized can be used to remove this bound if it’s not appropriate.
     934              :   //
     935              :   // We can only do this when we are not resolving the implicit Self for Sized
     936              :   // itself
     937        13030 :   if (apply_sized)
     938              :     {
     939         8773 :       TyTy::TypeBoundPredicate sized_predicate
     940         8773 :         = get_marker_predicate (LangItem::Kind::SIZED, param.get_locus ());
     941              : 
     942        17546 :       predicates[sized_predicate.get_id ()] = {sized_predicate};
     943         8773 :     }
     944              : 
     945              :   // resolve the bounds
     946        13030 :   if (param.has_type_param_bounds ())
     947              :     {
     948         2824 :       for (auto &bound : param.get_type_param_bounds ())
     949              :         {
     950         1444 :           switch (bound->get_bound_type ())
     951              :             {
     952         1444 :             case HIR::TypeParamBound::BoundType::TRAITBOUND:
     953         1444 :               {
     954         1444 :                 HIR::TraitBound &b = static_cast<HIR::TraitBound &> (*bound);
     955              : 
     956         1444 :                 TyTy::TypeBoundPredicate predicate = get_predicate_from_bound (
     957              :                   b.get_path (),
     958              :                   tl::optional<std::reference_wrapper<HIR::Type>> (
     959         1444 :                     std::ref (*implicit_self_bound)),
     960         1444 :                   b.get_polarity ());
     961         1444 :                 if (!predicate.is_error ())
     962              :                   {
     963         1443 :                     switch (predicate.get_polarity ())
     964              :                       {
     965          534 :                       case BoundPolarity::AntiBound:
     966          534 :                         {
     967          534 :                           bool found = predicates.find (predicate.get_id ())
     968          534 :                                        != predicates.end ();
     969          534 :                           if (found)
     970          534 :                             predicates.erase (predicate.get_id ());
     971              :                           else
     972              :                             {
     973              :                               // emit error message
     974            0 :                               rich_location r (line_table, b.get_locus ());
     975            0 :                               r.add_range (predicate.get ()->get_locus ());
     976            0 :                               rust_error_at (
     977              :                                 r, "antibound for %s is not applied here",
     978            0 :                                 predicate.get ()->get_name ().c_str ());
     979            0 :                             }
     980              :                         }
     981              :                         break;
     982              : 
     983          909 :                       default:
     984          909 :                         {
     985          909 :                           if (predicates.find (predicate.get_id ())
     986          909 :                               == predicates.end ())
     987              :                             {
     988          900 :                               predicates[predicate.get_id ()] = {};
     989              :                             }
     990          909 :                           predicates[predicate.get_id ()].push_back (predicate);
     991              :                         }
     992          909 :                         break;
     993              :                       }
     994              :                   }
     995         1444 :               }
     996         1444 :               break;
     997              : 
     998              :             default:
     999              :               break;
    1000              :             }
    1001              :         }
    1002              :     }
    1003              : 
    1004              :   // now to flat map the specified_bounds into the raw specified predicates
    1005        13030 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
    1006        22169 :   for (auto it = predicates.begin (); it != predicates.end (); it++)
    1007              :     {
    1008        18287 :       for (const auto &predicate : it->second)
    1009              :         {
    1010         9148 :           specified_bounds.push_back (predicate);
    1011              :         }
    1012              :     }
    1013              : 
    1014              :   // inherit them
    1015        13030 :   pty->inherit_bounds (specified_bounds);
    1016        13030 : }
    1017              : 
    1018              : void
    1019            2 : ResolveWhereClauseItem::Resolve (HIR::WhereClauseItem &item,
    1020              :                                  TyTy::RegionConstraints &region_constraints)
    1021              : {
    1022            2 :   ResolveWhereClauseItem resolver (region_constraints);
    1023              : 
    1024            2 :   auto binder_pin = resolver.context->push_lifetime_binder ();
    1025              : 
    1026            2 :   switch (item.get_item_type ())
    1027              :     {
    1028            2 :     case HIR::WhereClauseItem::LIFETIME:
    1029            2 :       resolver.visit (static_cast<HIR::LifetimeWhereClauseItem &> (item));
    1030            2 :       break;
    1031              : 
    1032            0 :     case HIR::WhereClauseItem::TYPE_BOUND:
    1033            0 :       resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (item));
    1034            0 :       break;
    1035              :     }
    1036            2 : }
    1037              : 
    1038              : void
    1039        60444 : ResolveWhereClauseItem::Resolve (HIR::WhereClause &clause,
    1040              :                                  TyTy::RegionConstraints &region_constraints)
    1041              : {
    1042        60444 :   ResolveWhereClauseItem resolver (region_constraints);
    1043              : 
    1044        60444 :   class PlainTypePath : public HIR::HIRTypeVisitor
    1045              :   {
    1046              :   public:
    1047              :     bool matches = false;
    1048              : 
    1049            0 :     void visit (HIR::TypePathSegmentFunction &segment) override {}
    1050            0 :     void visit (HIR::QualifiedPathInType &path) override {}
    1051            0 :     void visit (HIR::TraitBound &bound) override {}
    1052            0 :     void visit (HIR::ImplTraitType &type) override {}
    1053            0 :     void visit (HIR::TraitObjectType &type) override {}
    1054            0 :     void visit (HIR::ParenthesisedType &type) override {}
    1055            0 :     void visit (HIR::TupleType &type) override {}
    1056            0 :     void visit (HIR::NeverType &type) override {}
    1057            0 :     void visit (HIR::RawPointerType &type) override {}
    1058            0 :     void visit (HIR::ReferenceType &type) override {}
    1059            0 :     void visit (HIR::ArrayType &type) override {}
    1060            0 :     void visit (HIR::SliceType &type) override {}
    1061            0 :     void visit (HIR::InferredType &type) override {}
    1062            0 :     void visit (HIR::BareFunctionType &type) override {}
    1063              : 
    1064          684 :     void visit (HIR::TypePath &path) override
    1065              :     {
    1066          684 :       bool is_single = path.get_segments ().size () == 1;
    1067          684 :       bool final_seg_is_reg
    1068          684 :         = path.get_final_segment ().get_type () == HIR::TypePathSegment::REG;
    1069              : 
    1070          684 :       matches = is_single && final_seg_is_reg;
    1071          684 :     }
    1072              :   };
    1073              : 
    1074        60444 :   resolver.defer_bindings = true;
    1075        61130 :   for (auto &item : clause.get_items ())
    1076          686 :     if (item->get_item_type () == HIR::WhereClauseItem::TYPE_BOUND)
    1077              :       {
    1078          684 :         auto &bound = static_cast<HIR::TypeBoundWhereClauseItem &> (*item);
    1079          684 :         PlainTypePath plain;
    1080          684 :         bound.get_bound_type ().accept_vis (plain);
    1081          684 :         if (plain.matches)
    1082          676 :           resolver.visit (bound);
    1083              :       }
    1084              : 
    1085        60444 :   resolver.defer_bindings = false;
    1086        60444 :   resolver.complete_bindings = true;
    1087        61130 :   for (auto &item : clause.get_items ())
    1088              :     {
    1089          686 :       if (item->get_item_type () == HIR::WhereClauseItem::TYPE_BOUND)
    1090          684 :         resolver.visit (static_cast<HIR::TypeBoundWhereClauseItem &> (*item));
    1091              :       else
    1092            2 :         Resolve (*item, region_constraints);
    1093              :     }
    1094        60444 : }
    1095              : 
    1096              : void
    1097            2 : ResolveWhereClauseItem::visit (HIR::LifetimeWhereClauseItem &item)
    1098              : {
    1099            2 :   auto lhs = context->lookup_and_resolve_lifetime (item.get_lifetime ());
    1100            2 :   if (!lhs.has_value ())
    1101              :     {
    1102            0 :       rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
    1103              :     }
    1104            4 :   for (auto &lifetime : item.get_lifetime_bounds ())
    1105              :     {
    1106            2 :       auto rhs_i = context->lookup_and_resolve_lifetime (lifetime);
    1107            2 :       if (!rhs_i.has_value ())
    1108              :         {
    1109            0 :           rust_error_at (UNKNOWN_LOCATION, "failed to resolve lifetime");
    1110              :         }
    1111            2 :       region_constraints.region_region.emplace_back (lhs.value (),
    1112              :                                                      rhs_i.value ());
    1113              :     }
    1114            2 : }
    1115              : 
    1116              : void
    1117         1360 : ResolveWhereClauseItem::visit (HIR::TypeBoundWhereClauseItem &item)
    1118              : {
    1119         1360 :   auto binder_pin = context->push_lifetime_binder ();
    1120         1360 :   if (item.has_for_lifetimes ())
    1121              :     {
    1122           28 :       for (auto &lifetime_param : item.get_for_lifetimes ())
    1123              :         {
    1124           14 :           context->intern_and_insert_lifetime (lifetime_param.get_lifetime ());
    1125              :         }
    1126              :     }
    1127              : 
    1128         1360 :   auto &binding_type_path = item.get_bound_type ();
    1129         1360 :   TyTy::BaseType *binding
    1130         1360 :     = TypeCheckType::Resolve (binding_type_path,
    1131              :                               TypeCheckType::ResolutionMode::CANONICAL);
    1132              : 
    1133         1360 :   if (defer_bindings && binding->get_kind () != TyTy::TypeKind::PARAM)
    1134            1 :     return;
    1135              : 
    1136              :   // FIXME double check there might be a trait cycle here see TypeParam handling
    1137              : 
    1138         1359 :   std::vector<TyTy::TypeBoundPredicate> specified_bounds;
    1139         2718 :   for (auto &bound : item.get_type_param_bounds ())
    1140              :     {
    1141         1359 :       switch (bound->get_bound_type ())
    1142              :         {
    1143         1351 :         case HIR::TypeParamBound::BoundType::TRAITBOUND:
    1144         1351 :           {
    1145         1351 :             auto *b = static_cast<HIR::TraitBound *> (bound.get ());
    1146              : 
    1147         1351 :             TyTy::TypeBoundPredicate predicate
    1148         1351 :               = get_predicate_from_bound (b->get_path (), binding_type_path,
    1149              :                                           BoundPolarity::RegularBound, false,
    1150         1351 :                                           false, defer_bindings);
    1151         1351 :             if (!predicate.is_error ())
    1152         1351 :               specified_bounds.push_back (std::move (predicate));
    1153         1351 :           }
    1154         1351 :           break;
    1155            8 :         case HIR::TypeParamBound::BoundType::LIFETIME:
    1156            8 :           {
    1157            8 :             if (defer_bindings)
    1158              :               break;
    1159            8 :             if (auto param = binding->try_as<TyTy::ParamType> ())
    1160              :               {
    1161            4 :                 auto *b = static_cast<HIR::Lifetime *> (bound.get ());
    1162            4 :                 auto region = context->lookup_and_resolve_lifetime (*b);
    1163            4 :                 if (!region.has_value ())
    1164              :                   {
    1165            0 :                     rust_error_at (UNKNOWN_LOCATION,
    1166              :                                    "failed to resolve lifetime");
    1167              :                   }
    1168            4 :                 region_constraints.type_region.emplace_back (param,
    1169              :                                                              region.value ());
    1170              :               }
    1171              :           }
    1172            4 :           break;
    1173              : 
    1174              :         default:
    1175              :           break;
    1176              :         }
    1177              :     }
    1178              : 
    1179         2710 :   for (const auto &predicate : specified_bounds)
    1180              :     {
    1181         1351 :       bool replaced = false;
    1182         1351 :       if (complete_bindings)
    1183              :         {
    1184         1758 :           for (auto &bound : binding->get_specified_bounds ())
    1185              :             {
    1186         3270 :               if (bound.get_id () == predicate.get_id ()
    1187          671 :                   && bound.get_locus () == predicate.get_locus ())
    1188              :                 {
    1189          557 :                   bound = predicate;
    1190          557 :                   replaced = true;
    1191          557 :                   break;
    1192              :                 }
    1193              :             }
    1194              :         }
    1195              : 
    1196          557 :       if (!replaced)
    1197          794 :         binding->inherit_bound (predicate);
    1198              :     }
    1199         1360 : }
    1200              : 
    1201              : } // namespace Resolver
    1202              : } // namespace Rust
        

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