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