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-item.h"
20 : #include "optional.h"
21 : #include "rust-canonical-path.h"
22 : #include "rust-diagnostics.h"
23 : #include "rust-hir-item.h"
24 : #include "rust-hir-type-check-enumitem.h"
25 : #include "rust-hir-type-check-implitem.h"
26 : #include "rust-hir-type-check-type.h"
27 : #include "rust-hir-type-check-expr.h"
28 : #include "rust-hir-type-check-pattern.h"
29 : #include "rust-hir-trait-resolve.h"
30 : #include "rust-hir-type-check.h"
31 : #include "rust-identifier.h"
32 : #include "rust-rib.h"
33 : #include "rust-session-manager.h"
34 : #include "rust-finalized-name-resolution-context.h"
35 : #include "rust-substitution-mapper.h"
36 : #include "rust-type-util.h"
37 : #include "rust-tyty-variance-analysis.h"
38 : #include "rust-tyty.h"
39 : #include "options.h"
40 : #include "rust-compile-base.h"
41 : #include "rust-compile-context.h"
42 :
43 : namespace Rust {
44 : namespace Resolver {
45 :
46 : // Const-evaluate the discriminants of a repr(C) enum and warn when a value does
47 : // not fit into a C int/unsigned int. Done here, during type resolution, using
48 : // the compile context (a singleton shared with the backend).
49 : static void
50 3 : check_repr_c_enum_discriminants (Compile::Context *ctx, TyTy::BaseType *type)
51 : {
52 3 : if (type->get_kind () != TyTy::TypeKind::ADT)
53 : return;
54 :
55 3 : auto &adt = static_cast<TyTy::ADTType &> (*type);
56 3 : if (!adt.is_enum ()
57 3 : || adt.get_repr_options ().repr_kind != TyTy::ADTType::ReprKind::C)
58 : return;
59 :
60 4 : for (auto &variant : adt.get_variants ())
61 : {
62 2 : if (!variant->has_discriminant ())
63 0 : continue;
64 :
65 2 : HIR::Expr &discriminant = variant->get_discriminant ();
66 2 : TyTy::BaseType *discrim_ty = nullptr;
67 2 : if (!ctx->get_tyctx ()->lookup_type (
68 2 : discriminant.get_mappings ().get_hirid (), &discrim_ty))
69 0 : continue;
70 :
71 2 : tree folded
72 2 : = Compile::HIRCompileBase::query_compile_const_expr (ctx, discrim_ty,
73 : discriminant);
74 2 : if (folded == error_mark_node || TREE_CODE (folded) != INTEGER_CST)
75 0 : continue;
76 :
77 2 : widest_int value = wi::to_widest (folded);
78 2 : if (wi::lts_p (value, INT32_MIN) || wi::gts_p (value, UINT32_MAX))
79 1 : rust_warning_at (discriminant.get_locus (), OPT_Woverflow,
80 : "%<repr(C)%> enum discriminant does not fit into C "
81 : "%<int%> nor into C %<unsigned int%>");
82 2 : }
83 : }
84 :
85 53435 : TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
86 :
87 : TyTy::BaseType *
88 29285 : TypeCheckItem::Resolve (HIR::Item &item)
89 : {
90 : // is it already resolved?
91 29285 : auto context = TypeCheckContext::get ();
92 29285 : TyTy::BaseType *resolved = nullptr;
93 29285 : bool already_resolved
94 29285 : = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
95 29285 : if (already_resolved)
96 : {
97 5091 : bool function_body_pending = false;
98 5091 : if (auto fn = resolved->try_as<TyTy::FnType> ())
99 184 : function_body_pending = context->function_body_pending (fn->get_id ());
100 :
101 184 : if (!function_body_pending)
102 4912 : return resolved;
103 : }
104 :
105 24373 : rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
106 24373 : HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
107 :
108 24373 : TypeCheckItem resolver;
109 24373 : vis_item.accept_vis (resolver);
110 24372 : return resolver.infered;
111 24372 : }
112 :
113 : TyTy::FnType *
114 179 : TypeCheckItem::ResolveFunctionSignature (HIR::Function &function)
115 : {
116 179 : TypeCheckItem resolver;
117 179 : auto lifetime_pin = resolver.context->push_clean_lifetime_resolver ();
118 179 : TyTy::FnType *result = resolver.resolve_function_signature (function);
119 179 : if (result != nullptr)
120 179 : resolver.context->mark_function_body_pending (result->get_id ());
121 358 : return result;
122 179 : }
123 :
124 : TyTy::BaseType *
125 409 : TypeCheckItem::ResolveTraitSignature (HIR::Trait &trait)
126 : {
127 409 : TypeCheckItem resolver;
128 409 : return resolver.resolve_trait (trait, false);
129 409 : }
130 :
131 : TyTy::BaseType *
132 1 : TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
133 : {
134 1 : TypeCheckItem resolver;
135 1 : return resolver.resolve_impl_item (impl_block, item);
136 1 : }
137 :
138 : TyTy::BaseType *
139 23232 : TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
140 : {
141 23232 : TypeCheckItem resolver;
142 23232 : auto lifetime_pin = resolver.context->push_clean_lifetime_resolver (true);
143 :
144 23232 : bool failed_flag = false;
145 23232 : auto result
146 23232 : = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
147 23232 : if (failed_flag)
148 : {
149 0 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
150 : }
151 23232 : std::vector<TyTy::SubstitutionParamMapping> substitutions
152 23232 : = std::move (result.first);
153 23232 : TyTy::RegionConstraints region_constraints = std::move (result.second);
154 :
155 23232 : return resolver.resolve_impl_block_self (impl_block);
156 23232 : }
157 :
158 : TyTy::BaseType *
159 3198 : TypeCheckItem::ResolveImplBlockSelfWithInference (
160 : HIR::ImplBlock &impl, location_t locus,
161 : TyTy::SubstitutionArgumentMappings *infer_arguments)
162 : {
163 3198 : TypeCheckItem resolver;
164 3198 : auto lifetime_pin = resolver.context->push_clean_lifetime_resolver (true);
165 :
166 3198 : bool failed_flag = false;
167 3198 : auto result = resolver.resolve_impl_block_substitutions (impl, failed_flag);
168 3198 : if (failed_flag)
169 : {
170 1 : return new TyTy::ErrorType (impl.get_mappings ().get_hirid ());
171 : }
172 3197 : std::vector<TyTy::SubstitutionParamMapping> substitutions
173 3197 : = std::move (result.first);
174 3197 : TyTy::RegionConstraints region_constraints = std::move (result.second);
175 :
176 : // now that we have the param mappings we need to query the self type
177 3197 : TyTy::BaseType *self = resolver.resolve_impl_block_self (impl);
178 :
179 : // nothing to do
180 3197 : if (substitutions.empty () || self->is_concrete ())
181 : return self;
182 :
183 : // generate inference variables for the subst-param-mappings
184 779 : std::vector<TyTy::SubstitutionArg> args;
185 1591 : for (auto &p : substitutions)
186 : {
187 812 : auto param = p.get_param_ty ();
188 812 : if (!p.needs_substitution ())
189 : {
190 0 : auto resolved = param->destructure ();
191 0 : args.emplace_back (&p, resolved);
192 :
193 0 : continue;
194 0 : }
195 :
196 812 : TyTy::BaseType *argument = nullptr;
197 812 : if (param->get_kind () == TyTy::TypeKind::CONST)
198 : {
199 28 : auto i = TyTy::TyVar::get_implicit_const_infer_var (locus);
200 28 : argument = i.get_tyty ();
201 : }
202 : else
203 : {
204 784 : auto i = TyTy::TyVar::get_implicit_infer_var (locus);
205 784 : argument = i.get_tyty ();
206 : }
207 812 : args.emplace_back (&p, argument);
208 : }
209 :
210 : // create argument mappings
211 779 : *infer_arguments = TyTy::SubstitutionArgumentMappings (
212 : std::move (args), {},
213 1558 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (
214 : infer_arguments),
215 1558 : locus);
216 :
217 779 : TyTy::BaseType *infer = SubstMapperInternal::Resolve (self, *infer_arguments);
218 :
219 : // we only need to apply to the bounds manually on types which dont bind
220 : // generics
221 779 : if (!infer->has_substitutions_defined ())
222 : {
223 693 : for (auto &bound : infer->get_specified_bounds ())
224 185 : bound.handle_substitions (*infer_arguments);
225 : }
226 :
227 779 : return infer;
228 3977 : }
229 :
230 : std::vector<TyTy::SubstitutionParamMapping>
231 2043 : TypeCheckItem::ResolveImplBlockSubstitutions (HIR::ImplBlock &impl_block,
232 : bool &failure_flag)
233 : {
234 2043 : TypeCheckItem resolver;
235 2043 : auto result
236 2043 : = resolver.resolve_impl_block_substitutions (impl_block, failure_flag);
237 2043 : return std::move (result.first);
238 2043 : }
239 :
240 : void
241 5335 : TypeCheckItem::validate_trait_impl_block (
242 : const TyTy::TypeBoundPredicate &specified_bound,
243 : std::vector<const TraitItemReference *> trait_item_refs,
244 : TraitReference *trait_reference, HIR::ImplBlock &impl_block,
245 : TyTy::BaseType *self,
246 : std::vector<TyTy::SubstitutionParamMapping> &substitutions)
247 : {
248 5335 : bool impl_block_missing_trait_items
249 5335 : = !specified_bound.is_error ()
250 5335 : && trait_reference->size () != trait_item_refs.size ();
251 1722 : if (impl_block_missing_trait_items
252 1722 : && impl_block.get_polarity () == BoundPolarity::RegularBound)
253 : {
254 : // filter the missing impl_items
255 1720 : std::vector<std::reference_wrapper<const TraitItemReference>>
256 1720 : missing_trait_items;
257 5435 : for (const auto &trait_item_ref : trait_reference->get_trait_items ())
258 : {
259 3715 : bool found = false;
260 5706 : for (auto implemented_trait_item : trait_item_refs)
261 : {
262 3539 : std::string trait_item_name = trait_item_ref.get_identifier ();
263 3539 : std::string impl_item_name
264 3539 : = implemented_trait_item->get_identifier ();
265 3539 : found = trait_item_name == impl_item_name;
266 3539 : if (found)
267 : break;
268 3539 : }
269 :
270 3715 : bool is_required_trait_item = !trait_item_ref.is_optional ();
271 3715 : if (!found && is_required_trait_item)
272 7 : missing_trait_items.emplace_back (trait_item_ref);
273 : }
274 :
275 1720 : if (!missing_trait_items.empty ())
276 : {
277 5 : std::string missing_items_buf;
278 5 : rich_location r (line_table, impl_block.get_locus ());
279 17 : for (size_t i = 0; i < missing_trait_items.size (); i++)
280 : {
281 7 : bool has_more = (i + 1) < missing_trait_items.size ();
282 7 : const TraitItemReference &missing_trait_item
283 7 : = missing_trait_items.at (i);
284 7 : missing_items_buf += missing_trait_item.get_identifier ()
285 21 : + (has_more ? ", " : "");
286 7 : r.add_range (missing_trait_item.get_locus ());
287 : }
288 :
289 5 : rust_error_at (r, ErrorCode::E0046,
290 : "missing %s in implementation of trait %qs",
291 : missing_items_buf.c_str (),
292 5 : trait_reference->get_name ().c_str ());
293 5 : }
294 1720 : }
295 5335 : }
296 :
297 : void
298 72 : TypeCheckItem::visit (HIR::TypeAlias &alias)
299 : {
300 72 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
301 :
302 72 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
303 72 : if (alias.has_generics ())
304 9 : resolve_generic_params (HIR::Item::ItemKind::TypeAlias, alias.get_locus (),
305 9 : alias.get_generic_params (), substitutions);
306 :
307 72 : TyTy::BaseType *actual_type
308 72 : = TypeCheckType::Resolve (alias.get_type_aliased ());
309 :
310 72 : context->insert_type (alias.get_mappings (), actual_type);
311 :
312 72 : TyTy::RegionConstraints region_constraints;
313 72 : ResolveWhereClauseItem::Resolve (alias.get_where_clause (),
314 : region_constraints);
315 72 : infered = actual_type;
316 72 : }
317 :
318 : void
319 1012 : TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
320 : {
321 1012 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
322 :
323 1012 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
324 1012 : if (struct_decl.has_generics ())
325 308 : resolve_generic_params (HIR::Item::ItemKind::Struct,
326 : struct_decl.get_locus (),
327 308 : struct_decl.get_generic_params (), substitutions);
328 :
329 1012 : TyTy::RegionConstraints region_constraints;
330 1012 : ResolveWhereClauseItem::Resolve (struct_decl.get_where_clause (),
331 : region_constraints);
332 :
333 : // Process #[repr(X)] attribute, if any
334 1012 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
335 1012 : TyTy::ADTType::ReprOptions repr
336 1012 : = parse_repr_options (attrs, struct_decl.get_locus ());
337 :
338 1012 : std::vector<TyTy::StructFieldType *> fields;
339 1012 : size_t idx = 0;
340 2806 : for (auto &field : struct_decl.get_fields ())
341 : {
342 1794 : TyTy::BaseType *field_type
343 1794 : = TypeCheckType::Resolve (field.get_field_type ());
344 1794 : auto *ty_field
345 3588 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
346 1794 : std::to_string (idx), field_type,
347 1794 : field.get_locus ());
348 1794 : fields.push_back (ty_field);
349 1794 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
350 1794 : idx++;
351 : }
352 :
353 1012 : if (repr.repr_kind == TyTy::ADTType::ReprKind::SIMD)
354 : {
355 14 : bool is_valid = validate_repr_simd (fields, struct_decl.get_locus ());
356 14 : if (!is_valid)
357 3 : return;
358 : }
359 :
360 : // get the path
361 :
362 1009 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
363 :
364 1009 : CanonicalPath path
365 1009 : = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid (),
366 1009 : Resolver2_0::Namespace::Types);
367 :
368 1009 : RustIdent ident{path, struct_decl.get_locus ()};
369 :
370 : // its a single variant ADT
371 1009 : std::vector<TyTy::VariantDef *> variants;
372 1009 : variants.push_back (
373 1009 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
374 1009 : struct_decl.get_mappings ().get_defid (),
375 1009 : struct_decl.get_identifier ().as_string (), ident,
376 2018 : TyTy::VariantDef::VariantType::TUPLE, tl::nullopt,
377 3027 : std::move (fields)));
378 :
379 1009 : auto *type = new TyTy::ADTType (
380 1009 : struct_decl.get_mappings ().get_defid (),
381 1009 : struct_decl.get_mappings ().get_hirid (),
382 1009 : struct_decl.get_mappings ().get_hirid (),
383 1009 : struct_decl.get_identifier ().as_string (), ident,
384 : TyTy::ADTType::ADTKind::TUPLE_STRUCT, std::move (variants),
385 : std::move (substitutions), repr,
386 2018 : TyTy::SubstitutionArgumentMappings::empty (
387 1009 : context->get_lifetime_resolver ().get_num_bound_regions ()),
388 4036 : region_constraints);
389 :
390 1009 : context->insert_type (struct_decl.get_mappings (), type);
391 1009 : infered = type;
392 :
393 1009 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
394 2024 : }
395 :
396 : void
397 1699 : TypeCheckItem::visit (HIR::StructStruct &struct_decl)
398 : {
399 1699 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
400 1699 : auto &mappings = Analysis::Mappings::get ();
401 :
402 1699 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
403 1699 : if (struct_decl.has_generics ())
404 529 : resolve_generic_params (HIR::Item::ItemKind::Struct,
405 : struct_decl.get_locus (),
406 529 : struct_decl.get_generic_params (), substitutions);
407 :
408 1699 : TyTy::RegionConstraints region_constraints;
409 1699 : ResolveWhereClauseItem::Resolve (struct_decl.get_where_clause (),
410 : region_constraints);
411 :
412 : // Process #[repr(X)] attribute, if any
413 1699 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
414 1699 : TyTy::ADTType::ReprOptions repr
415 1699 : = parse_repr_options (attrs, struct_decl.get_locus ());
416 :
417 1699 : std::vector<TyTy::StructFieldType *> fields;
418 3671 : for (auto &field : struct_decl.get_fields ())
419 : {
420 1977 : TyTy::BaseType *field_type
421 1977 : = TypeCheckType::Resolve (field.get_field_type ());
422 1977 : auto infer_type = field_type->contains_infer ();
423 1977 : if (infer_type)
424 : {
425 5 : rust_error_at (mappings.lookup_location (infer_type->get_ref ()),
426 : "the placeholder %<_%> is not allowed within types on "
427 : "item signatures for structs");
428 5 : return;
429 : }
430 1972 : auto *ty_field
431 1972 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
432 1972 : field.get_field_name ().as_string (),
433 3944 : field_type, field.get_locus ());
434 1972 : fields.push_back (ty_field);
435 1972 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
436 : }
437 :
438 1694 : if (repr.repr_kind == TyTy::ADTType::ReprKind::SIMD)
439 : {
440 0 : bool is_valid = validate_repr_simd (fields, struct_decl.get_locus ());
441 0 : if (!is_valid)
442 : return;
443 : }
444 1694 : if (repr.repr_kind == TyTy::ADTType::ReprKind::TRANSPARENT)
445 : {
446 26 : size_t num_non_zst = 0;
447 55 : for (auto &field : fields)
448 : {
449 29 : if (!field->get_field_type ()->is_zero_sized ())
450 26 : num_non_zst++;
451 : }
452 26 : if (num_non_zst > 1)
453 : {
454 1 : rust_error_at (struct_decl.get_locus (), ErrorCode::E0690,
455 : "transparent struct needs at most one field with "
456 : "non-trivial size or alignment, but has %lu",
457 : (unsigned long) num_non_zst);
458 1 : return;
459 : }
460 : }
461 :
462 1693 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
463 :
464 1693 : CanonicalPath path
465 1693 : = nr_ctx.to_canonical_path (struct_decl.get_mappings ().get_nodeid (),
466 1693 : Resolver2_0::Namespace::Types);
467 :
468 1693 : RustIdent ident{path, struct_decl.get_locus ()};
469 :
470 : // its a single variant ADT
471 1693 : auto variant_type = struct_decl.is_unit_struct ()
472 1693 : ? TyTy::VariantDef::VariantType::UNIT
473 1090 : : TyTy::VariantDef::VariantType::STRUCT;
474 1693 : std::vector<TyTy::VariantDef *> variants;
475 1693 : variants.push_back (
476 1693 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
477 1693 : struct_decl.get_mappings ().get_defid (),
478 1693 : struct_decl.get_identifier ().as_string (), ident,
479 5079 : variant_type, tl::nullopt, std::move (fields)));
480 :
481 1693 : auto *type = new TyTy::ADTType (
482 1693 : struct_decl.get_mappings ().get_defid (),
483 1693 : struct_decl.get_mappings ().get_hirid (),
484 1693 : struct_decl.get_mappings ().get_hirid (),
485 1693 : struct_decl.get_identifier ().as_string (), ident,
486 : TyTy::ADTType::ADTKind::STRUCT_STRUCT, std::move (variants),
487 : std::move (substitutions), repr,
488 3386 : TyTy::SubstitutionArgumentMappings::empty (
489 1693 : context->get_lifetime_resolver ().get_num_bound_regions ()),
490 6772 : region_constraints);
491 :
492 1693 : context->insert_type (struct_decl.get_mappings (), type);
493 1693 : infered = type;
494 :
495 1693 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
496 3398 : }
497 :
498 : void
499 560 : TypeCheckItem::visit (HIR::Enum &enum_decl)
500 : {
501 560 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
502 560 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
503 560 : if (enum_decl.has_generics ())
504 245 : resolve_generic_params (HIR::Item::ItemKind::Enum, enum_decl.get_locus (),
505 245 : enum_decl.get_generic_params (), substitutions);
506 :
507 : // Process #[repr(X)] attribute, if any
508 560 : const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
509 560 : TyTy::ADTType::ReprOptions repr
510 560 : = parse_repr_options (attrs, enum_decl.get_locus ());
511 :
512 560 : std::vector<TyTy::VariantDef *> variants;
513 560 : int64_t discriminant_value = 0;
514 1848 : for (auto &variant : enum_decl.get_variants ())
515 : {
516 1288 : TyTy::VariantDef *field_type
517 1288 : = TypeCheckEnumItem::Resolve (*variant, discriminant_value);
518 1288 : if (field_type)
519 : {
520 1287 : discriminant_value++;
521 1287 : variants.push_back (field_type);
522 : }
523 : }
524 :
525 : // Check for zero-variant enum compatibility
526 560 : if (enum_decl.is_zero_variant ())
527 : {
528 11 : if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
529 11 : || repr.repr_kind == TyTy::ADTType::ReprKind::C)
530 : {
531 2 : rust_error_at (enum_decl.get_locus (),
532 : "unsupported representation for zero-variant enum");
533 2 : return;
534 : }
535 : }
536 :
537 558 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
538 :
539 : // get the path
540 558 : CanonicalPath canonical_path
541 558 : = nr_ctx.to_canonical_path (enum_decl.get_mappings ().get_nodeid (),
542 558 : Resolver2_0::Namespace::Types);
543 :
544 558 : RustIdent ident{canonical_path, enum_decl.get_locus ()};
545 :
546 : // multi variant ADT
547 558 : auto *type
548 558 : = new TyTy::ADTType (enum_decl.get_mappings ().get_defid (),
549 558 : enum_decl.get_mappings ().get_hirid (),
550 558 : enum_decl.get_mappings ().get_hirid (),
551 558 : enum_decl.get_identifier ().as_string (), ident,
552 : TyTy::ADTType::ADTKind::ENUM, std::move (variants),
553 1674 : std::move (substitutions), repr);
554 :
555 558 : context->insert_type (enum_decl.get_mappings (), type);
556 558 : infered = type;
557 :
558 558 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
559 :
560 558 : if (flag_unused_check_2_0)
561 3 : check_repr_c_enum_discriminants (Compile::Context::get (), type);
562 560 : }
563 :
564 : void
565 105 : TypeCheckItem::visit (HIR::Union &union_decl)
566 : {
567 105 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
568 105 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
569 105 : if (union_decl.has_generics ())
570 75 : resolve_generic_params (HIR::Item::ItemKind::Union, union_decl.get_locus (),
571 75 : union_decl.get_generic_params (), substitutions);
572 :
573 105 : TyTy::RegionConstraints region_constraints;
574 105 : ResolveWhereClauseItem::Resolve (union_decl.get_where_clause (),
575 : region_constraints);
576 :
577 105 : std::vector<TyTy::StructFieldType *> fields;
578 409 : for (auto &variant : union_decl.get_variants ())
579 : {
580 304 : TyTy::BaseType *variant_type
581 304 : = TypeCheckType::Resolve (variant.get_field_type ());
582 304 : auto *ty_variant
583 304 : = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
584 304 : variant.get_field_name ().as_string (),
585 608 : variant_type, variant.get_locus ());
586 304 : fields.push_back (ty_variant);
587 304 : context->insert_type (variant.get_mappings (),
588 : ty_variant->get_field_type ());
589 : }
590 :
591 105 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
592 :
593 : // get the path
594 105 : CanonicalPath canonical_path
595 105 : = nr_ctx.to_canonical_path (union_decl.get_mappings ().get_nodeid (),
596 105 : Resolver2_0::Namespace::Types);
597 :
598 105 : RustIdent ident{canonical_path, union_decl.get_locus ()};
599 :
600 : // there is only a single variant
601 105 : std::vector<TyTy::VariantDef *> variants;
602 105 : variants.push_back (
603 105 : new TyTy::VariantDef (union_decl.get_mappings ().get_hirid (),
604 105 : union_decl.get_mappings ().get_defid (),
605 105 : union_decl.get_identifier ().as_string (), ident,
606 210 : TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
607 315 : std::move (fields)));
608 :
609 105 : auto *type
610 105 : = new TyTy::ADTType (union_decl.get_mappings ().get_defid (),
611 105 : union_decl.get_mappings ().get_hirid (),
612 105 : union_decl.get_mappings ().get_hirid (),
613 105 : union_decl.get_identifier ().as_string (), ident,
614 : TyTy::ADTType::ADTKind::UNION, std::move (variants),
615 315 : std::move (substitutions));
616 :
617 105 : context->insert_type (union_decl.get_mappings (), type);
618 105 : infered = type;
619 :
620 105 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
621 210 : }
622 :
623 : void
624 57 : TypeCheckItem::visit (HIR::StaticItem &var)
625 : {
626 57 : TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
627 57 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
628 :
629 57 : TyTy::BaseType *unified
630 57 : = coercion_site (var.get_mappings ().get_hirid (),
631 57 : TyTy::TyWithLocation (type, var.get_type ().get_locus ()),
632 : TyTy::TyWithLocation (expr_type,
633 57 : var.get_expr ().get_locus ()),
634 : var.get_locus ());
635 57 : context->insert_type (var.get_mappings (), unified);
636 57 : infered = unified;
637 57 : }
638 :
639 : void
640 431 : TypeCheckItem::visit (HIR::ConstantItem &constant)
641 : {
642 431 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
643 431 : context->push_const_context ();
644 431 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
645 431 : context->pop_const_context ();
646 :
647 862 : TyTy::BaseType *unified = unify_site (
648 431 : constant.get_mappings ().get_hirid (),
649 431 : TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
650 431 : TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
651 : constant.get_locus ());
652 431 : context->insert_type (constant.get_mappings (), unified);
653 431 : infered = unified;
654 431 : }
655 :
656 : void
657 6386 : TypeCheckItem::visit (HIR::ImplBlock &impl_block)
658 : {
659 6386 : if (impl_block.has_trait_ref ())
660 5340 : resolve_trait_impl_block (impl_block);
661 : else
662 1046 : resolve_impl_block (impl_block);
663 6385 : }
664 :
665 : void
666 1046 : TypeCheckItem::resolve_impl_block (HIR::ImplBlock &impl_block)
667 : {
668 1046 : auto binder_pin = context->push_clean_lifetime_resolver (true);
669 :
670 1046 : bool failed_flag = false;
671 1046 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
672 1046 : if (failed_flag)
673 : {
674 3 : infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
675 3 : return;
676 : }
677 1043 : std::vector<TyTy::SubstitutionParamMapping> substitutions
678 1043 : = std::move (result.first);
679 1043 : TyTy::RegionConstraints region_constraints = std::move (result.second);
680 :
681 1043 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
682 :
683 4254 : for (auto &impl_item : impl_block.get_impl_items ())
684 3211 : TypeCheckImplItem::Resolve (impl_block, *impl_item, self, substitutions);
685 1046 : }
686 :
687 : void
688 5340 : TypeCheckItem::resolve_trait_impl_block (HIR::ImplBlock &impl_block)
689 : {
690 5340 : auto binder_pin = context->push_clean_lifetime_resolver (true);
691 :
692 5340 : bool failed_flag = false;
693 5340 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
694 5339 : if (failed_flag)
695 : {
696 1 : infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
697 1 : return;
698 : }
699 5338 : std::vector<TyTy::SubstitutionParamMapping> substitutions
700 5338 : = std::move (result.first);
701 5338 : TyTy::RegionConstraints region_constraints = std::move (result.second);
702 :
703 5338 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
704 5338 : TraitReference *trait_reference = &TraitReference::error_node ();
705 5338 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
706 :
707 5338 : HIR::TypePath &ref = impl_block.get_trait_ref ();
708 5338 : trait_reference = TraitResolver::Resolve (ref);
709 5338 : if (trait_reference->is_error ())
710 3 : return;
711 :
712 : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
713 : // for example
714 10670 : specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
715 5335 : impl_block.get_polarity ());
716 :
717 : // need to check that if this specified bound has super traits does this
718 : // Self implement them?
719 5335 : specified_bound.validate_type_implements_super_traits (
720 5335 : *self, impl_block.get_type (), impl_block.get_trait_ref ());
721 :
722 5335 : std::map<DefId, AssocTypeEntry> assoc_types_by_trait_item;
723 5335 : std::vector<const TraitItemReference *> trait_item_refs;
724 5335 : ResolveImplTraitAssociatedTypes (context, impl_block, specified_bound, self,
725 : substitutions, assoc_types_by_trait_item,
726 : trait_item_refs);
727 :
728 5335 : ImplTraitContextFrame frame{trait_reference, self,
729 5335 : std::move (assoc_types_by_trait_item)};
730 5335 : ImplTraitFrameGuard guard (frame);
731 11503 : for (auto &impl_item : impl_block.get_impl_items ())
732 : {
733 6168 : bool is_type_alias = impl_item->get_impl_item_type ()
734 6168 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
735 6168 : if (is_type_alias)
736 1414 : continue;
737 :
738 4754 : auto trait_item_ref
739 4754 : = TypeCheckImplItemWithTrait::Resolve (impl_block, *impl_item, self,
740 4754 : specified_bound, substitutions);
741 4754 : if (!trait_item_ref.is_error ())
742 4749 : trait_item_refs.push_back (trait_item_ref.get_raw_item ());
743 4754 : }
744 :
745 5335 : validate_trait_impl_block (specified_bound, trait_item_refs, trait_reference,
746 : impl_block, self, substitutions);
747 :
748 5335 : AssociatedImplTrait associated (trait_reference, specified_bound, &impl_block,
749 5335 : self, frame);
750 5335 : context->insert_associated_trait_impl (
751 5335 : impl_block.get_mappings ().get_hirid (), std::move (associated));
752 5335 : context->insert_associated_impl_mapping (
753 5335 : trait_reference->get_mappings ().get_hirid (), self,
754 5335 : impl_block.get_mappings ().get_hirid ());
755 10677 : }
756 :
757 : void
758 6754 : TypeCheckItem::ResolveImplTraitAssociatedTypes (
759 : TypeCheckContext *context, HIR::ImplBlock &impl_block,
760 : TyTy::TypeBoundPredicate &specified_bound, TyTy::BaseType *self,
761 : std::vector<TyTy::SubstitutionParamMapping> &substitutions,
762 : std::map<DefId, AssocTypeEntry> &assoc_types_by_trait_item,
763 : std::vector<const TraitItemReference *> &trait_item_refs)
764 : {
765 16700 : for (auto &impl_item : impl_block.get_impl_items ())
766 : {
767 9946 : bool is_type_alias = impl_item->get_impl_item_type ()
768 9946 : == HIR::ImplItem::ImplItemType::TYPE_ALIAS;
769 9946 : if (!is_type_alias)
770 7779 : continue;
771 :
772 2167 : rust_debug_loc (impl_item->get_locus (), "RESOLVE ITEM 1");
773 2167 : self->debug ();
774 2167 : auto trait_item_ref
775 2167 : = TypeCheckImplItemWithTrait::Resolve (impl_block, *impl_item, self,
776 2167 : specified_bound, substitutions);
777 2167 : rust_debug_loc (impl_item->get_locus (), "RESOLVE ITEM 2");
778 2167 : if (!trait_item_ref.is_error ())
779 : {
780 2167 : const TraitItemReference *tiref = trait_item_ref.get_raw_item ();
781 2167 : trait_item_refs.push_back (tiref);
782 :
783 2167 : DefId impl_item_defid = impl_item->get_impl_mappings ().get_defid ();
784 2167 : DefId trait_item_defid = tiref->get_mappings ().get_defid ();
785 2167 : TyTy::BaseType *impl_item_ty;
786 :
787 2167 : bool ok = context->lookup_type (
788 2167 : impl_item->get_impl_mappings ().get_hirid (), &impl_item_ty);
789 2167 : rust_assert (ok);
790 :
791 2167 : AssocTypeEntry entry
792 2167 : = {trait_item_defid, impl_item_defid, impl_item_ty};
793 2167 : assoc_types_by_trait_item[trait_item_defid] = std::move (entry);
794 : }
795 2167 : }
796 6754 : }
797 :
798 : TyTy::BaseType *
799 1 : TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
800 : HIR::ImplItem &item)
801 : {
802 1 : bool failed_flag = false;
803 1 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
804 1 : if (failed_flag)
805 : {
806 1 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
807 : }
808 :
809 0 : std::vector<TyTy::SubstitutionParamMapping> substitutions
810 0 : = std::move (result.first);
811 0 : TyTy::RegionConstraints region_constraints = std::move (result.second);
812 :
813 0 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
814 :
815 0 : return TypeCheckImplItem::Resolve (impl_block, item, self, substitutions);
816 1 : }
817 :
818 : TyTy::FnType *
819 6943 : TypeCheckItem::resolve_function_signature (HIR::Function &function)
820 : {
821 6943 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
822 6943 : if (function.has_generics ())
823 681 : resolve_generic_params (HIR::Item::ItemKind::Function,
824 : function.get_locus (),
825 681 : function.get_generic_params (), substitutions);
826 :
827 6943 : TyTy::RegionConstraints region_constraints;
828 6943 : ResolveWhereClauseItem::Resolve (function.get_where_clause (),
829 : region_constraints);
830 :
831 6943 : TyTy::BaseType *ret_type = nullptr;
832 6943 : if (!function.has_function_return_type ())
833 3495 : ret_type = TyTy::TupleType::get_unit_type ();
834 : else
835 : {
836 3448 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
837 3448 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
838 : return nullptr;
839 :
840 3444 : ret_type = resolved->clone ();
841 3444 : ret_type->set_ref (
842 3444 : function.get_return_type ().get_mappings ().get_hirid ());
843 : }
844 :
845 6939 : std::vector<TyTy::FnParam> params;
846 9115 : for (auto ¶m : function.get_function_params ())
847 : {
848 : // get the name as well required for later on
849 2176 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
850 2176 : context->insert_type (param.get_mappings (), param_tyty);
851 2176 : TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
852 2176 : params.emplace_back (param.get_param_name ().clone_pattern (),
853 : param_tyty);
854 : }
855 :
856 6939 : auto &nr_ctx = Resolver2_0::FinalizedNameResolutionContext::get ();
857 :
858 6939 : CanonicalPath path
859 6939 : = nr_ctx.to_canonical_path (function.get_mappings ().get_nodeid (),
860 6939 : Resolver2_0::Namespace::Values);
861 :
862 6939 : RustIdent ident{path, function.get_locus ()};
863 :
864 6939 : auto fn_type = new TyTy::FnType (
865 6939 : function.get_mappings ().get_hirid (),
866 6939 : function.get_mappings ().get_defid (),
867 6939 : function.get_function_name ().as_string (), ident,
868 : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type,
869 : std::move (substitutions),
870 13878 : TyTy::SubstitutionArgumentMappings::empty (
871 6939 : context->get_lifetime_resolver ().get_num_bound_regions ()),
872 27756 : region_constraints);
873 :
874 6939 : context->insert_type (function.get_mappings (), fn_type);
875 :
876 6939 : return fn_type;
877 13882 : }
878 :
879 : void
880 6943 : TypeCheckItem::visit (HIR::Function &function)
881 : {
882 6943 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
883 :
884 6943 : TyTy::BaseType *resolved = nullptr;
885 6943 : TyTy::FnType *resolved_fn_type = nullptr;
886 6943 : if (context->lookup_type (function.get_mappings ().get_hirid (), &resolved))
887 : {
888 179 : if (resolved->get_kind () != TyTy::TypeKind::FNDEF)
889 : return;
890 179 : resolved_fn_type = static_cast<TyTy::FnType *> (resolved);
891 : }
892 : else
893 6764 : resolved_fn_type = resolve_function_signature (function);
894 :
895 6943 : if (resolved_fn_type == nullptr)
896 : return;
897 :
898 : // Mark the body as claimed before resolving it. Recursive queries from the
899 : // body must reuse the cached signature rather than re-entering this body.
900 6939 : context->clear_function_body_pending (resolved_fn_type->get_id ());
901 :
902 : // need to get the return type from this
903 6939 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
904 6939 : context->push_return_type (TypeCheckContextItem (&function),
905 : expected_ret_tyty);
906 :
907 6939 : context->switch_to_fn_body ();
908 6939 : auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
909 :
910 : // emit check for
911 : // error[E0121]: the type placeholder `_` is not allowed within types on item
912 6939 : const auto placeholder = expected_ret_tyty->contains_infer ();
913 6939 : if (placeholder != nullptr && function.has_return_type ())
914 : {
915 : // FIXME
916 : // this will be a great place for the Default Hir Visitor we want to
917 : // grab the locations of the placeholders (HIR::InferredType) their
918 : // location, for now maybe we can use their hirid to lookup the location
919 3 : location_t placeholder_locus
920 3 : = mappings.lookup_location (placeholder->get_ref ());
921 3 : location_t type_locus = function.get_return_type ().get_locus ();
922 3 : rich_location r (line_table, placeholder_locus);
923 :
924 3 : bool have_expected_type
925 6 : = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
926 3 : if (!have_expected_type)
927 : {
928 0 : r.add_range (type_locus);
929 : }
930 : else
931 : {
932 3 : std::string fixit
933 3 : = "replace with the correct type " + block_expr_ty->get_name ();
934 3 : r.add_fixit_replace (type_locus, fixit.c_str ());
935 3 : }
936 :
937 3 : rust_error_at (r, ErrorCode::E0121,
938 : "the type placeholder %<_%> is not allowed within types "
939 : "on item signatures");
940 3 : }
941 :
942 6939 : location_t fn_return_locus = function.has_function_return_type ()
943 6939 : ? function.get_return_type ().get_locus ()
944 3495 : : function.get_locus ();
945 13878 : coercion_site (function.get_definition ().get_mappings ().get_hirid (),
946 6939 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
947 6939 : TyTy::TyWithLocation (block_expr_ty),
948 6939 : function.get_definition ().get_locus ());
949 :
950 6939 : context->pop_return_type ();
951 :
952 6939 : infered = resolved_fn_type;
953 6943 : }
954 :
955 : void
956 1257 : TypeCheckItem::visit (HIR::Module &module)
957 : {
958 5443 : for (auto &item : module.get_items ())
959 4186 : TypeCheckItem::Resolve (*item);
960 1257 : }
961 :
962 : void
963 4154 : TypeCheckItem::visit (HIR::Trait &trait)
964 : {
965 4154 : infered = resolve_trait (trait, true);
966 4154 : }
967 :
968 : TyTy::BaseType *
969 4563 : TypeCheckItem::resolve_trait (HIR::Trait &trait, bool resolve_bodies)
970 : {
971 4563 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
972 :
973 4563 : if (trait.has_type_param_bounds ())
974 : {
975 1719 : for (auto &tp_bound : trait.get_type_param_bounds ())
976 : {
977 935 : if (tp_bound.get ()->get_bound_type ()
978 : == HIR::TypeParamBound::BoundType::TRAITBOUND)
979 : {
980 935 : HIR::TraitBound &tb
981 935 : = static_cast<HIR::TraitBound &> (*tp_bound.get ());
982 935 : if (tb.get_polarity () == BoundPolarity::AntiBound)
983 : {
984 1 : rust_error_at (tb.get_locus (),
985 : "%<?Trait%> is not permitted in supertraits");
986 : }
987 : }
988 : }
989 : }
990 :
991 4563 : TraitReference *trait_ref = TraitResolver::Resolve (trait);
992 4563 : if (trait_ref->is_error ())
993 : {
994 7 : infered = new TyTy::ErrorType (trait.get_mappings ().get_hirid ());
995 7 : return infered;
996 : }
997 :
998 4556 : if (resolve_bodies)
999 4148 : trait_ref->resolve_default_function_bodies ();
1000 :
1001 4556 : RustIdent ident{CanonicalPath::create_empty (), trait.get_locus ()};
1002 4556 : return new TyTy::DynamicObjectType (
1003 4556 : trait.get_mappings ().get_hirid (), ident,
1004 : {TyTy::TypeBoundPredicate (*trait_ref, BoundPolarity::RegularBound,
1005 9112 : trait.get_locus ())});
1006 4563 : }
1007 :
1008 : void
1009 1697 : TypeCheckItem::visit (HIR::ExternBlock &extern_block)
1010 : {
1011 4370 : for (auto &item : extern_block.get_extern_items ())
1012 : {
1013 2673 : TypeCheckTopLevelExternItem::Resolve (*item, extern_block);
1014 : }
1015 1697 : }
1016 :
1017 : void
1018 0 : TypeCheckItem::visit (HIR::ExternCrate &extern_crate)
1019 : {
1020 0 : if (extern_crate.references_self ())
1021 : return;
1022 :
1023 0 : auto &mappings = Analysis::Mappings::get ();
1024 0 : CrateNum num
1025 0 : = mappings.lookup_crate_name (extern_crate.get_referenced_crate ())
1026 0 : .value ();
1027 0 : HIR::Crate &crate = mappings.get_hir_crate (num);
1028 :
1029 0 : CrateNum saved_crate_num = mappings.get_current_crate ();
1030 0 : mappings.set_current_crate (num);
1031 0 : for (auto &item : crate.get_items ())
1032 0 : TypeCheckItem::Resolve (*item);
1033 0 : mappings.set_current_crate (saved_crate_num);
1034 : }
1035 :
1036 : std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
1037 34860 : TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
1038 : bool &failure_flag)
1039 : {
1040 34860 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
1041 34860 : if (impl_block.has_generics ())
1042 4831 : resolve_generic_params (HIR::Item::ItemKind::Impl, impl_block.get_locus (),
1043 4831 : impl_block.get_generic_params (), substitutions);
1044 :
1045 34860 : TyTy::RegionConstraints region_constraints;
1046 34860 : ResolveWhereClauseItem::Resolve (impl_block.get_where_clause (),
1047 : region_constraints);
1048 :
1049 34860 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
1050 34860 : TraitReference *trait_reference = &TraitReference::error_node ();
1051 34860 : if (impl_block.has_trait_ref ())
1052 : {
1053 23307 : auto &ref = impl_block.get_trait_ref ();
1054 23307 : trait_reference = TraitResolver::Resolve (ref);
1055 23307 : if (!trait_reference->is_error ())
1056 : {
1057 : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
1058 : // for example
1059 23304 : specified_bound
1060 46607 : = get_predicate_from_bound (ref, impl_block.get_type (),
1061 23303 : impl_block.get_polarity ());
1062 : }
1063 : }
1064 :
1065 34859 : TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ());
1066 34859 : if (self->is<TyTy::ErrorType> ())
1067 : {
1068 : // we cannot check for unconstrained type arguments when the Self type is
1069 : // not resolved it will just add extra errors that dont help as well as
1070 : // the case where this could just be a recursive type query that should
1071 : // fail and will work later on anyway
1072 1 : return {substitutions, region_constraints};
1073 : }
1074 :
1075 : // inherit the bounds
1076 34858 : if (!specified_bound.is_error ())
1077 23300 : self->inherit_bound (specified_bound);
1078 :
1079 : // check for any unconstrained type-params
1080 34858 : const TyTy::SubstitutionArgumentMappings trait_constraints
1081 34858 : = specified_bound.get_substitution_arguments ();
1082 34858 : const TyTy::SubstitutionArgumentMappings impl_constraints
1083 34858 : = GetUsedSubstArgs::From (self);
1084 :
1085 34858 : failure_flag = check_for_unconstrained (substitutions, trait_constraints,
1086 : impl_constraints, self);
1087 :
1088 34858 : return {substitutions, region_constraints};
1089 69718 : }
1090 :
1091 : TyTy::BaseType *
1092 32810 : TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
1093 : {
1094 32810 : return TypeCheckType::Resolve (impl_block.get_type ());
1095 : }
1096 :
1097 : bool
1098 14 : TypeCheckItem::validate_repr_simd (
1099 : const std::vector<TyTy::StructFieldType *> &fields, location_t locus)
1100 : {
1101 14 : if (fields.empty ())
1102 : {
1103 0 : rust_error_at (locus, ErrorCode::E0075, "SIMD vector cannot be empty");
1104 0 : return false;
1105 : }
1106 :
1107 : // in 1.49, repr simd assumes all fields are same type with its size
1108 : // being power-of-two.
1109 : //
1110 : // TODO update this typecheck to make repr simd take in a single field
1111 : // of an array instead when we move past 1.49. Relevant Rust github
1112 : // issues/PRs:
1113 : // - https://github.com/rust-lang/compiler-team/issues/621
1114 : // - https://github.com/rust-lang/rust/pull/78863 (implemented
1115 : // for 1.50.0)
1116 :
1117 14 : TyTy::BaseType *first_field_ty = fields.at (0)->get_field_type ();
1118 14 : TyTy::TypeKind ty_kind = first_field_ty->get_kind ();
1119 14 : bool fields_are_same_type = true;
1120 :
1121 14 : switch (ty_kind)
1122 : {
1123 4 : case TyTy::TypeKind::INT:
1124 4 : {
1125 4 : auto int_ty = static_cast<TyTy::IntType *> (first_field_ty);
1126 4 : auto int_kind = int_ty->get_int_kind ();
1127 22 : for (const auto field : fields)
1128 : {
1129 18 : if (field->get_field_type ()->get_kind () != ty_kind)
1130 : {
1131 : fields_are_same_type = false;
1132 : break;
1133 : }
1134 18 : auto field_int_ty
1135 18 : = static_cast<TyTy::IntType *> (field->get_field_type ());
1136 18 : if (field_int_ty->get_int_kind () != int_kind)
1137 : {
1138 : fields_are_same_type = false;
1139 : break;
1140 : }
1141 : }
1142 : break;
1143 : }
1144 1 : case TyTy::TypeKind::UINT:
1145 1 : {
1146 1 : auto uint_ty = static_cast<TyTy::UintType *> (first_field_ty);
1147 1 : auto uint_kind = uint_ty->get_uint_kind ();
1148 5 : for (const auto field : fields)
1149 : {
1150 4 : if (field->get_field_type ()->get_kind () != ty_kind)
1151 : {
1152 : fields_are_same_type = false;
1153 : break;
1154 : }
1155 4 : auto field_uint_ty
1156 4 : = static_cast<TyTy::UintType *> (field->get_field_type ());
1157 4 : if (field_uint_ty->get_uint_kind () != uint_kind)
1158 : {
1159 : fields_are_same_type = false;
1160 : break;
1161 : }
1162 : }
1163 : break;
1164 : }
1165 8 : case TyTy::TypeKind::FLOAT:
1166 8 : {
1167 8 : auto float_ty = static_cast<TyTy::FloatType *> (first_field_ty);
1168 8 : auto float_kind = float_ty->get_float_kind ();
1169 54 : for (const auto field : fields)
1170 : {
1171 47 : if (field->get_field_type ()->get_kind () != ty_kind)
1172 : {
1173 : fields_are_same_type = false;
1174 : break;
1175 : }
1176 46 : auto field_float_ty
1177 46 : = static_cast<TyTy::FloatType *> (field->get_field_type ());
1178 46 : if (field_float_ty->get_float_kind () != float_kind)
1179 : {
1180 : fields_are_same_type = false;
1181 : break;
1182 : }
1183 : }
1184 : break;
1185 : }
1186 1 : default:
1187 1 : rust_error_at (locus, ErrorCode::E0077,
1188 : "SIMD vector element type should be a primitive scalar");
1189 1 : return false;
1190 : }
1191 :
1192 13 : if (!fields_are_same_type)
1193 : {
1194 1 : rust_error_at (locus, "SIMD struct fields should be of the same type");
1195 1 : return false;
1196 : }
1197 :
1198 : // check whether field count is power of 2
1199 12 : size_t field_count = fields.size ();
1200 12 : if ((field_count & (field_count - 1)) != 0)
1201 : {
1202 1 : rust_error_at (locus, "Size of SIMD struct must be a power of 2");
1203 1 : return false;
1204 : }
1205 : return true;
1206 : }
1207 :
1208 : } // namespace Resolver
1209 : } // namespace Rust
|