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