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

Generated by: LCOV version 2.4-beta

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