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

Generated by: LCOV version 2.5.0-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.