Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 "rust-canonical-path.h"
21 : : #include "rust-diagnostics.h"
22 : : #include "rust-hir-type-check-enumitem.h"
23 : : #include "rust-hir-type-check-implitem.h"
24 : : #include "rust-hir-type-check-type.h"
25 : : #include "rust-hir-type-check-expr.h"
26 : : #include "rust-hir-type-check-pattern.h"
27 : : #include "rust-hir-trait-resolve.h"
28 : : #include "rust-identifier.h"
29 : : #include "rust-session-manager.h"
30 : : #include "rust-immutable-name-resolution-context.h"
31 : : #include "rust-substitution-mapper.h"
32 : : #include "rust-type-util.h"
33 : : #include "rust-tyty-variance-analysis.h"
34 : :
35 : : namespace Rust {
36 : : namespace Resolver {
37 : :
38 : 23004 : TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
39 : :
40 : : TyTy::BaseType *
41 : 14961 : TypeCheckItem::Resolve (HIR::Item &item)
42 : : {
43 : : // is it already resolved?
44 : 14961 : auto context = TypeCheckContext::get ();
45 : 14961 : TyTy::BaseType *resolved = nullptr;
46 : 14961 : bool already_resolved
47 : 14961 : = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
48 : 14961 : if (already_resolved)
49 : 932 : return resolved;
50 : :
51 : 14029 : rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
52 : 14029 : HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
53 : :
54 : 14029 : TypeCheckItem resolver;
55 : 14029 : vis_item.accept_vis (resolver);
56 : 14025 : return resolver.infered;
57 : 14025 : }
58 : :
59 : : TyTy::BaseType *
60 : 1392 : TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
61 : : {
62 : 1392 : TypeCheckItem resolver;
63 : 1392 : return resolver.resolve_impl_item (impl_block, item);
64 : 1392 : }
65 : :
66 : : TyTy::BaseType *
67 : 5967 : TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
68 : : {
69 : 5967 : TypeCheckItem resolver;
70 : :
71 : 5967 : bool failed_flag = false;
72 : 5967 : auto result
73 : 5967 : = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
74 : 5967 : if (failed_flag)
75 : : {
76 : 1 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
77 : : }
78 : 5966 : std::vector<TyTy::SubstitutionParamMapping> substitutions
79 : 5966 : = std::move (result.first);
80 : 5966 : TyTy::RegionConstraints region_constraints = std::move (result.second);
81 : :
82 : 5966 : return resolver.resolve_impl_block_self (impl_block);
83 : 5967 : }
84 : :
85 : : TyTy::BaseType *
86 : 1616 : TypeCheckItem::ResolveImplBlockSelfWithInference (
87 : : HIR::ImplBlock &impl, location_t locus,
88 : : TyTy::SubstitutionArgumentMappings *infer_arguments)
89 : : {
90 : 1616 : TypeCheckItem resolver;
91 : :
92 : 1616 : bool failed_flag = false;
93 : 1616 : auto result = resolver.resolve_impl_block_substitutions (impl, failed_flag);
94 : 1616 : if (failed_flag)
95 : : {
96 : 1 : return new TyTy::ErrorType (impl.get_mappings ().get_hirid ());
97 : : }
98 : 1615 : std::vector<TyTy::SubstitutionParamMapping> substitutions
99 : 1615 : = std::move (result.first);
100 : 1615 : TyTy::RegionConstraints region_constraints = std::move (result.second);
101 : :
102 : : // now that we have the param mappings we need to query the self type
103 : 1615 : TyTy::BaseType *self = resolver.resolve_impl_block_self (impl);
104 : :
105 : : // nothing to do
106 : 1615 : if (substitutions.empty () || self->is_concrete ())
107 : 1066 : return self;
108 : :
109 : : // generate inference variables for the subst-param-mappings
110 : 549 : std::vector<TyTy::SubstitutionArg> args;
111 : 1156 : for (auto &p : substitutions)
112 : : {
113 : 607 : if (p.needs_substitution ())
114 : : {
115 : 607 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
116 : 607 : args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
117 : : }
118 : : else
119 : : {
120 : 0 : TyTy::ParamType *param = p.get_param_ty ();
121 : 0 : TyTy::BaseType *resolved = param->destructure ();
122 : 0 : args.push_back (TyTy::SubstitutionArg (&p, resolved));
123 : : }
124 : : }
125 : :
126 : : // create argument mappings
127 : 1098 : *infer_arguments = TyTy::SubstitutionArgumentMappings (
128 : : std::move (args), {},
129 : 549 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (
130 : : infer_arguments),
131 : 1098 : locus);
132 : :
133 : 549 : TyTy::BaseType *infer = SubstMapperInternal::Resolve (self, *infer_arguments);
134 : :
135 : : // we only need to apply to the bounds manually on types which dont bind
136 : : // generics
137 : 549 : if (!infer->has_substitutions_defined ())
138 : : {
139 : 464 : for (auto &bound : infer->get_specified_bounds ())
140 : 96 : bound.handle_substitions (*infer_arguments);
141 : : }
142 : :
143 : 549 : return infer;
144 : 2165 : }
145 : :
146 : : void
147 : 33 : TypeCheckItem::visit (HIR::TypeAlias &alias)
148 : : {
149 : 33 : TyTy::BaseType *actual_type
150 : 33 : = TypeCheckType::Resolve (alias.get_type_aliased ().get ());
151 : :
152 : 33 : context->insert_type (alias.get_mappings (), actual_type);
153 : :
154 : 33 : TyTy::RegionConstraints region_constraints;
155 : 33 : for (auto &where_clause_item : alias.get_where_clause ().get_items ())
156 : : {
157 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
158 : : }
159 : 33 : infered = actual_type;
160 : 33 : }
161 : :
162 : : void
163 : 754 : TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
164 : : {
165 : 754 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
166 : :
167 : 754 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
168 : 754 : if (struct_decl.has_generics ())
169 : 279 : resolve_generic_params (struct_decl.get_generic_params (), substitutions);
170 : :
171 : 754 : TyTy::RegionConstraints region_constraints;
172 : 754 : for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
173 : : {
174 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
175 : : }
176 : :
177 : 754 : std::vector<TyTy::StructFieldType *> fields;
178 : 754 : size_t idx = 0;
179 : 2024 : for (auto &field : struct_decl.get_fields ())
180 : : {
181 : 1270 : TyTy::BaseType *field_type
182 : 1270 : = TypeCheckType::Resolve (field.get_field_type ().get ());
183 : 1270 : auto *ty_field
184 : 2540 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
185 : 1270 : std::to_string (idx), field_type,
186 : 1270 : field.get_locus ());
187 : 1270 : fields.push_back (ty_field);
188 : 1270 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
189 : 1270 : idx++;
190 : : }
191 : :
192 : : // get the path
193 : :
194 : 754 : auto path = CanonicalPath::create_empty ();
195 : :
196 : : // FIXME: HACK: ARTHUR: Disgusting
197 : 754 : if (flag_name_resolution_2_0)
198 : : {
199 : 0 : auto nr_ctx
200 : 0 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
201 : 0 : auto canonical_path = nr_ctx.values.to_canonical_path (
202 : 0 : struct_decl.get_mappings ().get_nodeid ());
203 : :
204 : 0 : path = canonical_path.value ();
205 : 0 : }
206 : : else
207 : : {
208 : 754 : const CanonicalPath *canonical_path = nullptr;
209 : 754 : bool ok = mappings->lookup_canonical_path (
210 : 754 : struct_decl.get_mappings ().get_nodeid (), &canonical_path);
211 : 0 : rust_assert (ok);
212 : :
213 : 754 : path = *canonical_path;
214 : : }
215 : :
216 : 754 : RustIdent ident{path, struct_decl.get_locus ()};
217 : :
218 : : // its a single variant ADT
219 : 754 : std::vector<TyTy::VariantDef *> variants;
220 : 754 : variants.push_back (
221 : 754 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
222 : 754 : struct_decl.get_mappings ().get_defid (),
223 : 754 : struct_decl.get_identifier ().as_string (), ident,
224 : : TyTy::VariantDef::VariantType::TUPLE, nullptr,
225 : 1508 : std::move (fields)));
226 : :
227 : : // Process #[repr(X)] attribute, if any
228 : 754 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
229 : 754 : TyTy::ADTType::ReprOptions repr
230 : 754 : = parse_repr_options (attrs, struct_decl.get_locus ());
231 : :
232 : 754 : auto *type = new TyTy::ADTType (
233 : 1508 : struct_decl.get_mappings ().get_hirid (), mappings->get_next_hir_id (),
234 : 754 : struct_decl.get_identifier ().as_string (), ident,
235 : : TyTy::ADTType::ADTKind::TUPLE_STRUCT, std::move (variants),
236 : : std::move (substitutions), repr,
237 : 1508 : TyTy::SubstitutionArgumentMappings::empty (
238 : 754 : context->get_lifetime_resolver ().get_num_bound_regions ()),
239 : 2262 : region_constraints);
240 : :
241 : 754 : context->insert_type (struct_decl.get_mappings (), type);
242 : 754 : infered = type;
243 : :
244 : 754 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
245 : 1508 : }
246 : :
247 : : void
248 : 920 : TypeCheckItem::visit (HIR::StructStruct &struct_decl)
249 : : {
250 : 920 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
251 : :
252 : 920 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
253 : 920 : if (struct_decl.has_generics ())
254 : 242 : resolve_generic_params (struct_decl.get_generic_params (), substitutions);
255 : :
256 : 920 : TyTy::RegionConstraints region_constraints;
257 : 924 : for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
258 : : {
259 : 4 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
260 : : }
261 : :
262 : 920 : std::vector<TyTy::StructFieldType *> fields;
263 : 2213 : for (auto &field : struct_decl.get_fields ())
264 : : {
265 : 1293 : TyTy::BaseType *field_type
266 : 1293 : = TypeCheckType::Resolve (field.get_field_type ().get ());
267 : 1293 : auto *ty_field
268 : 1293 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
269 : 1293 : field.get_field_name ().as_string (),
270 : 1293 : field_type, field.get_locus ());
271 : 1293 : fields.push_back (ty_field);
272 : 1293 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
273 : : }
274 : :
275 : 920 : auto path = CanonicalPath::create_empty ();
276 : :
277 : : // FIXME: HACK: ARTHUR: Disgusting
278 : 920 : if (flag_name_resolution_2_0)
279 : : {
280 : 3 : auto nr_ctx
281 : 3 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
282 : 3 : auto canonical_path = nr_ctx.types.to_canonical_path (
283 : 3 : struct_decl.get_mappings ().get_nodeid ());
284 : :
285 : 3 : if (!canonical_path.has_value ())
286 : 0 : rust_unreachable ();
287 : 3 : path = canonical_path.value ();
288 : 3 : }
289 : : else
290 : : {
291 : 917 : const CanonicalPath *canonical_path = nullptr;
292 : 917 : bool ok = mappings->lookup_canonical_path (
293 : 917 : struct_decl.get_mappings ().get_nodeid (), &canonical_path);
294 : 0 : rust_assert (ok);
295 : :
296 : 917 : path = *canonical_path;
297 : : }
298 : :
299 : 920 : RustIdent ident{path, struct_decl.get_locus ()};
300 : :
301 : : // its a single variant ADT
302 : 920 : std::vector<TyTy::VariantDef *> variants;
303 : 920 : variants.push_back (
304 : 920 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
305 : 920 : struct_decl.get_mappings ().get_defid (),
306 : 920 : struct_decl.get_identifier ().as_string (), ident,
307 : : TyTy::VariantDef::VariantType::STRUCT, nullptr,
308 : 1840 : std::move (fields)));
309 : :
310 : : // Process #[repr(X)] attribute, if any
311 : 920 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
312 : 920 : TyTy::ADTType::ReprOptions repr
313 : 920 : = parse_repr_options (attrs, struct_decl.get_locus ());
314 : :
315 : 920 : auto *type = new TyTy::ADTType (
316 : 1840 : struct_decl.get_mappings ().get_hirid (), mappings->get_next_hir_id (),
317 : 920 : struct_decl.get_identifier ().as_string (), ident,
318 : : TyTy::ADTType::ADTKind::STRUCT_STRUCT, std::move (variants),
319 : : std::move (substitutions), repr,
320 : 1840 : TyTy::SubstitutionArgumentMappings::empty (
321 : 920 : context->get_lifetime_resolver ().get_num_bound_regions ()),
322 : 2760 : region_constraints);
323 : :
324 : 920 : context->insert_type (struct_decl.get_mappings (), type);
325 : 920 : infered = type;
326 : :
327 : 920 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
328 : 1840 : }
329 : :
330 : : void
331 : 166 : TypeCheckItem::visit (HIR::Enum &enum_decl)
332 : : {
333 : 166 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
334 : 166 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
335 : 166 : if (enum_decl.has_generics ())
336 : 81 : resolve_generic_params (enum_decl.get_generic_params (), substitutions);
337 : :
338 : 166 : std::vector<TyTy::VariantDef *> variants;
339 : 166 : int64_t discriminant_value = 0;
340 : 573 : for (auto &variant : enum_decl.get_variants ())
341 : : {
342 : 407 : TyTy::VariantDef *field_type
343 : 407 : = TypeCheckEnumItem::Resolve (variant.get (), discriminant_value);
344 : :
345 : 407 : discriminant_value++;
346 : 407 : variants.push_back (field_type);
347 : : }
348 : :
349 : : // get the path
350 : 166 : const CanonicalPath *canonical_path = nullptr;
351 : 166 : bool ok
352 : 166 : = mappings->lookup_canonical_path (enum_decl.get_mappings ().get_nodeid (),
353 : : &canonical_path);
354 : 0 : rust_assert (ok);
355 : 166 : RustIdent ident{*canonical_path, enum_decl.get_locus ()};
356 : :
357 : : // multi variant ADT
358 : 166 : auto *type
359 : 166 : = new TyTy::ADTType (enum_decl.get_mappings ().get_hirid (),
360 : 166 : mappings->get_next_hir_id (),
361 : 166 : enum_decl.get_identifier ().as_string (), ident,
362 : : TyTy::ADTType::ADTKind::ENUM, std::move (variants),
363 : 332 : std::move (substitutions));
364 : :
365 : 166 : context->insert_type (enum_decl.get_mappings (), type);
366 : 166 : infered = type;
367 : :
368 : 166 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
369 : 166 : }
370 : :
371 : : void
372 : 90 : TypeCheckItem::visit (HIR::Union &union_decl)
373 : : {
374 : 90 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
375 : 90 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
376 : 90 : if (union_decl.has_generics ())
377 : 65 : resolve_generic_params (union_decl.get_generic_params (), substitutions);
378 : :
379 : 90 : TyTy::RegionConstraints region_constraints;
380 : 90 : for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
381 : : {
382 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
383 : : }
384 : :
385 : 90 : std::vector<TyTy::StructFieldType *> fields;
386 : 356 : for (auto &variant : union_decl.get_variants ())
387 : : {
388 : 266 : TyTy::BaseType *variant_type
389 : 266 : = TypeCheckType::Resolve (variant.get_field_type ().get ());
390 : 266 : auto *ty_variant
391 : 266 : = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
392 : 266 : variant.get_field_name ().as_string (),
393 : 266 : variant_type, variant.get_locus ());
394 : 266 : fields.push_back (ty_variant);
395 : 266 : context->insert_type (variant.get_mappings (),
396 : : ty_variant->get_field_type ());
397 : : }
398 : :
399 : : // get the path
400 : 90 : const CanonicalPath *canonical_path = nullptr;
401 : 90 : bool ok
402 : 90 : = mappings->lookup_canonical_path (union_decl.get_mappings ().get_nodeid (),
403 : : &canonical_path);
404 : 0 : rust_assert (ok);
405 : 90 : RustIdent ident{*canonical_path, union_decl.get_locus ()};
406 : :
407 : : // there is only a single variant
408 : 90 : std::vector<TyTy::VariantDef *> variants;
409 : 90 : variants.push_back (
410 : 90 : new TyTy::VariantDef (union_decl.get_mappings ().get_hirid (),
411 : 90 : union_decl.get_mappings ().get_defid (),
412 : 90 : union_decl.get_identifier ().as_string (), ident,
413 : : TyTy::VariantDef::VariantType::STRUCT, nullptr,
414 : 180 : std::move (fields)));
415 : :
416 : 90 : auto *type
417 : 90 : = new TyTy::ADTType (union_decl.get_mappings ().get_hirid (),
418 : 90 : mappings->get_next_hir_id (),
419 : 90 : union_decl.get_identifier ().as_string (), ident,
420 : : TyTy::ADTType::ADTKind::UNION, std::move (variants),
421 : 180 : std::move (substitutions));
422 : :
423 : 90 : context->insert_type (union_decl.get_mappings (), type);
424 : 90 : infered = type;
425 : :
426 : 90 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
427 : 180 : }
428 : :
429 : : void
430 : 40 : TypeCheckItem::visit (HIR::StaticItem &var)
431 : : {
432 : 40 : TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ().get ());
433 : 40 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ().get ());
434 : :
435 : 40 : TyTy::BaseType *unified
436 : 80 : = coercion_site (var.get_mappings ().get_hirid (),
437 : 40 : TyTy::TyWithLocation (type, var.get_type ()->get_locus ()),
438 : : TyTy::TyWithLocation (expr_type,
439 : 40 : var.get_expr ()->get_locus ()),
440 : : var.get_locus ());
441 : 40 : context->insert_type (var.get_mappings (), unified);
442 : 40 : infered = unified;
443 : 40 : }
444 : :
445 : : void
446 : 372 : TypeCheckItem::visit (HIR::ConstantItem &constant)
447 : : {
448 : 372 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ().get ());
449 : 372 : TyTy::BaseType *expr_type
450 : 372 : = TypeCheckExpr::Resolve (constant.get_expr ().get ());
451 : :
452 : 744 : TyTy::BaseType *unified = unify_site (
453 : 372 : constant.get_mappings ().get_hirid (),
454 : 372 : TyTy::TyWithLocation (type, constant.get_type ()->get_locus ()),
455 : 372 : TyTy::TyWithLocation (expr_type, constant.get_expr ()->get_locus ()),
456 : : constant.get_locus ());
457 : 372 : context->insert_type (constant.get_mappings (), unified);
458 : 372 : infered = unified;
459 : 372 : }
460 : :
461 : : void
462 : 3007 : TypeCheckItem::visit (HIR::ImplBlock &impl_block)
463 : : {
464 : 3007 : auto binder_pin = context->push_clean_lifetime_resolver (true);
465 : :
466 : 3007 : bool failed_flag = false;
467 : 3007 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
468 : 3007 : if (failed_flag)
469 : : {
470 : 2 : infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
471 : 2 : return;
472 : : }
473 : 3005 : std::vector<TyTy::SubstitutionParamMapping> substitutions
474 : 3005 : = std::move (result.first);
475 : 3005 : TyTy::RegionConstraints region_constraints = std::move (result.second);
476 : :
477 : 3005 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
478 : :
479 : : // resolve each impl_item
480 : 7105 : for (auto &impl_item : impl_block.get_impl_items ())
481 : : {
482 : 4100 : TypeCheckImplItem::Resolve (&impl_block, impl_item.get (), self,
483 : : substitutions);
484 : : }
485 : :
486 : : // validate the impl items
487 : 3005 : validate_trait_impl_block (impl_block, self, substitutions);
488 : 3007 : }
489 : :
490 : : TyTy::BaseType *
491 : 1392 : TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
492 : : HIR::ImplItem &item)
493 : : {
494 : 1392 : bool failed_flag = false;
495 : 1392 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
496 : 1392 : if (failed_flag)
497 : : {
498 : 1 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
499 : : }
500 : :
501 : 1391 : std::vector<TyTy::SubstitutionParamMapping> substitutions
502 : 1391 : = std::move (result.first);
503 : 1391 : TyTy::RegionConstraints region_constraints = std::move (result.second);
504 : :
505 : 1391 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
506 : :
507 : 1391 : return TypeCheckImplItem::Resolve (&impl_block, &item, self, substitutions);
508 : 1392 : }
509 : :
510 : : void
511 : 5017 : TypeCheckItem::visit (HIR::Function &function)
512 : : {
513 : 5017 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
514 : 5017 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
515 : 5017 : if (function.has_generics ())
516 : 393 : resolve_generic_params (function.get_generic_params (),
517 : : substitutions); // TODO resolve constraints
518 : :
519 : 5017 : TyTy::RegionConstraints region_constraints;
520 : 5025 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
521 : : {
522 : 8 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
523 : : }
524 : :
525 : 5017 : TyTy::BaseType *ret_type = nullptr;
526 : 5017 : if (!function.has_function_return_type ())
527 : 2754 : ret_type
528 : 2754 : = TyTy::TupleType::get_unit_type (function.get_mappings ().get_hirid ());
529 : : else
530 : : {
531 : 2263 : auto resolved
532 : 2263 : = TypeCheckType::Resolve (function.get_return_type ().get ());
533 : 2263 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
534 : : {
535 : 3 : rust_error_at (function.get_locus (),
536 : : "failed to resolve return type");
537 : 3 : return;
538 : : }
539 : :
540 : 2260 : ret_type = resolved->clone ();
541 : 2260 : ret_type->set_ref (
542 : 4520 : function.get_return_type ()->get_mappings ().get_hirid ());
543 : : }
544 : :
545 : 5014 : std::vector<std::pair<HIR::Pattern *, TyTy::BaseType *>> params;
546 : 6239 : for (auto ¶m : function.get_function_params ())
547 : : {
548 : : // get the name as well required for later on
549 : 1225 : auto param_tyty = TypeCheckType::Resolve (param.get_type ().get ());
550 : 1225 : params.emplace_back (param.get_param_name ().get (), param_tyty);
551 : :
552 : 1225 : context->insert_type (param.get_mappings (), param_tyty);
553 : 1225 : TypeCheckPattern::Resolve (param.get_param_name ().get (), param_tyty);
554 : : }
555 : :
556 : 5014 : auto path = CanonicalPath::create_empty ();
557 : :
558 : : // FIXME: HACK: ARTHUR: Disgusting
559 : 5014 : if (flag_name_resolution_2_0)
560 : : {
561 : 34 : auto nr_ctx
562 : 34 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
563 : 34 : auto canonical_path = nr_ctx.values.to_canonical_path (
564 : 34 : function.get_mappings ().get_nodeid ());
565 : :
566 : 34 : path = canonical_path.value ();
567 : 34 : }
568 : : else
569 : : {
570 : 4980 : const CanonicalPath *canonical_path = nullptr;
571 : 4980 : bool ok = mappings->lookup_canonical_path (
572 : 4980 : function.get_mappings ().get_nodeid (), &canonical_path);
573 : 0 : rust_assert (ok);
574 : :
575 : 4980 : path = *canonical_path;
576 : : }
577 : :
578 : 5014 : RustIdent ident{path, function.get_locus ()};
579 : :
580 : 5014 : auto fn_type = new TyTy::FnType (
581 : 5014 : function.get_mappings ().get_hirid (),
582 : 5014 : function.get_mappings ().get_defid (),
583 : 5014 : function.get_function_name ().as_string (), ident,
584 : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type,
585 : : std::move (substitutions),
586 : 10028 : TyTy::SubstitutionArgumentMappings::empty (
587 : 5014 : context->get_lifetime_resolver ().get_num_bound_regions ()),
588 : 15042 : region_constraints);
589 : :
590 : 5014 : context->insert_type (function.get_mappings (), fn_type);
591 : :
592 : : // need to get the return type from this
593 : 5014 : TyTy::FnType *resolved_fn_type = fn_type;
594 : 5014 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
595 : 5014 : context->push_return_type (TypeCheckContextItem (&function),
596 : : expected_ret_tyty);
597 : :
598 : 5014 : context->switch_to_fn_body ();
599 : 5014 : auto block_expr_ty
600 : 5014 : = TypeCheckExpr::Resolve (function.get_definition ().get ());
601 : :
602 : 5013 : location_t fn_return_locus = function.has_function_return_type ()
603 : 5013 : ? function.get_return_type ()->get_locus ()
604 : 2753 : : function.get_locus ();
605 : 10026 : coercion_site (function.get_definition ()->get_mappings ().get_hirid (),
606 : 5013 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
607 : 5013 : TyTy::TyWithLocation (block_expr_ty),
608 : 5013 : function.get_definition ()->get_locus ());
609 : :
610 : 5013 : context->pop_return_type ();
611 : :
612 : 5013 : infered = fn_type;
613 : 10029 : }
614 : :
615 : : void
616 : 440 : TypeCheckItem::visit (HIR::Module &module)
617 : : {
618 : 994 : for (auto &item : module.get_items ())
619 : 555 : TypeCheckItem::Resolve (*item);
620 : 439 : }
621 : :
622 : : void
623 : 2175 : TypeCheckItem::visit (HIR::Trait &trait)
624 : : {
625 : 2175 : TraitReference *trait_ref = TraitResolver::Resolve (trait);
626 : 2174 : if (trait_ref->is_error ())
627 : : {
628 : 4 : infered = new TyTy::ErrorType (trait.get_mappings ().get_hirid ());
629 : 4 : return;
630 : : }
631 : :
632 : 2170 : RustIdent ident{CanonicalPath::create_empty (), trait.get_locus ()};
633 : 2170 : infered = new TyTy::DynamicObjectType (
634 : 2170 : trait.get_mappings ().get_hirid (), ident,
635 : : {TyTy::TypeBoundPredicate (*trait_ref, BoundPolarity::RegularBound,
636 : 6510 : trait.get_locus ())});
637 : 2170 : }
638 : :
639 : : void
640 : 1015 : TypeCheckItem::visit (HIR::ExternBlock &extern_block)
641 : : {
642 : 2597 : for (auto &item : extern_block.get_extern_items ())
643 : : {
644 : 1583 : TypeCheckTopLevelExternItem::Resolve (item.get (), extern_block);
645 : : }
646 : 1014 : }
647 : :
648 : : std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
649 : 11982 : TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
650 : : bool &failure_flag)
651 : : {
652 : 11982 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
653 : 11982 : if (impl_block.has_generics ())
654 : 4460 : resolve_generic_params (impl_block.get_generic_params (), substitutions);
655 : :
656 : 11982 : TyTy::RegionConstraints region_constraints;
657 : 12405 : for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
658 : : {
659 : 423 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
660 : : }
661 : :
662 : 11982 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
663 : 11982 : TraitReference *trait_reference = &TraitReference::error_node ();
664 : 11982 : if (impl_block.has_trait_ref ())
665 : : {
666 : 8463 : std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
667 : 8463 : trait_reference = TraitResolver::Resolve (*ref);
668 : 8463 : rust_assert (!trait_reference->is_error ());
669 : :
670 : : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
671 : : // for example
672 : 8463 : specified_bound
673 : 8463 : = get_predicate_from_bound (*ref, impl_block.get_type ().get ());
674 : : }
675 : :
676 : 11982 : TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ().get ());
677 : :
678 : : // inherit the bounds
679 : 11982 : if (!specified_bound.is_error ())
680 : 16922 : self->inherit_bounds ({specified_bound});
681 : :
682 : : // check for any unconstrained type-params
683 : 11982 : const TyTy::SubstitutionArgumentMappings trait_constraints
684 : 11982 : = specified_bound.get_substitution_arguments ();
685 : 11982 : const TyTy::SubstitutionArgumentMappings impl_constraints
686 : 11982 : = GetUsedSubstArgs::From (self);
687 : :
688 : 11982 : failure_flag = check_for_unconstrained (substitutions, trait_constraints,
689 : : impl_constraints, self);
690 : :
691 : 11982 : return {substitutions, region_constraints};
692 : 23964 : }
693 : :
694 : : void
695 : 3005 : TypeCheckItem::validate_trait_impl_block (
696 : : HIR::ImplBlock &impl_block, TyTy::BaseType *self,
697 : : std::vector<TyTy::SubstitutionParamMapping> &substitutions)
698 : : {
699 : 3005 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
700 : 3005 : TraitReference *trait_reference = &TraitReference::error_node ();
701 : 3005 : if (impl_block.has_trait_ref ())
702 : : {
703 : 2318 : std::unique_ptr<HIR::TypePath> &ref = impl_block.get_trait_ref ();
704 : 2318 : trait_reference = TraitResolver::Resolve (*ref);
705 : 2318 : rust_assert (!trait_reference->is_error ());
706 : :
707 : : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
708 : : // for example
709 : 2318 : specified_bound
710 : 2318 : = get_predicate_from_bound (*ref, impl_block.get_type ().get ());
711 : : }
712 : :
713 : 3005 : bool is_trait_impl_block = !trait_reference->is_error ();
714 : 3005 : std::vector<const TraitItemReference *> trait_item_refs;
715 : 7105 : for (auto &impl_item : impl_block.get_impl_items ())
716 : : {
717 : 4100 : if (!specified_bound.is_error ())
718 : : {
719 : 2465 : auto trait_item_ref
720 : 2465 : = TypeCheckImplItemWithTrait::Resolve (&impl_block,
721 : : impl_item.get (), self,
722 : : specified_bound,
723 : : substitutions);
724 : 2465 : if (!trait_item_ref.is_error ())
725 : 2462 : trait_item_refs.push_back (trait_item_ref.get_raw_item ());
726 : : }
727 : : }
728 : :
729 : 3005 : bool impl_block_missing_trait_items
730 : 3005 : = !specified_bound.is_error ()
731 : 3005 : && trait_reference->size () != trait_item_refs.size ();
732 : 742 : if (impl_block_missing_trait_items)
733 : : {
734 : : // filter the missing impl_items
735 : 742 : std::vector<std::reference_wrapper<const TraitItemReference>>
736 : 742 : missing_trait_items;
737 : 2184 : for (const auto &trait_item_ref : trait_reference->get_trait_items ())
738 : : {
739 : 1442 : bool found = false;
740 : 2138 : for (auto implemented_trait_item : trait_item_refs)
741 : : {
742 : 1384 : std::string trait_item_name = trait_item_ref.get_identifier ();
743 : 1384 : std::string impl_item_name
744 : 1384 : = implemented_trait_item->get_identifier ();
745 : 1384 : found = trait_item_name == impl_item_name;
746 : 1384 : if (found)
747 : : break;
748 : 1384 : }
749 : :
750 : 1442 : bool is_required_trait_item = !trait_item_ref.is_optional ();
751 : 1442 : if (!found && is_required_trait_item)
752 : 6 : missing_trait_items.emplace_back (trait_item_ref);
753 : : }
754 : :
755 : 742 : if (!missing_trait_items.empty ())
756 : : {
757 : 4 : std::string missing_items_buf;
758 : 4 : rich_location r (line_table, impl_block.get_locus ());
759 : 10 : for (size_t i = 0; i < missing_trait_items.size (); i++)
760 : : {
761 : 6 : bool has_more = (i + 1) < missing_trait_items.size ();
762 : 6 : const TraitItemReference &missing_trait_item
763 : 6 : = missing_trait_items.at (i);
764 : 6 : missing_items_buf += missing_trait_item.get_identifier ()
765 : 12 : + (has_more ? ", " : "");
766 : 6 : r.add_range (missing_trait_item.get_locus ());
767 : : }
768 : :
769 : 4 : rust_error_at (r, ErrorCode::E0046,
770 : : "missing %s in implementation of trait %qs",
771 : : missing_items_buf.c_str (),
772 : 4 : trait_reference->get_name ().c_str ());
773 : 4 : }
774 : 742 : }
775 : :
776 : 3005 : if (is_trait_impl_block)
777 : : {
778 : 2318 : trait_reference->clear_associated_types ();
779 : :
780 : 2318 : AssociatedImplTrait associated (trait_reference, specified_bound,
781 : 2318 : &impl_block, self, context);
782 : 2318 : context->insert_associated_trait_impl (
783 : 2318 : impl_block.get_mappings ().get_hirid (), std::move (associated));
784 : 2318 : context->insert_associated_impl_mapping (
785 : 2318 : trait_reference->get_mappings ().get_hirid (), self,
786 : 2318 : impl_block.get_mappings ().get_hirid ());
787 : 2318 : }
788 : 3005 : }
789 : :
790 : : TyTy::BaseType *
791 : 11977 : TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
792 : : {
793 : 11977 : return TypeCheckType::Resolve (impl_block.get_type ().get ());
794 : : }
795 : :
796 : : } // namespace Resolver
797 : : } // namespace Rust
|