LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-substitution-mapper.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 64.8 % 256 166
Test Date: 2026-10-03 16:17:38 Functions: 57.7 % 52 30
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-substitution-mapper.h"
      20              : #include "rust-hir-type-check.h"
      21              : 
      22              : namespace Rust {
      23              : namespace Resolver {
      24              : 
      25        11373 : SubstMapper::SubstMapper (HirId ref, HIR::GenericArgs *generics,
      26              :                           const std::vector<TyTy::Region> &regions,
      27              :                           location_t locus)
      28        11373 :   : resolved (new TyTy::ErrorType (ref)), generics (generics),
      29        11373 :     regions (regions), locus (locus)
      30        11373 : {}
      31              : 
      32              : TyTy::BaseType *
      33        11376 : SubstMapper::Resolve (TyTy::BaseType *base, location_t locus,
      34              :                       HIR::GenericArgs *generics,
      35              :                       const std::vector<TyTy::Region> &regions)
      36              : {
      37        11376 :   if (!valid_type (base))
      38              :     {
      39            3 :       rich_location r (line_table, locus);
      40            3 :       r.add_fixit_remove (generics->get_locus ());
      41            3 :       rust_error_at (r, ErrorCode::E0109,
      42              :                      "generic arguments are not allowed for this type");
      43            3 :       return base;
      44            3 :     }
      45              : 
      46        11373 :   SubstMapper mapper (base->get_ref (), generics, regions, locus);
      47        11373 :   base->accept_vis (mapper);
      48        11373 :   rust_assert (mapper.resolved != nullptr);
      49              :   return mapper.resolved;
      50              : }
      51              : 
      52              : TyTy::BaseType *
      53         8031 : SubstMapper::InferSubst (TyTy::BaseType *base, location_t locus)
      54              : {
      55         8031 :   return SubstMapper::Resolve (base, locus, nullptr, {});
      56              : }
      57              : 
      58              : bool
      59        11376 : SubstMapper::valid_type (TyTy::BaseType *base)
      60              : {
      61        11376 :   bool is_fn = base->is<TyTy::FnType> ();
      62        11376 :   bool is_adt = base->is<TyTy::ADTType> ();
      63        11376 :   bool is_placeholder = base->is<TyTy::PlaceholderType> ();
      64        11376 :   bool is_projection = base->is<TyTy::ProjectionType> ();
      65              : 
      66              :   // see gcc/testsuite/rust/compile/issue-4853.rs
      67        11376 :   if (auto *dyn = base->try_as<TyTy::DynamicObjectType> ())
      68              :     {
      69            2 :       auto &bounds = dyn->get_specified_bounds ();
      70            2 :       if (bounds.size () == 1)
      71            2 :         return bounds.at (0).requires_generic_args ();
      72              :     }
      73              : 
      74        11374 :   return is_fn || is_adt || is_placeholder || is_projection;
      75              : }
      76              : 
      77              : bool
      78        11373 : SubstMapper::have_generic_args () const
      79              : {
      80        11373 :   return generics != nullptr;
      81              : }
      82              : 
      83              : void
      84         6080 : SubstMapper::visit (TyTy::FnType &type)
      85              : {
      86         6080 :   TyTy::FnType *concrete = nullptr;
      87         6080 :   if (!have_generic_args ())
      88              :     {
      89         5319 :       TyTy::BaseType *substs = type.infer_substitions (locus);
      90         5319 :       rust_assert (substs->get_kind () == TyTy::TypeKind::FNDEF);
      91              :       concrete = static_cast<TyTy::FnType *> (substs);
      92              :     }
      93              :   else
      94              :     {
      95          761 :       TyTy::SubstitutionArgumentMappings mappings
      96          761 :         = type.get_mappings_from_generic_args (*generics, regions);
      97          761 :       if (mappings.is_error ())
      98            2 :         return;
      99              : 
     100          759 :       concrete = type.handle_substitions (mappings);
     101          761 :     }
     102              : 
     103          759 :   if (concrete != nullptr)
     104         6078 :     resolved = concrete;
     105              : }
     106              : 
     107              : void
     108         5265 : SubstMapper::visit (TyTy::ADTType &type)
     109              : {
     110         5265 :   TyTy::ADTType *concrete = nullptr;
     111         5265 :   if (!have_generic_args ())
     112              :     {
     113         2712 :       TyTy::BaseType *substs = type.infer_substitions (locus);
     114         2712 :       rust_assert (substs->get_kind () == TyTy::TypeKind::ADT);
     115              :       concrete = static_cast<TyTy::ADTType *> (substs);
     116              :     }
     117              :   else
     118              :     {
     119         2553 :       TyTy::SubstitutionArgumentMappings mappings
     120         2553 :         = type.get_mappings_from_generic_args (*generics, regions);
     121         2553 :       if (mappings.is_error ())
     122            9 :         return;
     123              : 
     124         2544 :       concrete = type.handle_substitions (mappings);
     125         2553 :     }
     126              : 
     127         2544 :   if (concrete != nullptr)
     128         5256 :     resolved = concrete;
     129              : }
     130              : 
     131              : void
     132            1 : SubstMapper::visit (TyTy::DynamicObjectType &type)
     133              : {
     134            1 :   rust_assert (have_generic_args ());
     135            1 :   rust_assert (type.get_specified_bounds ().size () == 1);
     136            1 :   rust_assert (type.get_specified_bounds ().at (0).requires_generic_args ());
     137              : 
     138            1 :   TyTy::TypeBoundPredicate predicate = type.get_specified_bounds ().at (0);
     139            1 :   predicate.apply_generic_arguments (generics, false, false);
     140            1 :   if (predicate.is_error ())
     141            0 :     return;
     142              : 
     143            1 :   resolved = new TyTy::DynamicObjectType (type.get_ref (), type.get_ident (),
     144            3 :                                           {predicate});
     145            1 : }
     146              : 
     147              : void
     148            0 : SubstMapper::visit (TyTy::PlaceholderType &type)
     149              : {
     150            0 :   if (!type.can_resolve ())
     151              :     {
     152            0 :       resolved = &type;
     153            0 :       return;
     154              :     }
     155              : 
     156            0 :   resolved = SubstMapper::Resolve (type.resolve (), locus, generics, regions);
     157              : }
     158              : 
     159              : void
     160           27 : SubstMapper::visit (TyTy::ProjectionType &type)
     161              : {
     162           27 :   TyTy::ProjectionType *concrete = nullptr;
     163           27 :   if (!have_generic_args ())
     164              :     {
     165            0 :       TyTy::BaseType *substs = type.infer_substitions (locus);
     166            0 :       rust_assert (substs->get_kind () == TyTy::TypeKind::PROJECTION);
     167              :       concrete = static_cast<TyTy::ProjectionType *> (substs);
     168              :     }
     169              :   else
     170              :     {
     171           27 :       TyTy::SubstitutionArgumentMappings mappings
     172           27 :         = type.get_mappings_from_generic_args (*generics, regions);
     173           27 :       if (mappings.is_error ())
     174            0 :         return;
     175              : 
     176           27 :       concrete = type.handle_substitions (mappings);
     177           27 :     }
     178              : 
     179           27 :   if (concrete != nullptr)
     180           27 :     resolved = concrete;
     181              : }
     182              : 
     183       109558 : SubstMapperInternal::SubstMapperInternal (
     184              :   HirId ref, TyTy::SubstitutionArgumentMappings &mappings)
     185       109558 :   : resolved (new TyTy::ErrorType (ref)), mappings (mappings)
     186       109558 : {}
     187              : 
     188              : TyTy::BaseType *
     189       109558 : SubstMapperInternal::Resolve (TyTy::BaseType *base,
     190              :                               TyTy::SubstitutionArgumentMappings &mappings)
     191              : {
     192       109558 :   auto context = TypeCheckContext::get ();
     193              : 
     194       109558 :   SubstMapperInternal mapper (base->get_ref (), mappings);
     195       109558 :   base->accept_vis (mapper);
     196       109558 :   rust_assert (mapper.resolved != nullptr);
     197              : 
     198              :   // insert these new implict types into the context
     199       109558 :   TyTy::BaseType *unused = nullptr;
     200       109558 :   bool is_ty_available
     201       109558 :     = context->lookup_type (mapper.resolved->get_ty_ref (), &unused);
     202       109558 :   if (!is_ty_available)
     203              :     {
     204        27965 :       context->insert_type (
     205        27965 :         Analysis::NodeMapping (0, 0, mapper.resolved->get_ty_ref (), 0),
     206              :         mapper.resolved);
     207              :     }
     208       109558 :   bool is_ref_available
     209       109558 :     = context->lookup_type (mapper.resolved->get_ref (), &unused);
     210       109558 :   if (!is_ref_available)
     211              :     {
     212        58671 :       context->insert_type (Analysis::NodeMapping (0, 0,
     213              :                                                    mapper.resolved->get_ref (),
     214        58671 :                                                    0),
     215              :                             mapper.resolved);
     216              :     }
     217              : 
     218       109558 :   return mapper.resolved;
     219              : }
     220              : 
     221              : bool
     222            0 : SubstMapperInternal::mappings_are_bound (
     223              :   TyTy::BaseType *tyseg, TyTy::SubstitutionArgumentMappings &mappings)
     224              : {
     225            0 :   if (tyseg->get_kind () == TyTy::TypeKind::ADT)
     226              :     {
     227            0 :       TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (tyseg);
     228            0 :       return adt->are_mappings_bound (mappings);
     229              :     }
     230            0 :   else if (tyseg->get_kind () == TyTy::TypeKind::FNDEF)
     231              :     {
     232            0 :       TyTy::FnType *fn = static_cast<TyTy::FnType *> (tyseg);
     233            0 :       return fn->are_mappings_bound (mappings);
     234              :     }
     235              : 
     236              :   return false;
     237              : }
     238              : 
     239              : void
     240         7356 : SubstMapperInternal::visit (TyTy::FnType &type)
     241              : {
     242         7356 :   TyTy::SubstitutionArgumentMappings adjusted
     243         7356 :     = type.adjust_mappings_for_this (mappings);
     244         7356 :   if (adjusted.is_error () && !mappings.trait_item_mode ())
     245            0 :     return;
     246         7356 :   if (adjusted.is_error () && mappings.trait_item_mode ())
     247            0 :     adjusted = mappings;
     248              : 
     249         7356 :   TyTy::BaseType *concrete = type.handle_substitions (adjusted);
     250         7356 :   if (concrete != nullptr)
     251         7356 :     resolved = concrete;
     252         7356 : }
     253              : 
     254              : void
     255         4031 : SubstMapperInternal::visit (TyTy::ADTType &type)
     256              : {
     257         4031 :   TyTy::SubstitutionArgumentMappings adjusted
     258         4031 :     = type.adjust_mappings_for_this (mappings);
     259         4031 :   if (adjusted.is_error () && !mappings.trait_item_mode ())
     260            0 :     return;
     261         4031 :   if (adjusted.is_error () && mappings.trait_item_mode ())
     262           12 :     adjusted = mappings;
     263              : 
     264         4031 :   TyTy::BaseType *concrete = type.handle_substitions (adjusted);
     265         4031 :   if (concrete != nullptr)
     266         4031 :     resolved = concrete;
     267         4031 : }
     268              : 
     269              : // these don't support generic arguments but might contain a type param
     270              : void
     271          305 : SubstMapperInternal::visit (TyTy::TupleType &type)
     272              : {
     273          305 :   resolved = type.handle_substitions (mappings);
     274          305 : }
     275              : 
     276              : void
     277        11151 : SubstMapperInternal::visit (TyTy::ReferenceType &type)
     278              : {
     279        11151 :   resolved = type.handle_substitions (mappings);
     280        11151 : }
     281              : 
     282              : void
     283         3403 : SubstMapperInternal::visit (TyTy::PointerType &type)
     284              : {
     285         3403 :   resolved = type.handle_substitions (mappings);
     286         3403 : }
     287              : 
     288              : void
     289        75214 : SubstMapperInternal::visit (TyTy::ParamType &type)
     290              : {
     291        75214 :   resolved = type.handle_substitions (mappings);
     292        75214 : }
     293              : 
     294              : void
     295           63 : SubstMapperInternal::visit (TyTy::ConstParamType &type)
     296              : {
     297           63 :   resolved = type.handle_substitions (mappings);
     298           63 : }
     299              : 
     300              : void
     301            0 : SubstMapperInternal::visit (TyTy::ConstValueType &type)
     302              : {
     303            0 :   resolved = type.clone ();
     304            0 : }
     305              : 
     306              : void
     307            0 : SubstMapperInternal::visit (TyTy::ConstInferType &type)
     308              : {
     309            0 :   resolved = type.clone ();
     310            0 : }
     311              : 
     312              : void
     313            0 : SubstMapperInternal::visit (TyTy::ConstErrorType &type)
     314              : {
     315            0 :   resolved = type.clone ();
     316            0 : }
     317              : 
     318              : void
     319            0 : SubstMapperInternal::visit (TyTy::PlaceholderType &type)
     320              : {
     321            0 :   rust_assert (type.can_resolve ());
     322            0 :   if (mappings.trait_item_mode ())
     323              :     {
     324            0 :       resolved = type.resolve ();
     325              :     }
     326              :   else
     327              :     {
     328            0 :       resolved = SubstMapperInternal::Resolve (type.resolve (), mappings);
     329              :     }
     330            0 : }
     331              : 
     332              : void
     333         6132 : SubstMapperInternal::visit (TyTy::ProjectionType &type)
     334              : {
     335         6132 :   resolved = type.handle_substitions (mappings);
     336         6132 : }
     337              : 
     338              : void
     339            0 : SubstMapperInternal::visit (TyTy::ClosureType &type)
     340              : {
     341            0 :   resolved = type.handle_substitions (mappings);
     342            0 : }
     343              : 
     344              : void
     345           63 : SubstMapperInternal::visit (TyTy::ArrayType &type)
     346              : {
     347           63 :   resolved = type.handle_substitions (mappings);
     348           63 : }
     349              : 
     350              : void
     351         1647 : SubstMapperInternal::visit (TyTy::SliceType &type)
     352              : {
     353         1647 :   resolved = type.handle_substitions (mappings);
     354         1647 : }
     355              : void
     356            9 : SubstMapperInternal::visit (TyTy::FnPtr &type)
     357              : {
     358            9 :   resolved = type.handle_substitions (mappings);
     359            9 : }
     360              : 
     361              : // nothing to do for these
     362              : void
     363            0 : SubstMapperInternal::visit (TyTy::InferType &type)
     364              : {
     365            0 :   resolved = type.clone ();
     366            0 : }
     367              : void
     368            0 : SubstMapperInternal::visit (TyTy::BoolType &type)
     369              : {
     370            0 :   resolved = type.clone ();
     371            0 : }
     372              : void
     373           44 : SubstMapperInternal::visit (TyTy::IntType &type)
     374              : {
     375           44 :   resolved = type.clone ();
     376           44 : }
     377              : void
     378           75 : SubstMapperInternal::visit (TyTy::UintType &type)
     379              : {
     380           75 :   resolved = type.clone ();
     381           75 : }
     382              : void
     383            0 : SubstMapperInternal::visit (TyTy::FloatType &type)
     384              : {
     385            0 :   resolved = type.clone ();
     386            0 : }
     387              : void
     388            7 : SubstMapperInternal::visit (TyTy::USizeType &type)
     389              : {
     390            7 :   resolved = type.clone ();
     391            7 : }
     392              : void
     393           56 : SubstMapperInternal::visit (TyTy::ISizeType &type)
     394              : {
     395           56 :   resolved = type.clone ();
     396           56 : }
     397              : void
     398            0 : SubstMapperInternal::visit (TyTy::ErrorType &type)
     399              : {
     400            0 :   resolved = type.clone ();
     401            0 : }
     402              : void
     403            0 : SubstMapperInternal::visit (TyTy::CharType &type)
     404              : {
     405            0 :   resolved = type.clone ();
     406            0 : }
     407              : void
     408            0 : SubstMapperInternal::visit (TyTy::StrType &type)
     409              : {
     410            0 :   resolved = type.clone ();
     411            0 : }
     412              : void
     413            0 : SubstMapperInternal::visit (TyTy::NeverType &type)
     414              : {
     415            0 :   resolved = type.clone ();
     416            0 : }
     417              : void
     418            2 : SubstMapperInternal::visit (TyTy::DynamicObjectType &type)
     419              : {
     420            2 :   resolved = type.clone ();
     421            2 : }
     422              : void
     423            0 : SubstMapperInternal::visit (TyTy::OpaqueType &type)
     424              : {
     425            0 :   resolved = type.clone ();
     426            0 : }
     427              : 
     428              : // SubstMapperFromExisting
     429              : 
     430            0 : SubstMapperFromExisting::SubstMapperFromExisting (TyTy::BaseType *concrete,
     431              :                                                   TyTy::BaseType *receiver)
     432            0 :   : concrete (concrete), receiver (receiver), resolved (nullptr)
     433            0 : {}
     434              : 
     435              : TyTy::BaseType *
     436            0 : SubstMapperFromExisting::Resolve (TyTy::BaseType *concrete,
     437              :                                   TyTy::BaseType *receiver)
     438              : {
     439            0 :   rust_assert (concrete->get_kind () == receiver->get_kind ());
     440              : 
     441            0 :   SubstMapperFromExisting mapper (concrete, receiver);
     442            0 :   concrete->accept_vis (mapper);
     443            0 :   return mapper.resolved;
     444              : }
     445              : 
     446              : void
     447            0 : SubstMapperFromExisting::visit (TyTy::FnType &type)
     448              : {
     449            0 :   rust_assert (type.was_substituted ());
     450              : 
     451            0 :   TyTy::FnType *to_sub = static_cast<TyTy::FnType *> (receiver);
     452            0 :   resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
     453            0 : }
     454              : 
     455              : void
     456            0 : SubstMapperFromExisting::visit (TyTy::ADTType &type)
     457              : {
     458            0 :   rust_assert (type.was_substituted ());
     459              : 
     460            0 :   TyTy::ADTType *to_sub = static_cast<TyTy::ADTType *> (receiver);
     461            0 :   resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
     462            0 : }
     463              : 
     464              : void
     465            0 : SubstMapperFromExisting::visit (TyTy::ClosureType &type)
     466              : {
     467            0 :   rust_assert (type.was_substituted ());
     468              : 
     469            0 :   TyTy::ClosureType *to_sub = static_cast<TyTy::ClosureType *> (receiver);
     470            0 :   resolved = to_sub->handle_substitions (type.get_substitution_arguments ());
     471            0 : }
     472              : 
     473              : // GetUsedSubstArgs
     474              : 
     475        36724 : GetUsedSubstArgs::GetUsedSubstArgs ()
     476        36724 :   : args (TyTy::SubstitutionArgumentMappings::error ())
     477        36724 : {}
     478              : 
     479              : TyTy::SubstitutionArgumentMappings
     480        36724 : GetUsedSubstArgs::From (const TyTy::BaseType *from)
     481              : {
     482        36724 :   GetUsedSubstArgs mapper;
     483        36724 :   from->accept_vis (mapper);
     484        36724 :   return mapper.args;
     485        36724 : }
     486              : 
     487              : void
     488            0 : GetUsedSubstArgs::visit (const TyTy::FnType &type)
     489              : {
     490            0 :   args = type.get_substitution_arguments ();
     491            0 : }
     492              : 
     493              : void
     494         8778 : GetUsedSubstArgs::visit (const TyTy::ADTType &type)
     495              : {
     496         8778 :   args = type.get_substitution_arguments ();
     497         8778 : }
     498              : 
     499              : void
     500            0 : GetUsedSubstArgs::visit (const TyTy::ClosureType &type)
     501              : {
     502            0 :   args = type.get_substitution_arguments ();
     503            0 : }
     504              : 
     505              : } // namespace Resolver
     506              : } // 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.