LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-implitem.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 93.0 % 401 373
Test Date: 2026-09-19 16:22:48 Functions: 100.0 % 19 19
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-implitem.h"
      20              : #include "rust-canonical-path.h"
      21              : #include "rust-diagnostics.h"
      22              : #include "rust-hir-full-decls.h"
      23              : #include "rust-hir-pattern.h"
      24              : #include "rust-hir-type-check-base.h"
      25              : #include "rust-hir-type-check-intrinsic.h"
      26              : #include "rust-hir-type-check-type.h"
      27              : #include "rust-hir-type-check-expr.h"
      28              : #include "rust-hir-type-check-pattern.h"
      29              : #include "rust-rib.h"
      30              : #include "rust-type-util.h"
      31              : #include "rust-tyty.h"
      32              : #include "rust-finalized-name-resolution-context.h"
      33              : 
      34              : namespace Rust {
      35              : namespace Resolver {
      36              : 
      37         2689 : TypeCheckTopLevelExternItem::TypeCheckTopLevelExternItem (
      38              :   const HIR::ExternBlock &parent)
      39         2689 :   : TypeCheckBase (), parent (parent)
      40         2689 : {}
      41              : 
      42              : TyTy::BaseType *
      43         2742 : TypeCheckTopLevelExternItem::Resolve (HIR::ExternalItem &item,
      44              :                                       const HIR::ExternBlock &parent)
      45              : {
      46              :   // is it already resolved?
      47         2742 :   auto context = TypeCheckContext::get ();
      48         2742 :   TyTy::BaseType *resolved = nullptr;
      49         2742 :   bool already_resolved
      50         2742 :     = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
      51         2742 :   if (already_resolved)
      52           53 :     return resolved;
      53              : 
      54         2689 :   TypeCheckTopLevelExternItem resolver (parent);
      55         2689 :   item.accept_vis (resolver);
      56         2689 :   return resolver.resolved;
      57         2689 : }
      58              : 
      59              : void
      60            1 : TypeCheckTopLevelExternItem::visit (HIR::ExternalStaticItem &item)
      61              : {
      62            1 :   TyTy::BaseType *actual_type = TypeCheckType::Resolve (item.get_item_type ());
      63              : 
      64            1 :   context->insert_type (item.get_mappings (), actual_type);
      65            1 :   resolved = actual_type;
      66            1 : }
      67              : 
      68              : void
      69         2685 : TypeCheckTopLevelExternItem::visit (HIR::ExternalFunctionItem &function)
      70              : {
      71         2685 :   auto binder_pin = context->push_clean_lifetime_resolver ();
      72              : 
      73         2685 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
      74         2685 :   if (function.has_generics ())
      75              :     {
      76         1073 :       resolve_generic_params (HIR::Item::ItemKind::Function,
      77              :                               function.get_locus (),
      78         1073 :                               function.get_generic_params (), substitutions,
      79         1073 :                               true /*is_foreign*/, parent.get_abi ());
      80              :     }
      81              : 
      82         2685 :   TyTy::RegionConstraints region_constraints;
      83         2685 :   ResolveWhereClauseItem::Resolve (function.get_where_clause (),
      84              :                                    region_constraints);
      85              : 
      86         2685 :   TyTy::BaseType *ret_type = nullptr;
      87         2685 :   if (!function.has_return_type ())
      88         1276 :     ret_type = TyTy::TupleType::get_unit_type ();
      89              :   else
      90              :     {
      91         1409 :       auto resolved = TypeCheckType::Resolve (function.get_return_type ());
      92         1409 :       if (resolved == nullptr)
      93              :         {
      94            0 :           rust_error_at (function.get_locus (),
      95              :                          "failed to resolve return type");
      96            0 :           return;
      97              :         }
      98              : 
      99         1409 :       ret_type = resolved->clone ();
     100         1409 :       ret_type->set_ref (
     101         1409 :         function.get_return_type ().get_mappings ().get_hirid ());
     102              :     }
     103              : 
     104         2685 :   std::vector<TyTy::FnParam> params;
     105         5778 :   for (auto &param : function.get_function_params ())
     106              :     {
     107              :       // get the name as well required for later on
     108         3093 :       auto param_tyty = TypeCheckType::Resolve (param.get_type ());
     109              : 
     110              :       // these are implicit mappings and not used
     111         3093 :       auto crate_num = mappings.get_current_crate ();
     112         6186 :       Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
     113         3093 :                                      mappings.get_next_hir_id (crate_num),
     114         3093 :                                      UNKNOWN_LOCAL_DEFID);
     115              : 
     116         3093 :       auto param_pattern = std::make_unique<HIR::IdentifierPattern> (
     117         3093 :         HIR::IdentifierPattern (mapping, param.get_param_name (),
     118              :                                 UNDEF_LOCATION, false, Mutability::Imm,
     119         6186 :                                 std::unique_ptr<HIR::Pattern> (nullptr)));
     120              : 
     121         3093 :       params.emplace_back (std::move (param_pattern), param_tyty);
     122              : 
     123         3093 :       context->insert_type (param.get_mappings (), param_tyty);
     124              : 
     125              :       // FIXME do we need error checking for patterns here?
     126              :       // see https://github.com/Rust-GCC/gccrs/issues/995
     127         3093 :     }
     128              : 
     129         2685 :   uint8_t flags = TyTy::FnType::FNTYPE_IS_EXTERN_FLAG;
     130         2685 :   if (function.is_variadic ())
     131              :     {
     132          887 :       flags |= TyTy::FnType::FNTYPE_IS_VARIADIC_FLAG;
     133          887 :       if (parent.get_abi () != Rust::ABI::C)
     134              :         {
     135            1 :           rust_error_at (
     136              :             function.get_locus (), ErrorCode::E0045,
     137              :             "C-variadic function must have C or cdecl calling convention");
     138              :         }
     139              :     }
     140              : 
     141         2685 :   RustIdent ident{
     142         5370 :     CanonicalPath::new_seg (function.get_mappings ().get_nodeid (),
     143         2685 :                             function.get_item_name ().as_string ()),
     144         2685 :     function.get_locus ()};
     145              : 
     146         2685 :   auto fnType = new TyTy::FnType (
     147         2685 :     function.get_mappings ().get_hirid (),
     148         5370 :     function.get_mappings ().get_defid (),
     149         2685 :     function.get_item_name ().as_string (), ident, flags, parent.get_abi (),
     150              :     std::move (params), ret_type, std::move (substitutions),
     151         5370 :     TyTy::SubstitutionArgumentMappings::empty (
     152         2685 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     153        10740 :     region_constraints);
     154              : 
     155         2685 :   context->insert_type (function.get_mappings (), fnType);
     156              : 
     157         2685 :   if (parent.get_abi () == Rust::ABI::INTRINSIC
     158         2685 :       && IntrinsicChecker::check (fnType) == IntrinsicCheckResult::Invalid)
     159           14 :     return;
     160              : 
     161         2671 :   resolved = fnType;
     162         5370 : }
     163              : 
     164              : void
     165            3 : TypeCheckTopLevelExternItem::visit (HIR::ExternalTypeItem &type)
     166              : {
     167            3 :   CanonicalPath path
     168            6 :     = CanonicalPath::new_seg (type.get_mappings ().get_nodeid (),
     169            6 :                               type.get_item_name ().as_string ());
     170              : 
     171            3 :   RustIdent ident{path, type.get_locus ()};
     172              : 
     173            3 :   TyTy::ADTType::ReprOptions repr;
     174            3 :   std::vector<TyTy::VariantDef *> variants;
     175            3 :   TyTy::RegionConstraints region_constraints;
     176            3 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     177              : 
     178            3 :   auto *extern_type = new TyTy::ADTType (
     179            3 :     type.get_mappings ().get_defid (), type.get_mappings ().get_hirid (),
     180            3 :     type.get_mappings ().get_hirid (), type.get_item_name ().as_string (),
     181              :     ident, TyTy::ADTType::ADTKind::EXTERN, std::move (variants),
     182              :     std::move (substitutions), repr,
     183            9 :     TyTy::SubstitutionArgumentMappings::empty (0), region_constraints);
     184              : 
     185            3 :   context->insert_type (type.get_mappings (), extern_type);
     186            3 :   resolved = extern_type;
     187            6 : }
     188              : 
     189        11408 : TypeCheckImplItem::TypeCheckImplItem (
     190              :   HIR::ImplBlock &parent, TyTy::BaseType *self,
     191              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     192        11408 :   : TypeCheckBase (), parent (parent), self (self),
     193        11408 :     substitutions (substitutions)
     194        11408 : {}
     195              : 
     196              : TyTy::BaseType *
     197        10143 : TypeCheckImplItem::Resolve (
     198              :   HIR::ImplBlock &parent, HIR::ImplItem &item, TyTy::BaseType *self,
     199              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     200              : {
     201              :   // is it already resolved?
     202        10143 :   auto context = TypeCheckContext::get ();
     203        10143 :   TyTy::BaseType *resolved = nullptr;
     204        10143 :   bool already_resolved
     205        10143 :     = context->lookup_type (item.get_impl_mappings ().get_hirid (), &resolved);
     206        10143 :   if (already_resolved)
     207              :     {
     208         2797 :       bool function_body_pending = false;
     209         2797 :       if (auto fn = resolved->try_as<TyTy::FnType> ())
     210         2034 :         function_body_pending = context->function_body_pending (fn->get_id ());
     211              : 
     212         2034 :       if (!function_body_pending)
     213          766 :         return resolved;
     214              :     }
     215              : 
     216              :   // resolve
     217         9377 :   TypeCheckImplItem resolver (parent, self, substitutions);
     218         9377 :   resolver.context->block_context ().enter (
     219         9377 :     TypeCheckBlockContextItem (&parent));
     220         9377 :   item.accept_vis (resolver);
     221         9377 :   resolver.context->block_context ().exit ();
     222              : 
     223         9377 :   return resolver.result;
     224         9377 : }
     225              : 
     226              : TyTy::FnType *
     227         2031 : TypeCheckImplItem::ResolveFunctionSignature (
     228              :   HIR::ImplBlock &parent, HIR::Function &function, TyTy::BaseType *self,
     229              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     230              : {
     231         2031 :   TypeCheckImplItem resolver (parent, self, std::move (substitutions));
     232         2031 :   auto binder_pin = resolver.context->push_lifetime_binder ();
     233         2031 :   resolver.context->block_context ().enter (
     234         2031 :     TypeCheckBlockContextItem (&parent));
     235         2031 :   TyTy::FnType *result = resolver.resolve_function_signature (function);
     236         2031 :   resolver.context->block_context ().exit ();
     237         2031 :   if (result != nullptr)
     238         2031 :     resolver.context->mark_function_body_pending (result->get_id ());
     239         4062 :   return result;
     240         2031 : }
     241              : 
     242              : TyTy::FnType *
     243         7892 : TypeCheckImplItem::resolve_function_signature (HIR::Function &function)
     244              : {
     245         7892 :   if (function.has_generics ())
     246          114 :     resolve_generic_params (HIR::Item::ItemKind::Function,
     247              :                             function.get_locus (),
     248          114 :                             function.get_generic_params (), substitutions);
     249              : 
     250         7892 :   TyTy::RegionConstraints region_constraints;
     251         7892 :   ResolveWhereClauseItem::Resolve (function.get_where_clause (),
     252              :                                    region_constraints);
     253              : 
     254         7892 :   TyTy::BaseType *ret_type = nullptr;
     255         7892 :   if (!function.has_function_return_type ())
     256          463 :     ret_type = TyTy::TupleType::get_unit_type ();
     257              :   else
     258              :     {
     259         7429 :       auto resolved = TypeCheckType::Resolve (function.get_return_type ());
     260         7429 :       if (resolved == nullptr)
     261              :         {
     262            0 :           rust_error_at (function.get_locus (),
     263              :                          "failed to resolve return type");
     264            0 :           return nullptr;
     265              :         }
     266              : 
     267         7429 :       ret_type = resolved->clone ();
     268         7429 :       ret_type->set_ref (
     269         7429 :         function.get_return_type ().get_mappings ().get_hirid ());
     270              :     }
     271              : 
     272         7892 :   std::vector<TyTy::FnParam> params;
     273         7892 :   if (function.is_method ())
     274              :     {
     275              :       // these are implicit mappings and not used
     276         6616 :       auto crate_num = mappings.get_current_crate ();
     277        13232 :       Analysis::NodeMapping mapping (crate_num, mappings.get_next_node_id (),
     278         6616 :                                      mappings.get_next_hir_id (crate_num),
     279         6616 :                                      UNKNOWN_LOCAL_DEFID);
     280              : 
     281              :       // add the synthetic self param at the front, this is a placeholder for
     282              :       // compilation to know parameter names. The types are ignored but we
     283              :       // reuse the HIR identifier pattern which requires it
     284         6616 :       HIR::SelfParam &self_param = function.get_self_param_unchecked ();
     285              :       // FIXME: which location should be used for Rust::Identifier for `self`?
     286         6616 :       std::unique_ptr<HIR::Pattern> self_pattern
     287         6616 :         = std::make_unique<HIR::IdentifierPattern> (
     288        13232 :           HIR::IdentifierPattern (mapping, {"self"}, self_param.get_locus (),
     289              :                                   self_param.is_ref (), self_param.get_mut (),
     290        26464 :                                   std::unique_ptr<HIR::Pattern> (nullptr)));
     291              : 
     292              :       // might have a specified type
     293         6616 :       TyTy::BaseType *self_type = nullptr;
     294         6616 :       if (self_param.has_type ())
     295              :         {
     296            2 :           auto &specified_type = self_param.get_type ();
     297            2 :           self_type = TypeCheckType::Resolve (specified_type);
     298              :         }
     299              :       else
     300              :         {
     301         6614 :           switch (self_param.get_self_kind ())
     302              :             {
     303         3045 :             case HIR::SelfParam::IMM:
     304         3045 :             case HIR::SelfParam::MUT:
     305         3045 :               self_type = self->clone ();
     306         3045 :               break;
     307              : 
     308         3344 :             case HIR::SelfParam::IMM_REF:
     309         3344 :               {
     310         3344 :                 tl::optional<TyTy::Region> region;
     311         3344 :                 if (self_param.has_lifetime ())
     312              :                   {
     313         6160 :                     region = context->lookup_and_resolve_lifetime (
     314         3080 :                       self_param.get_lifetime ());
     315         3080 :                     if (!region.has_value ())
     316              :                       {
     317            1 :                         rust_inform (self_param.get_locus (),
     318              :                                      "failed to resolve lifetime");
     319            1 :                         return nullptr;
     320              :                       }
     321              :                   }
     322              :                 else
     323              :                   {
     324          264 :                     region = TyTy::Region::make_anonymous ();
     325              :                   }
     326         6686 :                 self_type = new TyTy::ReferenceType (
     327         6686 :                   self_param.get_mappings ().get_hirid (),
     328         3343 :                   TyTy::TyVar (self->get_ref ()), Mutability::Imm,
     329         6686 :                   region.value ());
     330              :               }
     331         3343 :               break;
     332              : 
     333          225 :             case HIR::SelfParam::MUT_REF:
     334          225 :               {
     335          225 :                 tl::optional<TyTy::Region> region;
     336          225 :                 if (self_param.has_lifetime ())
     337              :                   {
     338          450 :                     region = context->lookup_and_resolve_lifetime (
     339          225 :                       self_param.get_lifetime ());
     340          225 :                     if (!region.has_value ())
     341              :                       {
     342            0 :                         rust_error_at (self_param.get_locus (),
     343              :                                        "failed to resolve lifetime");
     344            0 :                         return nullptr;
     345              :                       }
     346              :                   }
     347              :                 else
     348              :                   {
     349            0 :                     region = TyTy::Region::make_anonymous ();
     350              :                   }
     351          450 :                 self_type = new TyTy::ReferenceType (
     352          450 :                   self_param.get_mappings ().get_hirid (),
     353          225 :                   TyTy::TyVar (self->get_ref ()), Mutability::Mut,
     354          450 :                   region.value ());
     355              :               }
     356          225 :               break;
     357              : 
     358            0 :             default:
     359            0 :               rust_unreachable ();
     360              :               return nullptr;
     361              :             }
     362              :         }
     363              : 
     364         6615 :       context->insert_type (self_param.get_mappings (), self_type);
     365         6615 :       params.emplace_back (std::move (self_pattern), self_type);
     366         6616 :     }
     367              : 
     368        13016 :   for (auto &param : function.get_function_params ())
     369              :     {
     370              :       // get the name as well required for later on
     371         5125 :       auto param_tyty = TypeCheckType::Resolve (param.get_type ());
     372              : 
     373         5125 :       context->insert_type (param.get_mappings (), param_tyty);
     374         5125 :       TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
     375              : 
     376         5125 :       params.emplace_back (param.get_param_name ().clone_pattern (),
     377              :                            param_tyty);
     378              :     }
     379              : 
     380         7891 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     381              : 
     382         7891 :   CanonicalPath canonical_path
     383         7891 :     = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid (),
     384        15782 :                                 Resolver2_0::Namespace::Types);
     385              : 
     386        15782 :   RustIdent ident{canonical_path, function.get_locus ()};
     387         7891 :   auto fnType = new TyTy::FnType (
     388         7891 :     function.get_mappings ().get_hirid (),
     389         7891 :     function.get_mappings ().get_defid (),
     390         7891 :     function.get_function_name ().as_string (), ident,
     391         7891 :     function.is_method () ? TyTy::FnType::FNTYPE_IS_METHOD_FLAG
     392              :                           : TyTy::FnType::FNTYPE_DEFAULT_FLAGS,
     393         7891 :     ABI::RUST, std::move (params), ret_type, std::move (substitutions),
     394        15782 :     TyTy::SubstitutionArgumentMappings::empty (
     395         7891 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     396        39455 :     region_constraints);
     397              : 
     398         7891 :   context->insert_type (function.get_mappings (), fnType);
     399         7891 :   result = fnType;
     400              : 
     401         7891 :   return fnType;
     402         7892 : }
     403              : 
     404              : void
     405         7892 : TypeCheckImplItem::visit (HIR::Function &function)
     406              : {
     407         7892 :   auto binder_pin = context->push_lifetime_binder ();
     408              : 
     409         7892 :   TyTy::BaseType *resolved = nullptr;
     410         7892 :   TyTy::FnType *resolve_fn_type = nullptr;
     411         7892 :   if (context->lookup_type (function.get_mappings ().get_hirid (), &resolved))
     412              :     {
     413         2031 :       if (resolved->get_kind () != TyTy::TypeKind::FNDEF)
     414              :         return;
     415         2031 :       resolve_fn_type = static_cast<TyTy::FnType *> (resolved);
     416         2031 :       result = resolve_fn_type;
     417              :     }
     418              :   else
     419         5861 :     resolve_fn_type = resolve_function_signature (function);
     420              : 
     421         7892 :   if (resolve_fn_type == nullptr)
     422              :     return;
     423              : 
     424              :   // Mark the body as claimed before resolving it.  Recursive queries from the
     425              :   // body must reuse the cached signature rather than re-entering this body.
     426         7891 :   context->clear_function_body_pending (resolve_fn_type->get_id ());
     427              : 
     428              :   // need to get the return type from this
     429         7891 :   auto expected_ret_tyty = resolve_fn_type->get_return_type ();
     430         7891 :   context->push_return_type (TypeCheckContextItem (parent, &function),
     431              :                              expected_ret_tyty);
     432              : 
     433         7891 :   auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
     434              : 
     435         7891 :   location_t fn_return_locus = function.has_function_return_type ()
     436         7891 :                                  ? function.get_return_type ().get_locus ()
     437          463 :                                  : function.get_locus ();
     438              : 
     439        15782 :   coercion_site (function.get_definition ().get_mappings ().get_hirid (),
     440         7891 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     441         7891 :                  TyTy::TyWithLocation (block_expr_ty),
     442         7891 :                  function.get_definition ().get_locus ());
     443              : 
     444         7891 :   context->pop_return_type ();
     445         7892 : }
     446              : 
     447              : void
     448           72 : TypeCheckImplItem::visit (HIR::ConstantItem &constant)
     449              : {
     450           72 :   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
     451           72 :   context->push_const_context ();
     452           72 :   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
     453           72 :   context->pop_const_context ();
     454              : 
     455          144 :   TyTy::BaseType *unified = unify_site (
     456           72 :     constant.get_mappings ().get_hirid (),
     457           72 :     TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
     458           72 :     TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
     459              :     constant.get_locus ());
     460              : 
     461           72 :   if (substitutions.empty ())
     462              :     {
     463           43 :       context->insert_type (constant.get_mappings (), unified);
     464           43 :       result = unified;
     465           43 :       return;
     466              :     }
     467              : 
     468              :   // special case when this is a generic constant
     469           29 :   auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
     470              :   // TODO: Is Values the correct NS?
     471           29 :   CanonicalPath canonical_path
     472           29 :     = nr_ctx.to_canonical_path (constant.get_mappings ().get_nodeid (),
     473           29 :                                 Resolver2_0::Namespace::Values);
     474           29 :   RustIdent ident{canonical_path, constant.get_locus ()};
     475           29 :   auto fnType = new TyTy::FnType (
     476           29 :     constant.get_mappings ().get_hirid (),
     477           29 :     constant.get_mappings ().get_defid (),
     478           29 :     constant.get_identifier ().as_string (), ident,
     479              :     TyTy::FnType::FNTYPE_IS_SYN_CONST_FLAG, ABI::RUST, {}, unified,
     480           29 :     std::move (substitutions),
     481           58 :     TyTy::SubstitutionArgumentMappings::empty (
     482           29 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     483          116 :     {});
     484              : 
     485           29 :   context->insert_type (constant.get_mappings (), fnType);
     486           29 :   result = fnType;
     487           29 : }
     488              : 
     489              : void
     490         1413 : TypeCheckImplItem::visit (HIR::TypeAlias &alias)
     491              : {
     492         1413 :   auto binder_pin = context->push_lifetime_binder ();
     493              : 
     494         1413 :   if (alias.has_generics ())
     495           15 :     resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
     496           15 :                             alias.get_generic_params (), substitutions);
     497              : 
     498         1413 :   TyTy::BaseType *actual_type
     499         1413 :     = TypeCheckType::Resolve (alias.get_type_aliased ());
     500              : 
     501         1413 :   context->insert_type (alias.get_mappings (), actual_type);
     502         1413 :   result = actual_type;
     503         1413 :   TyTy::RegionConstraints region_constraints;
     504         1413 :   ResolveWhereClauseItem::Resolve (alias.get_where_clause (),
     505              :                                    region_constraints);
     506         1413 : }
     507              : 
     508         6921 : TypeCheckImplItemWithTrait::TypeCheckImplItemWithTrait (
     509              :   HIR::ImplBlock &parent, TyTy::BaseType *self,
     510              :   TyTy::TypeBoundPredicate &trait_reference,
     511              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     512         6921 :   : TypeCheckBase (), trait_reference (trait_reference),
     513         6921 :     resolved_trait_item (TyTy::TypeBoundPredicateItem::error ()),
     514         6921 :     parent (parent), self (self), substitutions (substitutions)
     515              : {
     516         6921 :   rust_assert (is_trait_impl_block ());
     517         6921 : }
     518              : 
     519              : TyTy::TypeBoundPredicateItem
     520         6921 : TypeCheckImplItemWithTrait::Resolve (
     521              :   HIR::ImplBlock &parent, HIR::ImplItem &item, TyTy::BaseType *self,
     522              :   TyTy::TypeBoundPredicate &trait_reference,
     523              :   std::vector<TyTy::SubstitutionParamMapping> substitutions)
     524              : {
     525         6921 :   TypeCheckImplItemWithTrait resolver (parent, self, trait_reference,
     526         6921 :                                        substitutions);
     527         6921 :   item.accept_vis (resolver);
     528         6921 :   return resolver.resolved_trait_item;
     529         6921 : }
     530              : 
     531              : void
     532           32 : TypeCheckImplItemWithTrait::visit (HIR::ConstantItem &constant)
     533              : {
     534              :   // normal resolution of the item
     535           32 :   TyTy::BaseType *lookup
     536           32 :     = TypeCheckImplItem::Resolve (parent, constant, self, substitutions);
     537              : 
     538              :   // map the impl item to the associated trait item
     539           32 :   const auto tref = trait_reference.get ();
     540           32 :   const TraitItemReference *raw_trait_item = nullptr;
     541           32 :   bool found
     542           32 :     = tref->lookup_trait_item_by_type (constant.get_identifier ().as_string (),
     543              :                                        TraitItemReference::TraitItemType::CONST,
     544              :                                        &raw_trait_item);
     545              : 
     546              :   // unknown trait item - https://doc.rust-lang.org/error_codes/E0323.html
     547           32 :   if (!found || raw_trait_item->is_error ())
     548              :     {
     549            1 :       rich_location r (line_table, constant.get_locus ());
     550            1 :       r.add_range (trait_reference.get_locus ());
     551            1 :       rust_error_at (r, ErrorCode::E0323,
     552              :                      "item %qs is an associated const, which does not match "
     553              :                      "its trait %qs",
     554            2 :                      constant.get_identifier ().as_string ().c_str (),
     555            1 :                      trait_reference.get_name ().c_str ());
     556            1 :       return;
     557            1 :     }
     558              : 
     559              :   // get the item from the predicate
     560           31 :   resolved_trait_item
     561           31 :     = trait_reference.lookup_associated_item (raw_trait_item).value ();
     562              : 
     563              :   // merge the attributes
     564           31 :   const HIR::TraitItem *hir_trait_item
     565           31 :     = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
     566           31 :   merge_attributes (constant.get_outer_attrs (), *hir_trait_item);
     567              : 
     568              :   // check the types are compatible
     569           31 :   auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
     570           31 :   if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
     571           31 :                          TyTy::TyWithLocation (lookup), constant.get_locus (),
     572              :                          true /*emit_errors*/))
     573              :     {
     574            0 :       rich_location r (line_table, constant.get_locus ());
     575            0 :       r.add_range (resolved_trait_item.get_locus ());
     576              : 
     577            0 :       rust_error_at (r, "constant %qs has an incompatible type for trait %qs",
     578            0 :                      constant.get_identifier ().as_string ().c_str (),
     579            0 :                      trait_reference.get_name ().c_str ());
     580            0 :     }
     581              : }
     582              : 
     583              : void
     584         2167 : TypeCheckImplItemWithTrait::visit (HIR::TypeAlias &type)
     585              : {
     586         2167 :   auto binder_pin = context->push_lifetime_binder ();
     587              : 
     588         2167 :   if (type.has_generics ())
     589           15 :     resolve_generic_params (HIR::Item::ItemKind::TypeAlias, type.get_locus (),
     590           15 :                             type.get_generic_params (), substitutions);
     591              : 
     592              :   // normal resolution of the item
     593         2167 :   TyTy::BaseType *lookup
     594         2167 :     = TypeCheckImplItem::Resolve (parent, type, self, substitutions);
     595              : 
     596              :   // map the impl item to the associated trait item
     597         2167 :   const auto tref = trait_reference.get ();
     598         2167 :   const TraitItemReference *raw_trait_item = nullptr;
     599         2167 :   bool found
     600         2167 :     = tref->lookup_trait_item_by_type (type.get_new_type_name ().as_string (),
     601              :                                        TraitItemReference::TraitItemType::TYPE,
     602              :                                        &raw_trait_item);
     603              : 
     604              :   // unknown trait item
     605         2167 :   if (!found || raw_trait_item->is_error ())
     606              :     {
     607            0 :       rich_location r (line_table, type.get_locus ());
     608            0 :       r.add_range (trait_reference.get_locus ());
     609            0 :       rust_error_at (r, "type alias %qs is not a member of trait %qs",
     610            0 :                      type.get_new_type_name ().as_string ().c_str (),
     611            0 :                      trait_reference.get_name ().c_str ());
     612            0 :       return;
     613            0 :     }
     614              : 
     615              :   // get the item from the predicate
     616         2167 :   resolved_trait_item
     617         2167 :     = trait_reference.lookup_associated_item (raw_trait_item).value ();
     618              : 
     619              :   // merge the attributes
     620         2167 :   const HIR::TraitItem *hir_trait_item
     621         2167 :     = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
     622         2167 :   merge_attributes (type.get_outer_attrs (), *hir_trait_item);
     623              : 
     624              :   // unwrap a ProjectionType that already wraps a concrete
     625         2167 :   if (auto *p = lookup->try_as<TyTy::ProjectionType> ())
     626         1590 :     if (!p->is_trait_position () && p->get () != nullptr
     627         1590 :         && p->get ()->get_kind () != TyTy::TypeKind::PROJECTION)
     628          746 :       lookup = p->get ();
     629              : 
     630              :   // The impl alias is itself a projection so the substitution machinery has a
     631              :   // handle to bind the impl's generic arguments to the alias body.
     632         2167 :   auto projection
     633         2167 :     = new TyTy::ProjectionType (type.get_mappings ().get_hirid (), lookup, tref,
     634         2167 :                                 raw_trait_item->get_mappings ().get_defid (),
     635         6501 :                                 substitutions, self);
     636              : 
     637              :   // check the types are compatible
     638         2167 :   auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
     639         2167 :   if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
     640         2167 :                          TyTy::TyWithLocation (projection), type.get_locus (),
     641              :                          true /*emit_errors*/))
     642              :     {
     643            0 :       rich_location r (line_table, type.get_locus ());
     644            0 :       r.add_range (resolved_trait_item.get_locus ());
     645              : 
     646            0 :       rust_error_at (r, "type alias %qs has an incompatible type for trait %qs",
     647            0 :                      type.get_new_type_name ().as_string ().c_str (),
     648            0 :                      trait_reference.get_name ().c_str ());
     649            0 :     }
     650              : 
     651         2167 :   context->insert_type (type.get_mappings (), projection);
     652         2167 : }
     653              : 
     654              : void
     655         4722 : TypeCheckImplItemWithTrait::visit (HIR::Function &function)
     656              : {
     657              :   // normal resolution of the item
     658         4722 :   TyTy::BaseType *lookup
     659         4722 :     = TypeCheckImplItem::Resolve (parent, function, self, substitutions);
     660         4722 :   if (lookup == nullptr)
     661            4 :     return;
     662              : 
     663              :   // map the impl item to the associated trait item
     664         4721 :   const auto tref = trait_reference.get ();
     665         4721 :   const TraitItemReference *raw_trait_item = nullptr;
     666         4721 :   bool found = tref->lookup_trait_item_by_type (
     667         4721 :     function.get_function_name ().as_string (),
     668              :     TraitItemReference::TraitItemType::FN, &raw_trait_item);
     669              : 
     670              :   // unknown trait item
     671         4721 :   if (!found || raw_trait_item->is_error ())
     672              :     {
     673            3 :       rich_location r (line_table, function.get_locus ());
     674            3 :       r.add_range (trait_reference.get_locus ());
     675            3 :       rust_error_at (r, "method %qs is not a member of trait %qs",
     676            6 :                      function.get_function_name ().as_string ().c_str (),
     677            3 :                      trait_reference.get_name ().c_str ());
     678            3 :       return;
     679            3 :     }
     680              : 
     681              :   // get the item from the predicate
     682         4718 :   resolved_trait_item
     683         4718 :     = trait_reference.lookup_associated_item (raw_trait_item).value ();
     684              : 
     685              :   // merge the attributes
     686         4718 :   const HIR::TraitItem *hir_trait_item
     687         4718 :     = resolved_trait_item.get_raw_item ()->get_hir_trait_item ();
     688         4718 :   merge_attributes (function.get_outer_attrs (), *hir_trait_item);
     689              : 
     690              :   // check the types are compatible
     691         4718 :   auto trait_item_type = resolved_trait_item.get_tyty_for_receiver (self);
     692         4718 :   if (!types_compatable (TyTy::TyWithLocation (trait_item_type),
     693         4718 :                          TyTy::TyWithLocation (lookup), function.get_locus (),
     694              :                          true /*emit_errors*/))
     695              :     {
     696            5 :       rich_location r (line_table, function.get_locus ());
     697            5 :       r.add_range (resolved_trait_item.get_locus ());
     698              : 
     699            5 :       rust_error_at (r, ErrorCode::E0053,
     700              :                      "method %qs has an incompatible type for trait %qs",
     701           10 :                      function.get_function_name ().as_string ().c_str (),
     702            5 :                      trait_reference.get_name ().c_str ());
     703            5 :     }
     704              : }
     705              : 
     706              : void
     707         6916 : TypeCheckImplItemWithTrait::merge_attributes (AST::AttrVec &impl_item_attrs,
     708              :                                               const HIR::TraitItem &trait_item)
     709              : {
     710        21256 :   for (const auto &attr : trait_item.get_outer_attrs ())
     711              :     {
     712        14340 :       impl_item_attrs.push_back (attr);
     713              :     }
     714         6916 : }
     715              : 
     716              : bool
     717         6921 : TypeCheckImplItemWithTrait::is_trait_impl_block () const
     718              : {
     719         6921 :   return !trait_reference.is_error ();
     720              : }
     721              : 
     722              : } // namespace Resolver
     723              : } // 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.