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