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 ¶m : 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 ¶m = 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 ¶m : 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> ¶ms_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 ¶m : 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 ¶m
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
|