LCOV - code coverage report
Current view: top level - gcc/rust/typecheck - rust-hir-type-check-base.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 94.6 % 461 436
Test Date: 2026-10-03 16:17:38 Functions: 100.0 % 10 10
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-base.h"
      20              : #include "options.h"
      21              : #include "rust-compile-base.h"
      22              : #include "rust-hir-item.h"
      23              : #include "rust-hir-type-check-expr.h"
      24              : #include "rust-hir-type-check-type.h"
      25              : #include "rust-hir-trait-resolve.h"
      26              : #include "rust-type-util.h"
      27              : #include "rust-attribute-values.h"
      28              : #include "rust-tyty.h"
      29              : 
      30              : namespace Rust {
      31              : namespace Resolver {
      32              : 
      33       959110 : TypeCheckBase::TypeCheckBase ()
      34       959110 :   : mappings (Analysis::Mappings::get ()), context (TypeCheckContext::get ())
      35       959110 : {}
      36              : 
      37              : void
      38           46 : TypeCheckBase::ResolveGenericParams (
      39              :   const HIR::Item::ItemKind item_kind, location_t item_locus,
      40              :   const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
      41              :   std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
      42              :   ABI abi)
      43              : {
      44           46 :   TypeCheckBase ctx;
      45           46 :   ctx.resolve_generic_params (item_kind, item_locus, generic_params,
      46              :                               substitutions, is_foreign, abi);
      47           46 : }
      48              : 
      49              : TyTy::TypeBoundPredicate
      50         1466 : TypeCheckBase::ResolvePredicateFromBound (
      51              :   HIR::TypePath &path,
      52              :   tl::optional<std::reference_wrapper<HIR::Type>> associated_self,
      53              :   BoundPolarity polarity, bool is_qualified_type, bool is_super_trait)
      54              : {
      55         1466 :   TypeCheckBase ctx;
      56         1466 :   return ctx.get_predicate_from_bound (path, associated_self, polarity,
      57         1466 :                                        is_qualified_type, is_super_trait);
      58         1466 : }
      59              : 
      60              : static void walk_type_to_constrain (std::set<HirId> &constrained_symbols,
      61              :                                     TyTy::BaseType &r);
      62              : 
      63              : static void
      64        13137 : walk_types_to_constrain (std::set<HirId> &constrained_symbols,
      65              :                          const TyTy::SubstitutionArgumentMappings &constraints)
      66              : {
      67        21045 :   for (const auto &c : constraints.get_mappings ())
      68              :     {
      69         7908 :       auto arg = c.get_tyty ();
      70         7908 :       if (arg != nullptr)
      71              :         {
      72         7908 :           const auto p = arg->get_root ();
      73         7908 :           constrained_symbols.insert (p->get_ref ());
      74         7908 :           constrained_symbols.insert (p->get_ty_ref ());
      75         7908 :           walk_type_to_constrain (constrained_symbols, *arg);
      76              : 
      77         7908 :           if (p->has_substitutions_defined ())
      78              :             {
      79          273 :               walk_types_to_constrain (constrained_symbols,
      80              :                                        p->get_subst_argument_mappings ());
      81              :             }
      82              :         }
      83              :     }
      84        13137 : }
      85              : 
      86              : static void
      87        14368 : walk_type_to_constrain (std::set<HirId> &constrained_symbols, TyTy::BaseType &r)
      88              : {
      89        15293 :   switch (r.get_kind ())
      90              :     {
      91          193 :     case TyTy::TypeKind::POINTER:
      92          193 :       {
      93          193 :         auto &p = static_cast<TyTy::PointerType &> (r);
      94          193 :         walk_type_to_constrain (constrained_symbols, *p.get_base ());
      95              :       }
      96          193 :       break;
      97          473 :     case TyTy::TypeKind::REF:
      98          473 :       {
      99          473 :         auto &ref = static_cast<TyTy::ReferenceType &> (r);
     100          473 :         walk_type_to_constrain (constrained_symbols, *ref.get_base ());
     101              :       }
     102          473 :       break;
     103           11 :     case TyTy::TypeKind::ARRAY:
     104           11 :       {
     105           11 :         auto &arr = static_cast<TyTy::ArrayType &> (r);
     106           11 :         walk_type_to_constrain (constrained_symbols, *arr.get_element_type ());
     107           11 :         walk_type_to_constrain (constrained_symbols, *arr.get_capacity ());
     108              :       }
     109           11 :       break;
     110            0 :     case TyTy::TypeKind::FNDEF:
     111            0 :       {
     112            0 :         auto &fn = static_cast<TyTy::FnType &> (r);
     113            0 :         for (auto &param : fn.get_params ())
     114            0 :           walk_type_to_constrain (constrained_symbols, *param.get_type ());
     115            0 :         walk_type_to_constrain (constrained_symbols, *fn.get_return_type ());
     116              :       }
     117            0 :       break;
     118         3095 :     case TyTy::TypeKind::PARAM:
     119         3095 :       {
     120         3095 :         auto &param = static_cast<TyTy::ParamType &> (r);
     121         3095 :         constrained_symbols.insert (param.get_ty_ref ());
     122              :       }
     123         3095 :       break;
     124           55 :     case TyTy::TypeKind::CONST:
     125           55 :       {
     126           55 :         auto *constant = r.as_const_type ();
     127           55 :         if (constant->const_kind () == TyTy::BaseConstType::ConstKind::Decl)
     128           36 :           constrained_symbols.insert (r.get_ty_ref ());
     129              :       }
     130              :       break;
     131          225 :     case TyTy::SLICE:
     132          225 :       {
     133          225 :         auto &slice = static_cast<TyTy::SliceType &> (r);
     134          225 :         walk_type_to_constrain (constrained_symbols,
     135          225 :                                 *slice.get_element_type ());
     136              :       }
     137          225 :       break;
     138           23 :     case TyTy::FNPTR:
     139           23 :       {
     140           23 :         auto &ptr = static_cast<TyTy::FnPtr &> (r);
     141           24 :         for (auto &param : ptr.get_params ())
     142            1 :           walk_type_to_constrain (constrained_symbols, *param.get_tyty ());
     143           23 :         walk_type_to_constrain (constrained_symbols, *ptr.get_return_type ());
     144              :       }
     145           23 :       break;
     146           16 :     case TyTy::TUPLE:
     147           16 :       {
     148           16 :         auto &tuple = static_cast<TyTy::TupleType &> (r);
     149           30 :         for (auto &ty : tuple.get_fields ())
     150           14 :           walk_type_to_constrain (constrained_symbols, *ty.get_tyty ());
     151              :       }
     152              :       break;
     153           11 :     case TyTy::DYNAMIC:
     154           11 :       {
     155           11 :         auto &dyn = static_cast<TyTy::DynamicObjectType &> (r);
     156           11 :         constrained_symbols.insert (dyn.get_ty_ref ());
     157              :       }
     158           11 :       break;
     159            0 :     case TyTy::CLOSURE:
     160            0 :       {
     161            0 :         auto &clos = static_cast<TyTy::ClosureType &> (r);
     162            0 :         walk_type_to_constrain (constrained_symbols, clos.get_parameters ());
     163            0 :         walk_type_to_constrain (constrained_symbols, *clos.get_return_type ());
     164              :       }
     165            0 :       break;
     166              :     default:
     167              :       break;
     168              :     }
     169        14368 : }
     170              : 
     171              : bool
     172        34858 : TypeCheckBase::check_for_unconstrained (
     173              :   const std::vector<TyTy::SubstitutionParamMapping> &params_to_constrain,
     174              :   const TyTy::SubstitutionArgumentMappings &constraint_a,
     175              :   const TyTy::SubstitutionArgumentMappings &constraint_b,
     176              :   TyTy::BaseType *reference)
     177              : {
     178        34858 :   bool check_result = false;
     179        34858 :   bool check_completed
     180        34858 :     = context->have_checked_for_unconstrained (reference->get_ref (),
     181              :                                                &check_result);
     182        34858 :   if (check_completed)
     183        28426 :     return check_result;
     184              : 
     185         6432 :   std::set<HirId> symbols_to_constrain;
     186         6432 :   std::map<HirId, location_t> symbol_to_location;
     187         7550 :   for (const auto &p : params_to_constrain)
     188              :     {
     189         1118 :       HirId ref = p.get_param_ty ()->get_ref ();
     190         1118 :       symbols_to_constrain.insert (ref);
     191         1118 :       symbol_to_location.insert ({ref, p.get_param_locus ()});
     192              :     }
     193              : 
     194              :   // set up the set of constrained symbols
     195         6432 :   std::set<HirId> constrained_symbols;
     196         6432 :   walk_types_to_constrain (constrained_symbols, constraint_a);
     197         6432 :   walk_types_to_constrain (constrained_symbols, constraint_b);
     198         6432 :   walk_type_to_constrain (constrained_symbols, *reference);
     199              : 
     200         7550 :   for (const auto &param : params_to_constrain)
     201              :     {
     202         1118 :       auto *ty = param.get_param_ty ();
     203         2391 :       for (const auto &bound : ty->get_specified_bounds ())
     204              :         {
     205         1273 :           const auto &args = bound.get_substitution_arguments ();
     206         1275 :           for (const auto &binding : args.get_binding_args ())
     207            2 :             walk_type_to_constrain (constrained_symbols, *binding.second);
     208              :         }
     209              :     }
     210              : 
     211              :   // check for unconstrained
     212         6432 :   bool unconstrained = false;
     213         7550 :   for (auto &sym : symbols_to_constrain)
     214              :     {
     215         1118 :       bool used = constrained_symbols.find (sym) != constrained_symbols.end ();
     216         1118 :       if (!used)
     217              :         {
     218            4 :           location_t locus = symbol_to_location.at (sym);
     219            4 :           rust_error_at (locus, "unconstrained type parameter");
     220            4 :           unconstrained = true;
     221              :         }
     222              :     }
     223              : 
     224         6432 :   context->insert_unconstrained_check_marker (reference->get_ref (),
     225              :                                               unconstrained);
     226              : 
     227         6432 :   return unconstrained;
     228         6432 : }
     229              : 
     230              : TyTy::BaseType *
     231        21842 : TypeCheckBase::resolve_literal (const Analysis::NodeMapping &expr_mappings,
     232              :                                 HIR::Literal &literal, location_t locus)
     233              : {
     234        21842 :   TyTy::BaseType *infered = nullptr;
     235        21842 :   switch (literal.get_lit_type ())
     236              :     {
     237        17057 :     case HIR::Literal::LitType::INT:
     238        17057 :       {
     239        17057 :         bool ok = false;
     240              : 
     241        17057 :         switch (literal.get_type_hint ())
     242              :           {
     243          110 :           case CORETYPE_I8:
     244          110 :             ok = context->lookup_builtin ("i8", &infered);
     245          110 :             break;
     246           86 :           case CORETYPE_I16:
     247           86 :             ok = context->lookup_builtin ("i16", &infered);
     248           86 :             break;
     249          259 :           case CORETYPE_I32:
     250          259 :             ok = context->lookup_builtin ("i32", &infered);
     251          259 :             break;
     252           88 :           case CORETYPE_I64:
     253           88 :             ok = context->lookup_builtin ("i64", &infered);
     254           88 :             break;
     255           14 :           case CORETYPE_I128:
     256           14 :             ok = context->lookup_builtin ("i128", &infered);
     257           14 :             break;
     258              : 
     259          136 :           case CORETYPE_U8:
     260          136 :             ok = context->lookup_builtin ("u8", &infered);
     261          136 :             break;
     262          131 :           case CORETYPE_U16:
     263          131 :             ok = context->lookup_builtin ("u16", &infered);
     264          131 :             break;
     265          221 :           case CORETYPE_U32:
     266          221 :             ok = context->lookup_builtin ("u32", &infered);
     267          221 :             break;
     268          120 :           case CORETYPE_U64:
     269          120 :             ok = context->lookup_builtin ("u64", &infered);
     270          120 :             break;
     271           17 :           case CORETYPE_U128:
     272           17 :             ok = context->lookup_builtin ("u128", &infered);
     273           17 :             break;
     274              : 
     275          466 :           case CORETYPE_F32:
     276          466 :             literal.set_lit_type (HIR::Literal::LitType::FLOAT);
     277          466 :             ok = context->lookup_builtin ("f32", &infered);
     278          466 :             break;
     279          205 :           case CORETYPE_F64:
     280          205 :             literal.set_lit_type (HIR::Literal::LitType::FLOAT);
     281          205 :             ok = context->lookup_builtin ("f64", &infered);
     282          205 :             break;
     283              : 
     284            4 :           case CORETYPE_ISIZE:
     285            4 :             ok = context->lookup_builtin ("isize", &infered);
     286            4 :             break;
     287              : 
     288           50 :           case CORETYPE_USIZE:
     289           50 :             ok = context->lookup_builtin ("usize", &infered);
     290           50 :             break;
     291              : 
     292        15150 :           default:
     293        15150 :             ok = true;
     294        15150 :             infered
     295        15150 :               = new TyTy::InferType (expr_mappings.get_hirid (),
     296              :                                      TyTy::InferType::InferTypeKind::INTEGRAL,
     297              :                                      TyTy::InferType::TypeHint::Default (),
     298        15150 :                                      locus);
     299        15150 :             break;
     300              :           }
     301        17057 :         rust_assert (ok);
     302              :       }
     303              :       break;
     304              : 
     305          346 :     case HIR::Literal::LitType::FLOAT:
     306          346 :       {
     307          346 :         bool ok = false;
     308              : 
     309          346 :         switch (literal.get_type_hint ())
     310              :           {
     311           35 :           case CORETYPE_F32:
     312           35 :             ok = context->lookup_builtin ("f32", &infered);
     313           35 :             break;
     314           19 :           case CORETYPE_F64:
     315           19 :             ok = context->lookup_builtin ("f64", &infered);
     316           19 :             break;
     317              : 
     318          292 :           default:
     319          292 :             ok = true;
     320          292 :             infered
     321          292 :               = new TyTy::InferType (expr_mappings.get_hirid (),
     322              :                                      TyTy::InferType::InferTypeKind::FLOAT,
     323              :                                      TyTy::InferType::TypeHint::Default (),
     324          292 :                                      locus);
     325          292 :             break;
     326              :           }
     327          346 :         rust_assert (ok);
     328              :       }
     329              :       break;
     330              : 
     331         1330 :     case HIR::Literal::LitType::BOOL:
     332         1330 :       {
     333         1330 :         auto ok = context->lookup_builtin ("bool", &infered);
     334         1330 :         rust_assert (ok);
     335              :       }
     336              :       break;
     337              : 
     338          186 :     case HIR::Literal::LitType::CHAR:
     339          186 :       {
     340          186 :         auto ok = context->lookup_builtin ("char", &infered);
     341          186 :         rust_assert (ok);
     342              :       }
     343              :       break;
     344              : 
     345          408 :     case HIR::Literal::LitType::BYTE:
     346          408 :       {
     347          408 :         auto ok = context->lookup_builtin ("u8", &infered);
     348          408 :         rust_assert (ok);
     349              :       }
     350              :       break;
     351              : 
     352         2465 :     case HIR::Literal::LitType::STRING:
     353         2465 :       {
     354         2465 :         TyTy::BaseType *base = nullptr;
     355         2465 :         auto ok = context->lookup_builtin ("str", &base);
     356         2465 :         rust_assert (ok);
     357              : 
     358         4930 :         infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
     359         2465 :                                            TyTy::TyVar (base->get_ref ()),
     360              :                                            Mutability::Imm,
     361         4930 :                                            TyTy::Region::make_static ());
     362              :       }
     363         2465 :       break;
     364              : 
     365           35 :     case HIR::Literal::LitType::BYTE_STRING:
     366           35 :       {
     367              :         /* This is an arraytype of u8 reference (&[u8;size]). It isn't in
     368              :            UTF-8, but really just a byte array. Code to construct the array
     369              :            reference copied from ArrayElemsValues and ArrayType. */
     370           35 :         TyTy::BaseType *u8;
     371           35 :         auto ok = context->lookup_builtin ("u8", &u8);
     372           35 :         rust_assert (ok);
     373              : 
     374           35 :         auto crate_num = mappings.get_current_crate ();
     375           35 :         Analysis::NodeMapping capacity_mapping (crate_num, UNKNOWN_NODEID,
     376           35 :                                                 mappings.get_next_hir_id (
     377              :                                                   crate_num),
     378           35 :                                                 UNKNOWN_LOCAL_DEFID);
     379              : 
     380              :         /* Capacity is the size of the string (number of chars).
     381              :            It is a constant, but for fold it to get a tree.  */
     382           35 :         std::string capacity_str
     383           35 :           = std::to_string (literal.as_string ().size ());
     384           35 :         HIR::LiteralExpr *literal_capacity
     385              :           = new HIR::LiteralExpr (capacity_mapping, capacity_str,
     386              :                                   HIR::Literal::LitType::INT,
     387           70 :                                   PrimitiveCoreType::CORETYPE_USIZE, locus, {});
     388              : 
     389              :         // mark the type for this implicit node
     390           35 :         TyTy::BaseType *expected_ty = nullptr;
     391           35 :         ok = context->lookup_builtin ("usize", &expected_ty);
     392           35 :         rust_assert (ok);
     393           35 :         context->insert_type (capacity_mapping, expected_ty);
     394              : 
     395           35 :         Analysis::NodeMapping array_mapping (crate_num, UNKNOWN_NODEID,
     396           35 :                                              mappings.get_next_hir_id (
     397              :                                                crate_num),
     398           35 :                                              UNKNOWN_LOCAL_DEFID);
     399              : 
     400           35 :         auto ctx = Compile::Context::get ();
     401           35 :         tree capacity = Compile::HIRCompileBase::query_compile_const_expr (
     402              :           ctx, expected_ty, *literal_capacity);
     403              : 
     404           35 :         HirId capacity_expr_id = literal_capacity->get_mappings ().get_hirid ();
     405           35 :         auto capacity_expr
     406              :           = new TyTy::ConstValueType (capacity, expected_ty, capacity_expr_id,
     407           35 :                                       capacity_expr_id);
     408           35 :         context->insert_type (literal_capacity->get_mappings (),
     409           35 :                               capacity_expr->as_base_type ());
     410              : 
     411           35 :         TyTy::ArrayType *array = new TyTy::ArrayType (
     412              :           array_mapping.get_hirid (), locus,
     413           35 :           TyTy::TyVar (capacity_expr->as_base_type ()->get_ty_ref ()),
     414           70 :           TyTy::TyVar (u8->get_ref ()));
     415           35 :         context->insert_type (array_mapping, array);
     416              : 
     417           70 :         infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
     418           35 :                                            TyTy::TyVar (array->get_ref ()),
     419              :                                            Mutability::Imm,
     420           70 :                                            TyTy::Region::make_static ());
     421           35 :       }
     422           35 :       break;
     423           15 :     case HIR::Literal::LitType::C_STRING:
     424           15 :       {
     425              :         // Throw error if C string literal contains null byte
     426           30 :         if (literal.as_string ().find ('\0') != std::string::npos)
     427              :           {
     428            1 :             rust_error_at (
     429              :               locus, "null characters in C string literals are not supported");
     430            1 :             infered = new TyTy::ErrorType (expr_mappings.get_hirid (), locus);
     431            1 :             break;
     432              :           }
     433              : 
     434           14 :         auto lang_item_defined
     435           14 :           = mappings.lookup_lang_item (LangItem::Kind::CSTR);
     436              : 
     437           14 :         if (!lang_item_defined)
     438              :           {
     439            0 :             rust_error_at (locus, "unable to find lang item: %<c_str%>");
     440            0 :             infered = new TyTy::ErrorType (expr_mappings.get_hirid (), locus);
     441            0 :             break;
     442              :           }
     443              : 
     444           14 :         DefId cstr_defid = lang_item_defined.value ();
     445           14 :         HIR::Item *item = mappings.lookup_defid (cstr_defid).value ();
     446              : 
     447           14 :         TyTy::BaseType *item_type = nullptr;
     448           14 :         bool ok = context->lookup_type (item->get_mappings ().get_hirid (),
     449              :                                         &item_type);
     450              : 
     451           14 :         rust_assert (ok);
     452           14 :         rust_assert (item_type->get_kind () == TyTy::TypeKind::ADT);
     453              : 
     454           28 :         infered = new TyTy::ReferenceType (expr_mappings.get_hirid (),
     455           14 :                                            TyTy::TyVar (item_type->get_ref ()),
     456              :                                            Mutability::Imm,
     457           28 :                                            TyTy::Region::make_static ());
     458              :       }
     459           14 :       break;
     460            0 :     default:
     461            0 :       rust_unreachable ();
     462        21842 :       break;
     463              :     }
     464              : 
     465        21842 :   return infered;
     466              : }
     467              : 
     468              : TyTy::ADTType::ReprOptions
     469         3271 : TypeCheckBase::parse_repr_options (const AST::AttrVec &attrs, location_t locus)
     470              : {
     471         3271 :   TyTy::ADTType::ReprOptions repr;
     472         3271 :   repr.pack = 0;
     473         3271 :   repr.align = 0;
     474              : 
     475              :   // Default repr for enums is isize, but we now check for other repr in the
     476              :   // attributes.
     477         3271 :   bool ok = context->lookup_builtin ("isize", &repr.repr);
     478         3271 :   rust_assert (ok);
     479              : 
     480         3727 :   for (const auto &attr : attrs)
     481              :     {
     482          527 :       bool is_repr = attr.get_path ().as_string () == Values::Attributes::REPR;
     483          527 :       if (is_repr && !attr.has_attr_input ())
     484              :         {
     485            1 :           rust_error_at (attr.get_locus (), "malformed %<repr%> attribute");
     486            1 :           continue;
     487              :         }
     488              : 
     489          526 :       if (is_repr)
     490              :         {
     491           73 :           const AST::AttrInput &input = attr.get_attr_input ();
     492           73 :           bool is_token_tree = input.get_attr_input_type ()
     493           73 :                                == AST::AttrInput::AttrInputType::TOKEN_TREE;
     494           73 :           bool is_meta_item = input.get_attr_input_type ()
     495           73 :                               == AST::AttrInput::AttrInputType::META_ITEM;
     496           73 :           if (!is_token_tree && !is_meta_item)
     497              :             {
     498            1 :               rust_error_at (attr.get_locus (), "malformed %<repr%> attribute");
     499            2 :               continue;
     500              :             }
     501              : 
     502           72 :           const AST::AttrInputMetaItemContainer *meta_items = nullptr;
     503           72 :           if (is_token_tree)
     504              :             {
     505           71 :               const auto &option
     506              :                 = static_cast<const AST::DelimTokenTree &> (input);
     507           71 :               meta_items = option.parse_to_meta_item ();
     508              :             }
     509              :           else
     510              :             { // is_meta_item is true
     511            1 :               const auto &option
     512              :                 = static_cast<const AST::AttrInputMetaItemContainer &> (input);
     513            1 :               meta_items = new AST::AttrInputMetaItemContainer (option);
     514              :             }
     515              : 
     516           72 :           if (meta_items == nullptr)
     517              :             {
     518            0 :               rust_error_at (attr.get_locus (), "malformed %qs attribute",
     519              :                              "repr");
     520            0 :               continue;
     521              :             }
     522              : 
     523           72 :           auto &items = meta_items->get_items ();
     524           72 :           if (items.size () == 0)
     525              :             {
     526              :               // nothing to do with this its empty
     527            1 :               delete meta_items;
     528            1 :               continue;
     529              :             }
     530              : 
     531           71 :           const std::string repr_option = items.at (0)->as_string ();
     532              : 
     533              :           // TODO: it would probably be better to make the MetaItems more aware
     534              :           // of constructs with nesting like #[repr(packed(2))] rather than
     535              :           // manually parsing the string "packed(2)" here.
     536              : 
     537           71 :           size_t oparen = repr_option.find ('(', 0);
     538           71 :           bool is_pack = false;
     539           71 :           bool is_align = false;
     540           71 :           bool is_c = false;
     541           71 :           bool is_integer = false;
     542           71 :           bool is_transparent = false;
     543           71 :           bool is_simd = false;
     544           71 :           unsigned char value = 1;
     545              : 
     546           71 :           if (oparen == std::string::npos)
     547              :             {
     548           64 :               if (repr_option.compare ("align") == 0)
     549              :                 {
     550            1 :                   rust_error_at (attr.get_locus (), ErrorCode::E0589,
     551              :                                  "invalid %<repr(align)%> attribute: %<align%> "
     552              :                                  "needs an argument");
     553            1 :                   delete meta_items;
     554              :                   break;
     555              :                 }
     556              : 
     557           63 :               is_pack = repr_option.compare ("packed") == 0;
     558           63 :               is_c = repr_option.compare ("C") == 0;
     559          126 :               is_integer = (repr_option.compare ("isize") == 0
     560           63 :                             || repr_option.compare ("i8") == 0
     561           63 :                             || repr_option.compare ("i16") == 0
     562           63 :                             || repr_option.compare ("i32") == 0
     563           61 :                             || repr_option.compare ("i64") == 0
     564           61 :                             || repr_option.compare ("i128") == 0
     565           61 :                             || repr_option.compare ("usize") == 0
     566           61 :                             || repr_option.compare ("u8") == 0
     567           61 :                             || repr_option.compare ("u16") == 0
     568           61 :                             || repr_option.compare ("u32") == 0
     569           61 :                             || repr_option.compare ("u64") == 0
     570          124 :                             || repr_option.compare ("u128") == 0);
     571           63 :               is_transparent = repr_option.compare ("transparent") == 0;
     572           63 :               is_simd = repr_option.compare ("simd") == 0;
     573              :             }
     574              : 
     575              :           else
     576              :             {
     577            7 :               std::string rep = repr_option.substr (0, oparen);
     578            7 :               is_pack = rep.compare ("packed") == 0;
     579            7 :               is_align = rep.compare ("align") == 0;
     580              : 
     581            7 :               size_t cparen = repr_option.find (')', oparen);
     582            7 :               if (cparen == std::string::npos)
     583              :                 {
     584            0 :                   rust_error_at (locus, "malformed attribute");
     585              :                 }
     586              : 
     587            7 :               std::string value_str = repr_option.substr (oparen, cparen);
     588            7 :               value = strtoul (value_str.c_str () + 1, NULL, 10);
     589            7 :             }
     590              : 
     591           70 :           if (is_transparent)
     592              :             {
     593           26 :               if (is_pack || is_align || is_c || is_integer)
     594            0 :                 rust_error_at (
     595              :                   locus, ErrorCode::E0692,
     596              :                   "transparent struct cannot have other repr hints");
     597              : 
     598           26 :               repr.repr_kind = TyTy::ADTType::ReprKind::TRANSPARENT;
     599              :             }
     600           44 :           else if (is_pack)
     601              :             {
     602            4 :               repr.repr_kind = TyTy::ADTType::ReprKind::PACKED;
     603            4 :               repr.pack = value;
     604              :             }
     605           40 :           else if (is_align)
     606              :             {
     607            5 :               if (value == 0 || (value & (value - 1)) != 0)
     608            1 :                 rust_error_at (
     609              :                   attr.get_locus (), ErrorCode::E0589,
     610              :                   "invalid %<repr(align)%> attribute: not a power of two");
     611            5 :               repr.repr_kind = TyTy::ADTType::ReprKind::ALIGN;
     612            5 :               repr.align = value;
     613              :             }
     614           35 :           else if (is_c)
     615              :             {
     616           18 :               repr.repr_kind = TyTy::ADTType::ReprKind::C;
     617              :             }
     618           17 :           else if (is_integer)
     619              :             {
     620            2 :               repr.repr_kind = TyTy::ADTType::ReprKind::INT;
     621            4 :               bool ok = context->lookup_builtin (repr_option, &repr.repr);
     622            2 :               if (!ok)
     623              :                 {
     624            0 :                   rust_error_at (attr.get_locus (), ErrorCode::E0552,
     625              :                                  "unrecognized representation hint");
     626              :                 }
     627              :             }
     628           15 :           else if (is_simd)
     629              :             {
     630           14 :               repr.repr_kind = TyTy::ADTType::ReprKind::SIMD;
     631              :             }
     632              :           else
     633              :             {
     634            1 :               rust_error_at (attr.get_locus (), ErrorCode::E0552,
     635              :                              "unrecognized representation hint");
     636              :             }
     637              : 
     638           70 :           delete meta_items;
     639              : 
     640              :           // Multiple repr options must be specified with e.g. #[repr(C,
     641              :           // packed(2))].
     642              :           break;
     643           71 :         }
     644              :     }
     645              : 
     646         3271 :   return repr;
     647              : }
     648              : 
     649              : void
     650         7941 : TypeCheckBase::resolve_generic_params (
     651              :   const HIR::Item::ItemKind item_kind, location_t item_locus,
     652              :   const std::vector<std::unique_ptr<HIR::GenericParam>> &generic_params,
     653              :   std::vector<TyTy::SubstitutionParamMapping> &substitutions, bool is_foreign,
     654              :   ABI abi)
     655              : {
     656        16785 :   for (auto &generic_param : generic_params)
     657              :     {
     658         8844 :       switch (generic_param->get_kind ())
     659              :         {
     660          869 :         case HIR::GenericParam::GenericKind::LIFETIME:
     661          869 :           {
     662          869 :             auto lifetime_param
     663          869 :               = static_cast<HIR::LifetimeParam &> (*generic_param);
     664          869 :             auto lifetime = lifetime_param.get_lifetime ();
     665          869 :             context->get_lifetime_resolver ().insert_mapping (
     666              :               context->intern_lifetime (lifetime));
     667          869 :           }
     668          869 :           break;
     669              : 
     670          136 :         case HIR::GenericParam::GenericKind::CONST:
     671          136 :           {
     672          136 :             if (is_foreign && abi != Rust::ABI::INTRINSIC
     673            0 :                 && abi != Rust::ABI::PLATFORM_INTRINSIC)
     674              :               {
     675            0 :                 rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
     676              :                                "foreign items may not have const parameters");
     677              :               }
     678              : 
     679          136 :             auto &param
     680          136 :               = static_cast<HIR::ConstGenericParam &> (*generic_param);
     681          136 :             auto specified_type = TypeCheckType::Resolve (param.get_type ());
     682              : 
     683          136 :             if (param.has_default_expression ())
     684              :               {
     685           16 :                 switch (item_kind)
     686              :                   {
     687              :                   case HIR::Item::ItemKind::Struct:
     688              :                   case HIR::Item::ItemKind::Enum:
     689              :                   case HIR::Item::ItemKind::TypeAlias:
     690              :                   case HIR::Item::ItemKind::Trait:
     691              :                   case HIR::Item::ItemKind::Union:
     692              :                     break;
     693              : 
     694            2 :                   default:
     695            2 :                     {
     696            2 :                       rich_location r (line_table, item_locus);
     697            2 :                       r.add_fixit_remove (param.get_locus ());
     698            2 :                       rust_error_at (
     699              :                         r,
     700              :                         "default values for const generic parameters are not "
     701              :                         "allowed here");
     702            2 :                     }
     703            2 :                     break;
     704              :                   }
     705              : 
     706           16 :                 auto expr_type
     707           16 :                   = TypeCheckExpr::Resolve (param.get_default_expression ());
     708              : 
     709           16 :                 if (specified_type->is<TyTy::ErrorType> ()
     710           32 :                     || expr_type->is<TyTy::ErrorType> ())
     711              :                   break;
     712              : 
     713           30 :                 coercion_site (param.get_mappings ().get_hirid (),
     714           15 :                                TyTy::TyWithLocation (specified_type),
     715              :                                TyTy::TyWithLocation (
     716              :                                  expr_type,
     717           15 :                                  param.get_default_expression ().get_locus ()),
     718              :                                param.get_locus ());
     719              : 
     720              :                 // fold the default value
     721           15 :                 auto ctx = Compile::Context::get ();
     722           15 :                 auto &expr = param.get_default_expression ();
     723           15 :                 tree default_value
     724           15 :                   = Compile::HIRCompileBase::query_compile_const_expr (
     725              :                     ctx, specified_type, expr);
     726              : 
     727           15 :                 auto default_const_decl
     728              :                   = new TyTy::ConstValueType (default_value, specified_type,
     729           15 :                                               expr.get_mappings ().get_hirid (),
     730           15 :                                               expr.get_mappings ().get_hirid (),
     731           15 :                                               {});
     732              : 
     733           15 :                 context->insert_type (expr.get_mappings (), default_const_decl);
     734              :               }
     735              : 
     736          135 :             TyTy::BaseGeneric *const_decl
     737          270 :               = new TyTy::ConstParamType (param.get_name (), param.get_locus (),
     738              :                                           specified_type,
     739          135 :                                           param.get_mappings ().get_hirid (),
     740          270 :                                           param.get_mappings ().get_hirid (),
     741          270 :                                           {});
     742              : 
     743          135 :             context->insert_type (generic_param->get_mappings (), const_decl);
     744          135 :             TyTy::SubstitutionParamMapping p (*generic_param, const_decl);
     745          135 :             substitutions.push_back (p);
     746              :           }
     747          135 :           break;
     748              : 
     749         7839 :         case HIR::GenericParam::GenericKind::TYPE:
     750         7839 :           {
     751         7839 :             if (is_foreign && abi != Rust::ABI::INTRINSIC
     752            1 :                 && abi != Rust::ABI::PLATFORM_INTRINSIC)
     753              :               {
     754            1 :                 rust_error_at (generic_param->get_locus (), ErrorCode::E0044,
     755              :                                "foreign items may not have type parameters");
     756              :               }
     757              : 
     758         7839 :             auto param_type = TypeResolveGenericParam::Resolve (
     759         7839 :               *generic_param, false /*resolve_trait_bounds*/);
     760         7839 :             context->insert_type (generic_param->get_mappings (), param_type);
     761              : 
     762         7839 :             TyTy::SubstitutionParamMapping p (*generic_param, param_type);
     763         7839 :             substitutions.push_back (p);
     764              :           }
     765         7839 :           break;
     766              :         }
     767              :     }
     768              : 
     769              :   // now walk them to setup any specified type param bounds
     770        16021 :   for (auto &subst : substitutions)
     771              :     {
     772         8080 :       auto &generic = subst.get_generic_param ();
     773         8080 :       if (generic.get_kind () != HIR::GenericParam::GenericKind::TYPE)
     774          135 :         continue;
     775              : 
     776         7945 :       auto &type_param = static_cast<HIR::TypeParam &> (generic);
     777         7945 :       auto bpty = subst.get_param_ty ();
     778         7945 :       rust_assert (bpty->get_kind () == TyTy::TypeKind::PARAM);
     779         7945 :       auto pty = static_cast<TyTy::ParamType *> (bpty);
     780              : 
     781         7945 :       TypeResolveGenericParam::ApplyAnyTraitBounds (type_param, pty);
     782              : 
     783              :       // The drop_bounds lint: a `T: Drop` bound is most likely a mistake, as
     784              :       // `Drop` bounds do not constrain a generic parameter in a useful way.
     785         7945 :       if (flag_unused_check_2_0)
     786            3 :         if (auto drop = mappings.lookup_lang_item (LangItem::Kind::DROP))
     787            3 :           for (auto &bound : pty->get_specified_bounds ())
     788            4 :             if (bound.get_id () == drop.value ())
     789            1 :               rust_warning_at (
     790              :                 type_param.get_locus (), OPT_Wunused_variable,
     791              :                 "bounds on %<Drop%> are most likely incorrect, "
     792              :                 "use %<core::mem::needs_drop%> to detect whether "
     793              :                 "a type has a destructor");
     794              :     }
     795         7941 : }
     796              : 
     797              : TyTy::TypeBoundPredicate
     798         8658 : TypeCheckBase::get_marker_predicate (LangItem::Kind item_type, location_t locus)
     799              : {
     800         8658 :   DefId item_id = mappings.get_lang_item (item_type, locus);
     801         8658 :   HIR::Item *item = mappings.lookup_defid (item_id).value ();
     802         8658 :   rust_assert (item->get_item_kind () == HIR::Item::ItemKind::Trait);
     803              : 
     804         8658 :   HIR::Trait &trait = *static_cast<HIR::Trait *> (item);
     805         8658 :   TraitReference *ref = TraitResolver::Resolve (trait);
     806         8658 :   rust_assert (ref != nullptr);
     807              : 
     808         8658 :   return TyTy::TypeBoundPredicate (*ref, BoundPolarity::RegularBound, locus);
     809              : }
     810              : 
     811              : } // namespace Resolver
     812              : } // 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.