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