LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-item.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 95.8 % 500 479
Test Date: 2026-04-20 14:57:17 Functions: 95.5 % 22 21
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-item.h"
      20              : #include "optional.h"
      21              : #include "rust-canonical-path.h"
      22              : #include "rust-diagnostics.h"
      23              : #include "rust-hir-item.h"
      24              : #include "rust-hir-type-check-enumitem.h"
      25              : #include "rust-hir-type-check-implitem.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-hir-trait-resolve.h"
      30              : #include "rust-identifier.h"
      31              : #include "rust-session-manager.h"
      32              : #include "rust-immutable-name-resolution-context.h"
      33              : #include "rust-substitution-mapper.h"
      34              : #include "rust-type-util.h"
      35              : #include "rust-tyty-variance-analysis.h"
      36              : 
      37              : namespace Rust {
      38              : namespace Resolver {
      39              : 
      40        58355 : TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
      41              : 
      42              : TyTy::BaseType *
      43        27555 : TypeCheckItem::Resolve (HIR::Item &item)
      44              : {
      45              :   // is it already resolved?
      46        27555 :   auto context = TypeCheckContext::get ();
      47        27555 :   TyTy::BaseType *resolved = nullptr;
      48        27555 :   bool already_resolved
      49        27555 :     = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
      50        27555 :   if (already_resolved)
      51         4871 :     return resolved;
      52              : 
      53        22684 :   rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
      54        22684 :   HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
      55              : 
      56        22684 :   TypeCheckItem resolver;
      57        22684 :   vis_item.accept_vis (resolver);
      58        22682 :   return resolver.infered;
      59        22682 : }
      60              : 
      61              : TyTy::BaseType *
      62         3279 : TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
      63              : {
      64         3279 :   TypeCheckItem resolver;
      65         3279 :   return resolver.resolve_impl_item (impl_block, item);
      66         3279 : }
      67              : 
      68              : TyTy::BaseType *
      69        29406 : TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
      70              : {
      71        29406 :   TypeCheckItem resolver;
      72              : 
      73        29406 :   bool failed_flag = false;
      74        29406 :   auto result
      75        29406 :     = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
      76        29406 :   if (failed_flag)
      77              :     {
      78            1 :       return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
      79              :     }
      80        29405 :   std::vector<TyTy::SubstitutionParamMapping> substitutions
      81        29405 :     = std::move (result.first);
      82        29405 :   TyTy::RegionConstraints region_constraints = std::move (result.second);
      83              : 
      84        29405 :   return resolver.resolve_impl_block_self (impl_block);
      85        29406 : }
      86              : 
      87              : TyTy::BaseType *
      88         2986 : TypeCheckItem::ResolveImplBlockSelfWithInference (
      89              :   HIR::ImplBlock &impl, location_t locus,
      90              :   TyTy::SubstitutionArgumentMappings *infer_arguments)
      91              : {
      92         2986 :   TypeCheckItem resolver;
      93              : 
      94         2986 :   bool failed_flag = false;
      95         2986 :   auto result = resolver.resolve_impl_block_substitutions (impl, failed_flag);
      96         2986 :   if (failed_flag)
      97              :     {
      98            1 :       return new TyTy::ErrorType (impl.get_mappings ().get_hirid ());
      99              :     }
     100         2985 :   std::vector<TyTy::SubstitutionParamMapping> substitutions
     101         2985 :     = std::move (result.first);
     102         2985 :   TyTy::RegionConstraints region_constraints = std::move (result.second);
     103              : 
     104              :   // now that we have the param mappings we need to query the self type
     105         2985 :   TyTy::BaseType *self = resolver.resolve_impl_block_self (impl);
     106              : 
     107              :   // nothing to do
     108         2985 :   if (substitutions.empty () || self->is_concrete ())
     109         2274 :     return self;
     110              : 
     111              :   // generate inference variables for the subst-param-mappings
     112          711 :   std::vector<TyTy::SubstitutionArg> args;
     113         1447 :   for (auto &p : substitutions)
     114              :     {
     115          736 :       auto param = p.get_param_ty ();
     116          736 :       if (!p.needs_substitution ())
     117              :         {
     118            0 :           auto resolved = param->destructure ();
     119            0 :           args.emplace_back (&p, resolved);
     120              : 
     121            0 :           continue;
     122            0 :         }
     123              : 
     124          736 :       TyTy::BaseType *argument = nullptr;
     125          736 :       if (param->get_kind () == TyTy::TypeKind::CONST)
     126              :         {
     127           28 :           auto i = TyTy::TyVar::get_implicit_const_infer_var (locus);
     128           28 :           argument = i.get_tyty ();
     129              :         }
     130              :       else
     131              :         {
     132          708 :           auto i = TyTy::TyVar::get_implicit_infer_var (locus);
     133          708 :           argument = i.get_tyty ();
     134              :         }
     135          736 :       args.emplace_back (&p, argument);
     136              :     }
     137              : 
     138              :   // create argument mappings
     139         1422 :   *infer_arguments = TyTy::SubstitutionArgumentMappings (
     140              :     std::move (args), {},
     141          711 :     TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (
     142              :       infer_arguments),
     143         1422 :     locus);
     144              : 
     145          711 :   TyTy::BaseType *infer = SubstMapperInternal::Resolve (self, *infer_arguments);
     146              : 
     147              :   // we only need to apply to the bounds manually on types which dont bind
     148              :   // generics
     149          711 :   if (!infer->has_substitutions_defined ())
     150              :     {
     151          613 :       for (auto &bound : infer->get_specified_bounds ())
     152          161 :         bound.handle_substitions (*infer_arguments);
     153              :     }
     154              : 
     155          711 :   return infer;
     156         3697 : }
     157              : 
     158              : void
     159           54 : TypeCheckItem::visit (HIR::TypeAlias &alias)
     160              : {
     161           54 :   TyTy::BaseType *actual_type
     162           54 :     = TypeCheckType::Resolve (alias.get_type_aliased ());
     163              : 
     164           54 :   context->insert_type (alias.get_mappings (), actual_type);
     165              : 
     166           54 :   TyTy::RegionConstraints region_constraints;
     167           54 :   for (auto &where_clause_item : alias.get_where_clause ().get_items ())
     168              :     {
     169            0 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     170              :     }
     171           54 :   infered = actual_type;
     172           54 : }
     173              : 
     174              : void
     175          957 : TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
     176              : {
     177          957 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     178              : 
     179          957 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     180          957 :   if (struct_decl.has_generics ())
     181          295 :     resolve_generic_params (HIR::Item::ItemKind::Struct,
     182              :                             struct_decl.get_locus (),
     183          295 :                             struct_decl.get_generic_params (), substitutions);
     184              : 
     185          957 :   TyTy::RegionConstraints region_constraints;
     186          957 :   for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
     187              :     {
     188            0 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     189              :     }
     190              : 
     191          957 :   std::vector<TyTy::StructFieldType *> fields;
     192          957 :   size_t idx = 0;
     193         2576 :   for (auto &field : struct_decl.get_fields ())
     194              :     {
     195         1619 :       TyTy::BaseType *field_type
     196         1619 :         = TypeCheckType::Resolve (field.get_field_type ());
     197         1619 :       auto *ty_field
     198         3238 :         = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
     199         1619 :                                      std::to_string (idx), field_type,
     200         1619 :                                      field.get_locus ());
     201         1619 :       fields.push_back (ty_field);
     202         1619 :       context->insert_type (field.get_mappings (), ty_field->get_field_type ());
     203         1619 :       idx++;
     204              :     }
     205              : 
     206              :   // get the path
     207              : 
     208          957 :   auto &nr_ctx
     209          957 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     210              : 
     211          957 :   CanonicalPath path
     212          957 :     = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
     213              : 
     214          957 :   RustIdent ident{path, struct_decl.get_locus ()};
     215              : 
     216              :   // its a single variant ADT
     217          957 :   std::vector<TyTy::VariantDef *> variants;
     218          957 :   variants.push_back (
     219          957 :     new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
     220          957 :                           struct_decl.get_mappings ().get_defid (),
     221          957 :                           struct_decl.get_identifier ().as_string (), ident,
     222         1914 :                           TyTy::VariantDef::VariantType::TUPLE, tl::nullopt,
     223         2871 :                           std::move (fields)));
     224              : 
     225              :   // Process #[repr(X)] attribute, if any
     226          957 :   const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
     227          957 :   TyTy::ADTType::ReprOptions repr
     228          957 :     = parse_repr_options (attrs, struct_decl.get_locus ());
     229              : 
     230          957 :   auto *type = new TyTy::ADTType (
     231          957 :     struct_decl.get_mappings ().get_defid (),
     232          957 :     struct_decl.get_mappings ().get_hirid (),
     233          957 :     struct_decl.get_mappings ().get_hirid (),
     234          957 :     struct_decl.get_identifier ().as_string (), ident,
     235              :     TyTy::ADTType::ADTKind::TUPLE_STRUCT, std::move (variants),
     236              :     std::move (substitutions), repr,
     237         1914 :     TyTy::SubstitutionArgumentMappings::empty (
     238          957 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     239         3828 :     region_constraints);
     240              : 
     241          957 :   context->insert_type (struct_decl.get_mappings (), type);
     242          957 :   infered = type;
     243              : 
     244          957 :   context->get_variance_analysis_ctx ().add_type_constraints (*type);
     245         1914 : }
     246              : 
     247              : void
     248         1503 : TypeCheckItem::visit (HIR::StructStruct &struct_decl)
     249              : {
     250         1503 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     251              : 
     252         1503 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     253         1503 :   if (struct_decl.has_generics ())
     254          482 :     resolve_generic_params (HIR::Item::ItemKind::Struct,
     255              :                             struct_decl.get_locus (),
     256          482 :                             struct_decl.get_generic_params (), substitutions);
     257              : 
     258         1503 :   TyTy::RegionConstraints region_constraints;
     259         1507 :   for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
     260              :     {
     261            4 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     262              :     }
     263              : 
     264         1503 :   std::vector<TyTy::StructFieldType *> fields;
     265         3312 :   for (auto &field : struct_decl.get_fields ())
     266              :     {
     267         1809 :       TyTy::BaseType *field_type
     268         1809 :         = TypeCheckType::Resolve (field.get_field_type ());
     269         1809 :       auto *ty_field
     270         1809 :         = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
     271         1809 :                                      field.get_field_name ().as_string (),
     272         3618 :                                      field_type, field.get_locus ());
     273         1809 :       fields.push_back (ty_field);
     274         1809 :       context->insert_type (field.get_mappings (), ty_field->get_field_type ());
     275              :     }
     276              : 
     277         1503 :   auto &nr_ctx
     278         1503 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     279              : 
     280         1503 :   CanonicalPath path
     281         1503 :     = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid ());
     282              : 
     283         1503 :   RustIdent ident{path, struct_decl.get_locus ()};
     284              : 
     285              :   // its a single variant ADT
     286         1503 :   auto variant_type = struct_decl.is_unit_struct ()
     287         1503 :                         ? TyTy::VariantDef::VariantType::UNIT
     288          967 :                         : TyTy::VariantDef::VariantType::STRUCT;
     289         1503 :   std::vector<TyTy::VariantDef *> variants;
     290         1503 :   variants.push_back (
     291         1503 :     new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
     292         1503 :                           struct_decl.get_mappings ().get_defid (),
     293         1503 :                           struct_decl.get_identifier ().as_string (), ident,
     294         4509 :                           variant_type, tl::nullopt, std::move (fields)));
     295              : 
     296              :   // Process #[repr(X)] attribute, if any
     297         1503 :   const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
     298         1503 :   TyTy::ADTType::ReprOptions repr
     299         1503 :     = parse_repr_options (attrs, struct_decl.get_locus ());
     300              : 
     301         1503 :   auto *type = new TyTy::ADTType (
     302         1503 :     struct_decl.get_mappings ().get_defid (),
     303         1503 :     struct_decl.get_mappings ().get_hirid (),
     304         1503 :     struct_decl.get_mappings ().get_hirid (),
     305         1503 :     struct_decl.get_identifier ().as_string (), ident,
     306              :     TyTy::ADTType::ADTKind::STRUCT_STRUCT, std::move (variants),
     307              :     std::move (substitutions), repr,
     308         3006 :     TyTy::SubstitutionArgumentMappings::empty (
     309         1503 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     310         6012 :     region_constraints);
     311              : 
     312         1503 :   context->insert_type (struct_decl.get_mappings (), type);
     313         1503 :   infered = type;
     314              : 
     315         1503 :   context->get_variance_analysis_ctx ().add_type_constraints (*type);
     316         3006 : }
     317              : 
     318              : void
     319          523 : TypeCheckItem::visit (HIR::Enum &enum_decl)
     320              : {
     321          523 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     322          523 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     323          523 :   if (enum_decl.has_generics ())
     324          226 :     resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (),
     325          226 :                             enum_decl.get_generic_params (), substitutions);
     326              : 
     327              :   // Process #[repr(X)] attribute, if any
     328          523 :   const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
     329          523 :   TyTy::ADTType::ReprOptions repr
     330          523 :     = parse_repr_options (attrs, enum_decl.get_locus ());
     331              : 
     332          523 :   std::vector<TyTy::VariantDef *> variants;
     333          523 :   int64_t discriminant_value = 0;
     334         1738 :   for (auto &variant : enum_decl.get_variants ())
     335              :     {
     336         1215 :       TyTy::VariantDef *field_type
     337         1215 :         = TypeCheckEnumItem::Resolve (*variant, discriminant_value);
     338              : 
     339         1215 :       discriminant_value++;
     340         1215 :       variants.push_back (field_type);
     341              :     }
     342              : 
     343              :   // Check for zero-variant enum compatibility
     344          523 :   if (enum_decl.is_zero_variant ())
     345              :     {
     346           10 :       if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
     347           10 :           || repr.repr_kind == TyTy::ADTType::ReprKind::C)
     348              :         {
     349            2 :           rust_error_at (enum_decl.get_locus (),
     350              :                          "unsupported representation for zero-variant enum");
     351            2 :           return;
     352              :         }
     353              :     }
     354              : 
     355          521 :   auto &nr_ctx
     356          521 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     357              : 
     358              :   // get the path
     359          521 :   CanonicalPath canonical_path
     360          521 :     = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid ());
     361              : 
     362          521 :   RustIdent ident{canonical_path, enum_decl.get_locus ()};
     363              : 
     364              :   // multi variant ADT
     365          521 :   auto *type
     366          521 :     = new TyTy::ADTType (enum_decl.get_mappings ().get_defid (),
     367          521 :                          enum_decl.get_mappings ().get_hirid (),
     368          521 :                          enum_decl.get_mappings ().get_hirid (),
     369          521 :                          enum_decl.get_identifier ().as_string (), ident,
     370              :                          TyTy::ADTType::ADTKind::ENUM, std::move (variants),
     371         1563 :                          std::move (substitutions), repr);
     372              : 
     373          521 :   context->insert_type (enum_decl.get_mappings (), type);
     374          521 :   infered = type;
     375              : 
     376          521 :   context->get_variance_analysis_ctx ().add_type_constraints (*type);
     377          523 : }
     378              : 
     379              : void
     380          104 : TypeCheckItem::visit (HIR::Union &union_decl)
     381              : {
     382          104 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     383          104 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     384          104 :   if (union_decl.has_generics ())
     385           74 :     resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (),
     386           74 :                             union_decl.get_generic_params (), substitutions);
     387              : 
     388          104 :   TyTy::RegionConstraints region_constraints;
     389          104 :   for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
     390              :     {
     391            0 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     392              :     }
     393              : 
     394          104 :   std::vector<TyTy::StructFieldType *> fields;
     395          406 :   for (auto &variant : union_decl.get_variants ())
     396              :     {
     397          302 :       TyTy::BaseType *variant_type
     398          302 :         = TypeCheckType::Resolve (variant.get_field_type ());
     399          302 :       auto *ty_variant
     400          302 :         = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
     401          302 :                                      variant.get_field_name ().as_string (),
     402          604 :                                      variant_type, variant.get_locus ());
     403          302 :       fields.push_back (ty_variant);
     404          302 :       context->insert_type (variant.get_mappings (),
     405              :                             ty_variant->get_field_type ());
     406              :     }
     407              : 
     408          104 :   auto &nr_ctx
     409          104 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     410              : 
     411              :   // get the path
     412          104 :   CanonicalPath canonical_path
     413          104 :     = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid ());
     414              : 
     415          104 :   RustIdent ident{canonical_path, union_decl.get_locus ()};
     416              : 
     417              :   // there is only a single variant
     418          104 :   std::vector<TyTy::VariantDef *> variants;
     419          104 :   variants.push_back (
     420          104 :     new TyTy::VariantDef (union_decl.get_mappings ().get_hirid (),
     421          104 :                           union_decl.get_mappings ().get_defid (),
     422          104 :                           union_decl.get_identifier ().as_string (), ident,
     423          208 :                           TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
     424          312 :                           std::move (fields)));
     425              : 
     426          104 :   auto *type
     427          104 :     = new TyTy::ADTType (union_decl.get_mappings ().get_defid (),
     428          104 :                          union_decl.get_mappings ().get_hirid (),
     429          104 :                          union_decl.get_mappings ().get_hirid (),
     430          104 :                          union_decl.get_identifier ().as_string (), ident,
     431              :                          TyTy::ADTType::ADTKind::UNION, std::move (variants),
     432          312 :                          std::move (substitutions));
     433              : 
     434          104 :   context->insert_type (union_decl.get_mappings (), type);
     435          104 :   infered = type;
     436              : 
     437          104 :   context->get_variance_analysis_ctx ().add_type_constraints (*type);
     438          208 : }
     439              : 
     440              : void
     441           53 : TypeCheckItem::visit (HIR::StaticItem &var)
     442              : {
     443           53 :   TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
     444           53 :   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
     445              : 
     446           53 :   TyTy::BaseType *unified
     447           53 :     = coercion_site (var.get_mappings ().get_hirid (),
     448           53 :                      TyTy::TyWithLocation (type, var.get_type ().get_locus ()),
     449              :                      TyTy::TyWithLocation (expr_type,
     450           53 :                                            var.get_expr ().get_locus ()),
     451              :                      var.get_locus ());
     452           53 :   context->insert_type (var.get_mappings (), unified);
     453           53 :   infered = unified;
     454           53 : }
     455              : 
     456              : void
     457          409 : TypeCheckItem::visit (HIR::ConstantItem &constant)
     458              : {
     459          409 :   TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
     460          409 :   TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
     461              : 
     462          818 :   TyTy::BaseType *unified = unify_site (
     463          409 :     constant.get_mappings ().get_hirid (),
     464          409 :     TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
     465          409 :     TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
     466              :     constant.get_locus ());
     467          409 :   context->insert_type (constant.get_mappings (), unified);
     468          409 :   infered = unified;
     469          409 : }
     470              : 
     471              : void
     472         5597 : TypeCheckItem::visit (HIR::ImplBlock &impl_block)
     473              : {
     474         5597 :   auto binder_pin = context->push_clean_lifetime_resolver (true);
     475              : 
     476         5597 :   TraitReference *trait_reference = &TraitReference::error_node ();
     477         5597 :   if (impl_block.has_trait_ref ())
     478              :     {
     479         4654 :       HIR::TypePath &ref = impl_block.get_trait_ref ();
     480         4654 :       trait_reference = TraitResolver::Resolve (ref);
     481         4654 :       if (trait_reference->is_error ())
     482              :         return;
     483              :     }
     484              : 
     485         5596 :   bool failed_flag = false;
     486         5596 :   auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
     487         5596 :   if (failed_flag)
     488              :     {
     489            4 :       infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
     490            4 :       return;
     491              :     }
     492         5592 :   std::vector<TyTy::SubstitutionParamMapping> substitutions
     493         5592 :     = std::move (result.first);
     494         5592 :   TyTy::RegionConstraints region_constraints = std::move (result.second);
     495              : 
     496         5592 :   TyTy::BaseType *self = resolve_impl_block_self (impl_block);
     497              : 
     498              :   // resolve each impl_item
     499        13673 :   for (auto &impl_item : impl_block.get_impl_items ())
     500              :     {
     501         8081 :       TypeCheckImplItem::Resolve (impl_block, *impl_item, self, substitutions);
     502              :     }
     503              : 
     504              :   // validate the impl items
     505         5592 :   validate_trait_impl_block (trait_reference, impl_block, self, substitutions);
     506         5597 : }
     507              : 
     508              : TyTy::BaseType *
     509         3279 : TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
     510              :                                   HIR::ImplItem &item)
     511              : {
     512         3279 :   bool failed_flag = false;
     513         3279 :   auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
     514         3279 :   if (failed_flag)
     515              :     {
     516            1 :       return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
     517              :     }
     518              : 
     519         3278 :   std::vector<TyTy::SubstitutionParamMapping> substitutions
     520         3278 :     = std::move (result.first);
     521         3278 :   TyTy::RegionConstraints region_constraints = std::move (result.second);
     522              : 
     523         3278 :   TyTy::BaseType *self = resolve_impl_block_self (impl_block);
     524              : 
     525         3278 :   return TypeCheckImplItem::Resolve (impl_block, item, self, substitutions);
     526         3279 : }
     527              : 
     528              : void
     529         6491 : TypeCheckItem::visit (HIR::Function &function)
     530              : {
     531         6491 :   auto lifetime_pin = context->push_clean_lifetime_resolver ();
     532         6491 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     533         6491 :   if (function.has_generics ())
     534          601 :     resolve_generic_params (HIR::Item::ItemKind::Function,
     535              :                             function.get_locus (),
     536          601 :                             function.get_generic_params (), substitutions);
     537              : 
     538         6491 :   TyTy::RegionConstraints region_constraints;
     539         6537 :   for (auto &where_clause_item : function.get_where_clause ().get_items ())
     540              :     {
     541           46 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     542              :     }
     543              : 
     544         6491 :   TyTy::BaseType *ret_type = nullptr;
     545         6491 :   if (!function.has_function_return_type ())
     546         3243 :     ret_type = TyTy::TupleType::get_unit_type ();
     547              :   else
     548              :     {
     549         3248 :       auto resolved = TypeCheckType::Resolve (function.get_return_type ());
     550         3248 :       if (resolved->get_kind () == TyTy::TypeKind::ERROR)
     551              :         {
     552            3 :           rust_error_at (function.get_locus (),
     553              :                          "failed to resolve return type");
     554            3 :           return;
     555              :         }
     556              : 
     557         3245 :       ret_type = resolved->clone ();
     558         3245 :       ret_type->set_ref (
     559         3245 :         function.get_return_type ().get_mappings ().get_hirid ());
     560              :     }
     561              : 
     562         6488 :   std::vector<TyTy::FnParam> params;
     563         8396 :   for (auto &param : function.get_function_params ())
     564              :     {
     565              :       // get the name as well required for later on
     566         1908 :       auto param_tyty = TypeCheckType::Resolve (param.get_type ());
     567         1908 :       context->insert_type (param.get_mappings (), param_tyty);
     568         1908 :       TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
     569         1908 :       params.emplace_back (param.get_param_name ().clone_pattern (),
     570              :                            param_tyty);
     571              :     }
     572              : 
     573         6488 :   auto &nr_ctx
     574         6488 :     = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
     575              : 
     576         6488 :   CanonicalPath path
     577         6488 :     = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid ());
     578              : 
     579         6488 :   RustIdent ident{path, function.get_locus ()};
     580              : 
     581         6488 :   auto fn_type = new TyTy::FnType (
     582         6488 :     function.get_mappings ().get_hirid (),
     583         6488 :     function.get_mappings ().get_defid (),
     584         6488 :     function.get_function_name ().as_string (), ident,
     585              :     TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type,
     586              :     std::move (substitutions),
     587        12976 :     TyTy::SubstitutionArgumentMappings::empty (
     588         6488 :       context->get_lifetime_resolver ().get_num_bound_regions ()),
     589        25952 :     region_constraints);
     590              : 
     591         6488 :   context->insert_type (function.get_mappings (), fn_type);
     592              : 
     593              :   // need to get the return type from this
     594         6488 :   TyTy::FnType *resolved_fn_type = fn_type;
     595         6488 :   auto expected_ret_tyty = resolved_fn_type->get_return_type ();
     596         6488 :   context->push_return_type (TypeCheckContextItem (&function),
     597              :                              expected_ret_tyty);
     598              : 
     599         6488 :   context->switch_to_fn_body ();
     600         6488 :   auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
     601              : 
     602              :   // emit check for
     603              :   // error[E0121]: the type placeholder `_` is not allowed within types on item
     604         6488 :   const auto placeholder = ret_type->contains_infer ();
     605         6488 :   if (placeholder != nullptr && function.has_return_type ())
     606              :     {
     607              :       // FIXME
     608              :       // this will be a great place for the Default Hir Visitor we want to
     609              :       // grab the locations of the placeholders (HIR::InferredType) their
     610              :       // location, for now maybe we can use their hirid to lookup the location
     611            3 :       location_t placeholder_locus
     612            3 :         = mappings.lookup_location (placeholder->get_ref ());
     613            3 :       location_t type_locus = function.get_return_type ().get_locus ();
     614            3 :       rich_location r (line_table, placeholder_locus);
     615              : 
     616            3 :       bool have_expected_type
     617            6 :         = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
     618            3 :       if (!have_expected_type)
     619              :         {
     620            0 :           r.add_range (type_locus);
     621              :         }
     622              :       else
     623              :         {
     624            3 :           std::string fixit
     625            3 :             = "replace with the correct type " + block_expr_ty->get_name ();
     626            3 :           r.add_fixit_replace (type_locus, fixit.c_str ());
     627            3 :         }
     628              : 
     629            3 :       rust_error_at (r, ErrorCode::E0121,
     630              :                      "the type placeholder %<_%> is not allowed within types "
     631              :                      "on item signatures");
     632            3 :     }
     633              : 
     634         6488 :   location_t fn_return_locus = function.has_function_return_type ()
     635         6488 :                                  ? function.get_return_type ().get_locus ()
     636         3243 :                                  : function.get_locus ();
     637        12976 :   coercion_site (function.get_definition ().get_mappings ().get_hirid (),
     638         6488 :                  TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
     639         6488 :                  TyTy::TyWithLocation (block_expr_ty),
     640         6488 :                  function.get_definition ().get_locus ());
     641              : 
     642         6488 :   context->pop_return_type ();
     643              : 
     644         6488 :   infered = fn_type;
     645        12979 : }
     646              : 
     647              : void
     648         1203 : TypeCheckItem::visit (HIR::Module &module)
     649              : {
     650         5125 :   for (auto &item : module.get_items ())
     651         3923 :     TypeCheckItem::Resolve (*item);
     652         1202 : }
     653              : 
     654              : void
     655         4200 : TypeCheckItem::visit (HIR::Trait &trait)
     656              : {
     657         4200 :   if (trait.has_type_param_bounds ())
     658              :     {
     659         1625 :       for (auto &tp_bound : trait.get_type_param_bounds ())
     660              :         {
     661          886 :           if (tp_bound.get ()->get_bound_type ()
     662              :               == HIR::TypeParamBound::BoundType::TRAITBOUND)
     663              :             {
     664          886 :               HIR::TraitBound &tb
     665          886 :                 = static_cast<HIR::TraitBound &> (*tp_bound.get ());
     666          886 :               if (tb.get_polarity () == BoundPolarity::AntiBound)
     667              :                 {
     668            1 :                   rust_error_at (tb.get_locus (),
     669              :                                  "%<?Trait%> is not permitted in supertraits");
     670              :                 }
     671              :             }
     672              :         }
     673              :     }
     674              : 
     675         4200 :   TraitReference *trait_ref = TraitResolver::Resolve (trait);
     676         4200 :   if (trait_ref->is_error ())
     677              :     {
     678            4 :       infered = new TyTy::ErrorType (trait.get_mappings ().get_hirid ());
     679            4 :       return;
     680              :     }
     681              : 
     682         4196 :   RustIdent ident{CanonicalPath::create_empty (), trait.get_locus ()};
     683         4196 :   infered = new TyTy::DynamicObjectType (
     684         4196 :     trait.get_mappings ().get_hirid (), ident,
     685              :     {TyTy::TypeBoundPredicate (*trait_ref, BoundPolarity::RegularBound,
     686        12588 :                                trait.get_locus ())});
     687         4196 : }
     688              : 
     689              : void
     690         1590 : TypeCheckItem::visit (HIR::ExternBlock &extern_block)
     691              : {
     692         4065 :   for (auto &item : extern_block.get_extern_items ())
     693              :     {
     694         2476 :       TypeCheckTopLevelExternItem::Resolve (*item, extern_block);
     695              :     }
     696         1589 : }
     697              : 
     698              : void
     699            0 : TypeCheckItem::visit (HIR::ExternCrate &extern_crate)
     700              : {
     701            0 :   if (extern_crate.references_self ())
     702              :     return;
     703              : 
     704            0 :   auto &mappings = Analysis::Mappings::get ();
     705            0 :   CrateNum num
     706            0 :     = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
     707            0 :         .value ();
     708            0 :   HIR::Crate &crate = mappings.get_hir_crate (num);
     709              : 
     710            0 :   CrateNum saved_crate_num = mappings.get_current_crate ();
     711            0 :   mappings.set_current_crate (num);
     712            0 :   for (auto &item : crate.get_items ())
     713            0 :     TypeCheckItem::Resolve (*item);
     714            0 :   mappings.set_current_crate (saved_crate_num);
     715              : }
     716              : 
     717              : std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
     718        41267 : TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
     719              :                                                  bool &failure_flag)
     720              : {
     721        41267 :   std::vector<TyTy::SubstitutionParamMapping> substitutions;
     722        41267 :   if (impl_block.has_generics ())
     723         5935 :     resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (),
     724         5935 :                             impl_block.get_generic_params (), substitutions);
     725              : 
     726        41267 :   TyTy::RegionConstraints region_constraints;
     727        41781 :   for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
     728              :     {
     729          514 :       ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
     730              :     }
     731              : 
     732        41267 :   auto specified_bound = TyTy::TypeBoundPredicate::error ();
     733        41267 :   TraitReference *trait_reference = &TraitReference::error_node ();
     734        41267 :   if (impl_block.has_trait_ref ())
     735              :     {
     736        30476 :       auto &ref = impl_block.get_trait_ref ();
     737        30476 :       trait_reference = TraitResolver::Resolve (ref);
     738        30476 :       rust_assert (!trait_reference->is_error ());
     739              : 
     740              :       // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
     741              :       // for example
     742        60952 :       specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
     743        30476 :                                                   impl_block.get_polarity ());
     744              :     }
     745              : 
     746        41267 :   TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ());
     747        41267 :   if (self->is<TyTy::ErrorType> ())
     748              :     {
     749              :       // we cannot check for unconstrained type arguments when the Self type is
     750              :       // not resolved it will just add extra errors that dont help as well as
     751              :       // the case where this could just be a recursive type query that should
     752              :       // fail and will work later on anyway
     753            1 :       return {substitutions, region_constraints};
     754              :     }
     755              : 
     756              :   // inherit the bounds
     757        41266 :   if (!specified_bound.is_error ())
     758        60944 :     self->inherit_bounds ({specified_bound});
     759              : 
     760              :   // check for any unconstrained type-params
     761        41266 :   const TyTy::SubstitutionArgumentMappings trait_constraints
     762        41266 :     = specified_bound.get_substitution_arguments ();
     763        41266 :   const TyTy::SubstitutionArgumentMappings impl_constraints
     764        41266 :     = GetUsedSubstArgs::From (self);
     765              : 
     766        41266 :   failure_flag = check_for_unconstrained (substitutions, trait_constraints,
     767              :                                           impl_constraints, self);
     768              : 
     769        41266 :   return {substitutions, region_constraints};
     770        82534 : }
     771              : 
     772              : void
     773         5592 : TypeCheckItem::validate_trait_impl_block (
     774              :   TraitReference *trait_reference, HIR::ImplBlock &impl_block,
     775              :   TyTy::BaseType *self,
     776              :   std::vector<TyTy::SubstitutionParamMapping> &substitutions)
     777              : {
     778         5592 :   auto specified_bound = TyTy::TypeBoundPredicate::error ();
     779         5592 :   if (impl_block.has_trait_ref ())
     780              :     {
     781         4652 :       auto &ref = impl_block.get_trait_ref ();
     782         4652 :       trait_reference = TraitResolver::Resolve (ref);
     783         4652 :       if (trait_reference->is_error ())
     784            0 :         return;
     785              : 
     786              :       // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
     787              :       // for example
     788         9304 :       specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
     789         4652 :                                                   impl_block.get_polarity ());
     790              : 
     791              :       // need to check that if this specified bound has super traits does this
     792              :       // Self
     793              :       // implement them?
     794         4652 :       specified_bound.validate_type_implements_super_traits (
     795         4652 :         *self, impl_block.get_type (), impl_block.get_trait_ref ());
     796              :     }
     797              : 
     798         5592 :   bool is_trait_impl_block = !trait_reference->is_error ();
     799         5592 :   std::vector<const TraitItemReference *> trait_item_refs;
     800        13673 :   for (auto &impl_item : impl_block.get_impl_items ())
     801              :     {
     802         8081 :       if (!specified_bound.is_error ())
     803              :         {
     804         5352 :           auto trait_item_ref
     805         5352 :             = TypeCheckImplItemWithTrait::Resolve (impl_block, *impl_item, self,
     806              :                                                    specified_bound,
     807         5352 :                                                    substitutions);
     808         5352 :           if (!trait_item_ref.is_error ())
     809         5347 :             trait_item_refs.push_back (trait_item_ref.get_raw_item ());
     810         5352 :         }
     811              :     }
     812              : 
     813         5592 :   bool impl_block_missing_trait_items
     814         5592 :     = !specified_bound.is_error ()
     815         5592 :       && trait_reference->size () != trait_item_refs.size ();
     816         1604 :   if (impl_block_missing_trait_items
     817         1604 :       && impl_block.get_polarity () == BoundPolarity::RegularBound)
     818              :     {
     819              :       // filter the missing impl_items
     820         1602 :       std::vector<std::reference_wrapper<const TraitItemReference>>
     821         1602 :         missing_trait_items;
     822         5086 :       for (const auto &trait_item_ref : trait_reference->get_trait_items ())
     823              :         {
     824         3484 :           bool found = false;
     825         5362 :           for (auto implemented_trait_item : trait_item_refs)
     826              :             {
     827         3313 :               std::string trait_item_name = trait_item_ref.get_identifier ();
     828         3313 :               std::string impl_item_name
     829         3313 :                 = implemented_trait_item->get_identifier ();
     830         3313 :               found = trait_item_name == impl_item_name;
     831         3313 :               if (found)
     832              :                 break;
     833         3313 :             }
     834              : 
     835         3484 :           bool is_required_trait_item = !trait_item_ref.is_optional ();
     836         3484 :           if (!found && is_required_trait_item)
     837            7 :             missing_trait_items.emplace_back (trait_item_ref);
     838              :         }
     839              : 
     840         1602 :       if (!missing_trait_items.empty ())
     841              :         {
     842            5 :           std::string missing_items_buf;
     843            5 :           rich_location r (line_table, impl_block.get_locus ());
     844           12 :           for (size_t i = 0; i < missing_trait_items.size (); i++)
     845              :             {
     846            7 :               bool has_more = (i + 1) < missing_trait_items.size ();
     847            7 :               const TraitItemReference &missing_trait_item
     848            7 :                 = missing_trait_items.at (i);
     849            7 :               missing_items_buf += missing_trait_item.get_identifier ()
     850           21 :                                    + (has_more ? ", " : "");
     851            7 :               r.add_range (missing_trait_item.get_locus ());
     852              :             }
     853              : 
     854            5 :           rust_error_at (r, ErrorCode::E0046,
     855              :                          "missing %s in implementation of trait %qs",
     856              :                          missing_items_buf.c_str (),
     857            5 :                          trait_reference->get_name ().c_str ());
     858            5 :         }
     859         1602 :     }
     860              : 
     861         5592 :   if (is_trait_impl_block)
     862              :     {
     863         4652 :       trait_reference->clear_associated_types ();
     864              : 
     865         4652 :       AssociatedImplTrait associated (trait_reference, specified_bound,
     866         4652 :                                       &impl_block, self, context);
     867         4652 :       context->insert_associated_trait_impl (
     868         4652 :         impl_block.get_mappings ().get_hirid (), std::move (associated));
     869         4652 :       context->insert_associated_impl_mapping (
     870         4652 :         trait_reference->get_mappings ().get_hirid (), self,
     871         4652 :         impl_block.get_mappings ().get_hirid ());
     872         4652 :     }
     873         5592 : }
     874              : 
     875              : TyTy::BaseType *
     876        41260 : TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
     877              : {
     878        41260 :   return TypeCheckType::Resolve (impl_block.get_type ());
     879              : }
     880              : 
     881              : } // namespace Resolver
     882              : } // 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.