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 "optional.h"
21 : : #include "rust-canonical-path.h"
22 : : #include "rust-diagnostics.h"
23 : : #include "rust-hir-type-check-enumitem.h"
24 : : #include "rust-hir-type-check-implitem.h"
25 : : #include "rust-hir-type-check-type.h"
26 : : #include "rust-hir-type-check-expr.h"
27 : : #include "rust-hir-type-check-pattern.h"
28 : : #include "rust-hir-trait-resolve.h"
29 : : #include "rust-identifier.h"
30 : : #include "rust-session-manager.h"
31 : : #include "rust-immutable-name-resolution-context.h"
32 : : #include "rust-substitution-mapper.h"
33 : : #include "rust-type-util.h"
34 : : #include "rust-tyty-variance-analysis.h"
35 : :
36 : : // for flag_name_resolution_2_0
37 : : #include "options.h"
38 : :
39 : : namespace Rust {
40 : : namespace Resolver {
41 : :
42 : 36939 : TypeCheckItem::TypeCheckItem () : TypeCheckBase (), infered (nullptr) {}
43 : :
44 : : TyTy::BaseType *
45 : 22696 : TypeCheckItem::Resolve (HIR::Item &item)
46 : : {
47 : : // is it already resolved?
48 : 22696 : auto context = TypeCheckContext::get ();
49 : 22696 : TyTy::BaseType *resolved = nullptr;
50 : 22696 : bool already_resolved
51 : 22696 : = context->lookup_type (item.get_mappings ().get_hirid (), &resolved);
52 : 22696 : if (already_resolved)
53 : 2164 : return resolved;
54 : :
55 : 20532 : rust_assert (item.get_hir_kind () == HIR::Node::BaseKind::VIS_ITEM);
56 : 20532 : HIR::VisItem &vis_item = static_cast<HIR::VisItem &> (item);
57 : :
58 : 20532 : TypeCheckItem resolver;
59 : 20532 : vis_item.accept_vis (resolver);
60 : 20528 : return resolver.infered;
61 : 20528 : }
62 : :
63 : : TyTy::BaseType *
64 : 2695 : TypeCheckItem::ResolveImplItem (HIR::ImplBlock &impl_block, HIR::ImplItem &item)
65 : : {
66 : 2695 : TypeCheckItem resolver;
67 : 2695 : return resolver.resolve_impl_item (impl_block, item);
68 : 2695 : }
69 : :
70 : : TyTy::BaseType *
71 : 11347 : TypeCheckItem::ResolveImplBlockSelf (HIR::ImplBlock &impl_block)
72 : : {
73 : 11347 : TypeCheckItem resolver;
74 : :
75 : 11347 : bool failed_flag = false;
76 : 11347 : auto result
77 : 11347 : = resolver.resolve_impl_block_substitutions (impl_block, failed_flag);
78 : 11347 : if (failed_flag)
79 : : {
80 : 2 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
81 : : }
82 : 11345 : std::vector<TyTy::SubstitutionParamMapping> substitutions
83 : 11345 : = std::move (result.first);
84 : 11345 : TyTy::RegionConstraints region_constraints = std::move (result.second);
85 : :
86 : 11345 : return resolver.resolve_impl_block_self (impl_block);
87 : 11347 : }
88 : :
89 : : TyTy::BaseType *
90 : 2365 : TypeCheckItem::ResolveImplBlockSelfWithInference (
91 : : HIR::ImplBlock &impl, location_t locus,
92 : : TyTy::SubstitutionArgumentMappings *infer_arguments)
93 : : {
94 : 2365 : TypeCheckItem resolver;
95 : :
96 : 2365 : bool failed_flag = false;
97 : 2365 : auto result = resolver.resolve_impl_block_substitutions (impl, failed_flag);
98 : 2365 : if (failed_flag)
99 : : {
100 : 2 : return new TyTy::ErrorType (impl.get_mappings ().get_hirid ());
101 : : }
102 : 2363 : std::vector<TyTy::SubstitutionParamMapping> substitutions
103 : 2363 : = std::move (result.first);
104 : 2363 : TyTy::RegionConstraints region_constraints = std::move (result.second);
105 : :
106 : : // now that we have the param mappings we need to query the self type
107 : 2363 : TyTy::BaseType *self = resolver.resolve_impl_block_self (impl);
108 : :
109 : : // nothing to do
110 : 2363 : if (substitutions.empty () || self->is_concrete ())
111 : 1642 : return self;
112 : :
113 : : // generate inference variables for the subst-param-mappings
114 : 721 : std::vector<TyTy::SubstitutionArg> args;
115 : 1520 : for (auto &p : substitutions)
116 : : {
117 : 799 : if (p.needs_substitution ())
118 : : {
119 : 799 : TyTy::TyVar infer_var = TyTy::TyVar::get_implicit_infer_var (locus);
120 : 799 : args.push_back (TyTy::SubstitutionArg (&p, infer_var.get_tyty ()));
121 : : }
122 : : else
123 : : {
124 : 0 : TyTy::ParamType *param = p.get_param_ty ();
125 : 0 : TyTy::BaseType *resolved = param->destructure ();
126 : 0 : args.push_back (TyTy::SubstitutionArg (&p, resolved));
127 : : }
128 : : }
129 : :
130 : : // create argument mappings
131 : 1442 : *infer_arguments = TyTy::SubstitutionArgumentMappings (
132 : : std::move (args), {},
133 : 721 : TyTy::SubstitutionArgumentMappings::regions_from_nullable_args (
134 : : infer_arguments),
135 : 1442 : locus);
136 : :
137 : 721 : TyTy::BaseType *infer = SubstMapperInternal::Resolve (self, *infer_arguments);
138 : :
139 : : // we only need to apply to the bounds manually on types which dont bind
140 : : // generics
141 : 721 : if (!infer->has_substitutions_defined ())
142 : : {
143 : 686 : for (auto &bound : infer->get_specified_bounds ())
144 : 185 : bound.handle_substitions (*infer_arguments);
145 : : }
146 : :
147 : 721 : return infer;
148 : 3086 : }
149 : :
150 : : void
151 : 61 : TypeCheckItem::visit (HIR::TypeAlias &alias)
152 : : {
153 : 61 : TyTy::BaseType *actual_type
154 : 61 : = TypeCheckType::Resolve (alias.get_type_aliased ());
155 : :
156 : 61 : context->insert_type (alias.get_mappings (), actual_type);
157 : :
158 : 61 : TyTy::RegionConstraints region_constraints;
159 : 61 : for (auto &where_clause_item : alias.get_where_clause ().get_items ())
160 : : {
161 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
162 : : }
163 : 61 : infered = actual_type;
164 : 61 : }
165 : :
166 : : void
167 : 980 : TypeCheckItem::visit (HIR::TupleStruct &struct_decl)
168 : : {
169 : 980 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
170 : :
171 : 980 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
172 : 980 : if (struct_decl.has_generics ())
173 : 352 : resolve_generic_params (struct_decl.get_generic_params (), substitutions);
174 : :
175 : 980 : TyTy::RegionConstraints region_constraints;
176 : 980 : for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
177 : : {
178 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
179 : : }
180 : :
181 : 980 : std::vector<TyTy::StructFieldType *> fields;
182 : 980 : size_t idx = 0;
183 : 2686 : for (auto &field : struct_decl.get_fields ())
184 : : {
185 : 1706 : TyTy::BaseType *field_type
186 : 1706 : = TypeCheckType::Resolve (field.get_field_type ());
187 : 1706 : auto *ty_field
188 : 3412 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
189 : 1706 : std::to_string (idx), field_type,
190 : 1706 : field.get_locus ());
191 : 1706 : fields.push_back (ty_field);
192 : 1706 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
193 : 1706 : idx++;
194 : : }
195 : :
196 : : // get the path
197 : :
198 : 980 : auto path = CanonicalPath::create_empty ();
199 : :
200 : : // FIXME: HACK: ARTHUR: Disgusting
201 : 980 : if (flag_name_resolution_2_0)
202 : : {
203 : 140 : auto &nr_ctx
204 : 140 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
205 : :
206 : 140 : path = nr_ctx.values
207 : 280 : .to_canonical_path (struct_decl.get_mappings ().get_nodeid ())
208 : 140 : .value ();
209 : : }
210 : : else
211 : : {
212 : 840 : path
213 : 840 : = mappings
214 : 840 : .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
215 : 840 : .value ();
216 : : }
217 : :
218 : 980 : RustIdent ident{path, struct_decl.get_locus ()};
219 : :
220 : : // its a single variant ADT
221 : 980 : std::vector<TyTy::VariantDef *> variants;
222 : 980 : variants.push_back (
223 : 980 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
224 : 980 : struct_decl.get_mappings ().get_defid (),
225 : 980 : struct_decl.get_identifier ().as_string (), ident,
226 : 1960 : TyTy::VariantDef::VariantType::TUPLE, tl::nullopt,
227 : 2940 : std::move (fields)));
228 : :
229 : : // Process #[repr(X)] attribute, if any
230 : 980 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
231 : 980 : TyTy::ADTType::ReprOptions repr
232 : 980 : = parse_repr_options (attrs, struct_decl.get_locus ());
233 : :
234 : 980 : auto *type = new TyTy::ADTType (
235 : 980 : struct_decl.get_mappings ().get_defid (),
236 : 980 : struct_decl.get_mappings ().get_hirid (),
237 : 980 : struct_decl.get_mappings ().get_hirid (),
238 : 980 : struct_decl.get_identifier ().as_string (), ident,
239 : : TyTy::ADTType::ADTKind::TUPLE_STRUCT, std::move (variants),
240 : : std::move (substitutions), repr,
241 : 1960 : TyTy::SubstitutionArgumentMappings::empty (
242 : 980 : context->get_lifetime_resolver ().get_num_bound_regions ()),
243 : 3920 : region_constraints);
244 : :
245 : 980 : context->insert_type (struct_decl.get_mappings (), type);
246 : 980 : infered = type;
247 : :
248 : 980 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
249 : 1960 : }
250 : :
251 : : void
252 : 1332 : TypeCheckItem::visit (HIR::StructStruct &struct_decl)
253 : : {
254 : 1332 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
255 : :
256 : 1332 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
257 : 1332 : if (struct_decl.has_generics ())
258 : 340 : resolve_generic_params (struct_decl.get_generic_params (), substitutions);
259 : :
260 : 1332 : TyTy::RegionConstraints region_constraints;
261 : 1340 : for (auto &where_clause_item : struct_decl.get_where_clause ().get_items ())
262 : : {
263 : 8 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
264 : : }
265 : :
266 : 1332 : std::vector<TyTy::StructFieldType *> fields;
267 : 3048 : for (auto &field : struct_decl.get_fields ())
268 : : {
269 : 1716 : TyTy::BaseType *field_type
270 : 1716 : = TypeCheckType::Resolve (field.get_field_type ());
271 : 1716 : auto *ty_field
272 : 1716 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
273 : 1716 : field.get_field_name ().as_string (),
274 : 3432 : field_type, field.get_locus ());
275 : 1716 : fields.push_back (ty_field);
276 : 1716 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
277 : : }
278 : :
279 : 1332 : auto path = CanonicalPath::create_empty ();
280 : :
281 : : // FIXME: HACK: ARTHUR: Disgusting
282 : 1332 : if (flag_name_resolution_2_0)
283 : : {
284 : 261 : auto &nr_ctx
285 : 261 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
286 : 261 : auto canonical_path = nr_ctx.types.to_canonical_path (
287 : 261 : struct_decl.get_mappings ().get_nodeid ());
288 : :
289 : 261 : if (!canonical_path.has_value ())
290 : 0 : rust_unreachable ();
291 : 261 : path = canonical_path.value ();
292 : 261 : }
293 : : else
294 : : {
295 : 1071 : path
296 : 1071 : = mappings
297 : 1071 : .lookup_canonical_path (struct_decl.get_mappings ().get_nodeid ())
298 : 1071 : .value ();
299 : : }
300 : :
301 : 1332 : RustIdent ident{path, struct_decl.get_locus ()};
302 : :
303 : : // its a single variant ADT
304 : 1332 : std::vector<TyTy::VariantDef *> variants;
305 : 1332 : variants.push_back (
306 : 1332 : new TyTy::VariantDef (struct_decl.get_mappings ().get_hirid (),
307 : 1332 : struct_decl.get_mappings ().get_defid (),
308 : 1332 : struct_decl.get_identifier ().as_string (), ident,
309 : 2664 : TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
310 : 3996 : std::move (fields)));
311 : :
312 : : // Process #[repr(X)] attribute, if any
313 : 1332 : const AST::AttrVec &attrs = struct_decl.get_outer_attrs ();
314 : 1332 : TyTy::ADTType::ReprOptions repr
315 : 1332 : = parse_repr_options (attrs, struct_decl.get_locus ());
316 : :
317 : 1332 : auto *type = new TyTy::ADTType (
318 : 1332 : struct_decl.get_mappings ().get_defid (),
319 : 1332 : struct_decl.get_mappings ().get_hirid (),
320 : 1332 : struct_decl.get_mappings ().get_hirid (),
321 : 1332 : struct_decl.get_identifier ().as_string (), ident,
322 : : TyTy::ADTType::ADTKind::STRUCT_STRUCT, std::move (variants),
323 : : std::move (substitutions), repr,
324 : 2664 : TyTy::SubstitutionArgumentMappings::empty (
325 : 1332 : context->get_lifetime_resolver ().get_num_bound_regions ()),
326 : 5328 : region_constraints);
327 : :
328 : 1332 : context->insert_type (struct_decl.get_mappings (), type);
329 : 1332 : infered = type;
330 : :
331 : 1332 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
332 : 2664 : }
333 : :
334 : : void
335 : 383 : TypeCheckItem::visit (HIR::Enum &enum_decl)
336 : : {
337 : 383 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
338 : 383 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
339 : 383 : if (enum_decl.has_generics ())
340 : 166 : resolve_generic_params (enum_decl.get_generic_params (), substitutions);
341 : :
342 : : // Process #[repr(X)] attribute, if any
343 : 383 : const AST::AttrVec &attrs = enum_decl.get_outer_attrs ();
344 : 383 : TyTy::ADTType::ReprOptions repr
345 : 383 : = parse_repr_options (attrs, enum_decl.get_locus ());
346 : :
347 : 383 : std::vector<TyTy::VariantDef *> variants;
348 : 383 : int64_t discriminant_value = 0;
349 : 1225 : for (auto &variant : enum_decl.get_variants ())
350 : : {
351 : 842 : TyTy::VariantDef *field_type
352 : 842 : = TypeCheckEnumItem::Resolve (*variant, discriminant_value);
353 : :
354 : 842 : discriminant_value++;
355 : 842 : variants.push_back (field_type);
356 : : }
357 : :
358 : : // Check for zero-variant enum compatibility
359 : 383 : if (enum_decl.is_zero_variant ())
360 : : {
361 : 16 : if (repr.repr_kind == TyTy::ADTType::ReprKind::INT
362 : 16 : || repr.repr_kind == TyTy::ADTType::ReprKind::C)
363 : : {
364 : 4 : rust_error_at (enum_decl.get_locus (),
365 : : "unsupported representation for zero-variant enum");
366 : 4 : return;
367 : : }
368 : : }
369 : :
370 : : // get the path
371 : 379 : tl::optional<CanonicalPath> canonical_path;
372 : :
373 : 379 : if (flag_name_resolution_2_0)
374 : : {
375 : 88 : auto &nr_ctx
376 : 88 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
377 : :
378 : 176 : canonical_path = nr_ctx.types.to_canonical_path (
379 : 176 : enum_decl.get_mappings ().get_nodeid ());
380 : : }
381 : : else
382 : : {
383 : 291 : canonical_path = mappings.lookup_canonical_path (
384 : 291 : enum_decl.get_mappings ().get_nodeid ());
385 : : }
386 : :
387 : 379 : rust_assert (canonical_path.has_value ());
388 : :
389 : 379 : RustIdent ident{*canonical_path, enum_decl.get_locus ()};
390 : :
391 : : // multi variant ADT
392 : 379 : auto *type
393 : 379 : = new TyTy::ADTType (enum_decl.get_mappings ().get_defid (),
394 : 379 : enum_decl.get_mappings ().get_hirid (),
395 : 379 : enum_decl.get_mappings ().get_hirid (),
396 : 379 : enum_decl.get_identifier ().as_string (), ident,
397 : : TyTy::ADTType::ADTKind::ENUM, std::move (variants),
398 : 1137 : std::move (substitutions), repr);
399 : :
400 : 379 : context->insert_type (enum_decl.get_mappings (), type);
401 : 379 : infered = type;
402 : :
403 : 379 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
404 : 762 : }
405 : :
406 : : void
407 : 104 : TypeCheckItem::visit (HIR::Union &union_decl)
408 : : {
409 : 104 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
410 : 104 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
411 : 104 : if (union_decl.has_generics ())
412 : 70 : resolve_generic_params (union_decl.get_generic_params (), substitutions);
413 : :
414 : 104 : TyTy::RegionConstraints region_constraints;
415 : 104 : for (auto &where_clause_item : union_decl.get_where_clause ().get_items ())
416 : : {
417 : 0 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
418 : : }
419 : :
420 : 104 : std::vector<TyTy::StructFieldType *> fields;
421 : 406 : for (auto &variant : union_decl.get_variants ())
422 : : {
423 : 302 : TyTy::BaseType *variant_type
424 : 302 : = TypeCheckType::Resolve (variant.get_field_type ());
425 : 302 : auto *ty_variant
426 : 302 : = new TyTy::StructFieldType (variant.get_mappings ().get_hirid (),
427 : 302 : variant.get_field_name ().as_string (),
428 : 604 : variant_type, variant.get_locus ());
429 : 302 : fields.push_back (ty_variant);
430 : 302 : context->insert_type (variant.get_mappings (),
431 : : ty_variant->get_field_type ());
432 : : }
433 : :
434 : : // get the path
435 : 104 : tl::optional<CanonicalPath> canonical_path;
436 : :
437 : 104 : if (flag_name_resolution_2_0)
438 : : {
439 : 12 : auto &nr_ctx
440 : 12 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
441 : :
442 : 24 : canonical_path = nr_ctx.types.to_canonical_path (
443 : 24 : union_decl.get_mappings ().get_nodeid ());
444 : : }
445 : : else
446 : : {
447 : 92 : canonical_path = mappings.lookup_canonical_path (
448 : 92 : union_decl.get_mappings ().get_nodeid ());
449 : : }
450 : :
451 : 104 : rust_assert (canonical_path.has_value ());
452 : :
453 : 104 : RustIdent ident{*canonical_path, union_decl.get_locus ()};
454 : :
455 : : // there is only a single variant
456 : 104 : std::vector<TyTy::VariantDef *> variants;
457 : 104 : variants.push_back (
458 : 104 : new TyTy::VariantDef (union_decl.get_mappings ().get_hirid (),
459 : 104 : union_decl.get_mappings ().get_defid (),
460 : 104 : union_decl.get_identifier ().as_string (), ident,
461 : 208 : TyTy::VariantDef::VariantType::STRUCT, tl::nullopt,
462 : 312 : std::move (fields)));
463 : :
464 : 104 : auto *type
465 : 104 : = new TyTy::ADTType (union_decl.get_mappings ().get_defid (),
466 : 104 : union_decl.get_mappings ().get_hirid (),
467 : 104 : union_decl.get_mappings ().get_hirid (),
468 : 104 : union_decl.get_identifier ().as_string (), ident,
469 : : TyTy::ADTType::ADTKind::UNION, std::move (variants),
470 : 312 : std::move (substitutions));
471 : :
472 : 104 : context->insert_type (union_decl.get_mappings (), type);
473 : 104 : infered = type;
474 : :
475 : 104 : context->get_variance_analysis_ctx ().add_type_constraints (*type);
476 : 312 : }
477 : :
478 : : void
479 : 61 : TypeCheckItem::visit (HIR::StaticItem &var)
480 : : {
481 : 61 : TyTy::BaseType *type = TypeCheckType::Resolve (var.get_type ());
482 : 61 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (var.get_expr ());
483 : :
484 : 61 : TyTy::BaseType *unified
485 : 61 : = coercion_site (var.get_mappings ().get_hirid (),
486 : 61 : TyTy::TyWithLocation (type, var.get_type ().get_locus ()),
487 : : TyTy::TyWithLocation (expr_type,
488 : 61 : var.get_expr ().get_locus ()),
489 : : var.get_locus ());
490 : 61 : context->insert_type (var.get_mappings (), unified);
491 : 61 : infered = unified;
492 : 61 : }
493 : :
494 : : void
495 : 453 : TypeCheckItem::visit (HIR::ConstantItem &constant)
496 : : {
497 : 453 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
498 : 453 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
499 : :
500 : 906 : TyTy::BaseType *unified = unify_site (
501 : 453 : constant.get_mappings ().get_hirid (),
502 : 453 : TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
503 : 453 : TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
504 : : constant.get_locus ());
505 : 453 : context->insert_type (constant.get_mappings (), unified);
506 : 453 : infered = unified;
507 : 453 : }
508 : :
509 : : void
510 : 4920 : TypeCheckItem::visit (HIR::ImplBlock &impl_block)
511 : : {
512 : 4920 : auto binder_pin = context->push_clean_lifetime_resolver (true);
513 : :
514 : 4920 : TraitReference *trait_reference = &TraitReference::error_node ();
515 : 4920 : if (impl_block.has_trait_ref ())
516 : : {
517 : 3951 : HIR::TypePath &ref = impl_block.get_trait_ref ();
518 : 3951 : trait_reference = TraitResolver::Resolve (ref);
519 : 3951 : if (trait_reference->is_error ())
520 : : return;
521 : : }
522 : :
523 : 4918 : bool failed_flag = false;
524 : 4918 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
525 : 4918 : if (failed_flag)
526 : : {
527 : 4 : infered = new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
528 : 4 : return;
529 : : }
530 : 4914 : std::vector<TyTy::SubstitutionParamMapping> substitutions
531 : 4914 : = std::move (result.first);
532 : 4914 : TyTy::RegionConstraints region_constraints = std::move (result.second);
533 : :
534 : 4914 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
535 : :
536 : : // resolve each impl_item
537 : 11999 : for (auto &impl_item : impl_block.get_impl_items ())
538 : : {
539 : 7085 : TypeCheckImplItem::Resolve (impl_block, *impl_item, self, substitutions);
540 : : }
541 : :
542 : : // validate the impl items
543 : 4914 : validate_trait_impl_block (trait_reference, impl_block, self, substitutions);
544 : 4920 : }
545 : :
546 : : TyTy::BaseType *
547 : 2695 : TypeCheckItem::resolve_impl_item (HIR::ImplBlock &impl_block,
548 : : HIR::ImplItem &item)
549 : : {
550 : 2695 : bool failed_flag = false;
551 : 2695 : auto result = resolve_impl_block_substitutions (impl_block, failed_flag);
552 : 2695 : if (failed_flag)
553 : : {
554 : 2 : return new TyTy::ErrorType (impl_block.get_mappings ().get_hirid ());
555 : : }
556 : :
557 : 2693 : std::vector<TyTy::SubstitutionParamMapping> substitutions
558 : 2693 : = std::move (result.first);
559 : 2693 : TyTy::RegionConstraints region_constraints = std::move (result.second);
560 : :
561 : 2693 : TyTy::BaseType *self = resolve_impl_block_self (impl_block);
562 : :
563 : 2693 : return TypeCheckImplItem::Resolve (impl_block, item, self, substitutions);
564 : 2695 : }
565 : :
566 : : void
567 : 6657 : TypeCheckItem::visit (HIR::Function &function)
568 : : {
569 : 6657 : auto lifetime_pin = context->push_clean_lifetime_resolver ();
570 : 6657 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
571 : 6657 : if (function.has_generics ())
572 : 616 : resolve_generic_params (function.get_generic_params (),
573 : : substitutions); // TODO resolve constraints
574 : :
575 : 6657 : TyTy::RegionConstraints region_constraints;
576 : 6668 : for (auto &where_clause_item : function.get_where_clause ().get_items ())
577 : : {
578 : 11 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
579 : : }
580 : :
581 : 6657 : TyTy::BaseType *ret_type = nullptr;
582 : 6657 : if (!function.has_function_return_type ())
583 : 3826 : ret_type = TyTy::TupleType::get_unit_type ();
584 : : else
585 : : {
586 : 2831 : auto resolved = TypeCheckType::Resolve (function.get_return_type ());
587 : 2831 : if (resolved->get_kind () == TyTy::TypeKind::ERROR)
588 : : {
589 : 4 : rust_error_at (function.get_locus (),
590 : : "failed to resolve return type");
591 : 4 : return;
592 : : }
593 : :
594 : 2827 : ret_type = resolved->clone ();
595 : 2827 : ret_type->set_ref (
596 : 2827 : function.get_return_type ().get_mappings ().get_hirid ());
597 : : }
598 : :
599 : 6653 : std::vector<TyTy::FnParam> params;
600 : 8576 : for (auto ¶m : function.get_function_params ())
601 : : {
602 : : // get the name as well required for later on
603 : 1923 : auto param_tyty = TypeCheckType::Resolve (param.get_type ());
604 : 1923 : context->insert_type (param.get_mappings (), param_tyty);
605 : 1923 : TypeCheckPattern::Resolve (param.get_param_name (), param_tyty);
606 : 3846 : params.push_back (
607 : 3846 : TyTy::FnParam (param.get_param_name ().clone_pattern (), param_tyty));
608 : : }
609 : :
610 : 6653 : auto path = CanonicalPath::create_empty ();
611 : :
612 : : // FIXME: HACK: ARTHUR: Disgusting
613 : 6653 : if (flag_name_resolution_2_0)
614 : : {
615 : 1096 : auto &nr_ctx
616 : 1096 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
617 : 1096 : auto canonical_path = nr_ctx.values.to_canonical_path (
618 : 1096 : function.get_mappings ().get_nodeid ());
619 : :
620 : 1096 : path = canonical_path.value ();
621 : 1096 : }
622 : : else
623 : : {
624 : 5557 : path = mappings
625 : 5557 : .lookup_canonical_path (function.get_mappings ().get_nodeid ())
626 : 5557 : .value ();
627 : : }
628 : :
629 : 6653 : RustIdent ident{path, function.get_locus ()};
630 : :
631 : 6653 : auto fn_type = new TyTy::FnType (
632 : 6653 : function.get_mappings ().get_hirid (),
633 : 6653 : function.get_mappings ().get_defid (),
634 : 6653 : function.get_function_name ().as_string (), ident,
635 : : TyTy::FnType::FNTYPE_DEFAULT_FLAGS, ABI::RUST, std::move (params), ret_type,
636 : : std::move (substitutions),
637 : 13306 : TyTy::SubstitutionArgumentMappings::empty (
638 : 6653 : context->get_lifetime_resolver ().get_num_bound_regions ()),
639 : 26612 : region_constraints);
640 : :
641 : 6653 : context->insert_type (function.get_mappings (), fn_type);
642 : :
643 : : // need to get the return type from this
644 : 6653 : TyTy::FnType *resolved_fn_type = fn_type;
645 : 6653 : auto expected_ret_tyty = resolved_fn_type->get_return_type ();
646 : 6653 : context->push_return_type (TypeCheckContextItem (&function),
647 : : expected_ret_tyty);
648 : :
649 : 6653 : context->switch_to_fn_body ();
650 : 6653 : auto block_expr_ty = TypeCheckExpr::Resolve (function.get_definition ());
651 : :
652 : : // emit check for
653 : : // error[E0121]: the type placeholder `_` is not allowed within types on item
654 : 6653 : const auto placeholder = ret_type->contains_infer ();
655 : 6653 : if (placeholder != nullptr && function.has_return_type ())
656 : : {
657 : : // FIXME
658 : : // this will be a great place for the Default Hir Visitor we want to
659 : : // grab the locations of the placeholders (HIR::InferredType) their
660 : : // location, for now maybe we can use their hirid to lookup the location
661 : 6 : location_t placeholder_locus
662 : 6 : = mappings.lookup_location (placeholder->get_ref ());
663 : 6 : location_t type_locus = function.get_return_type ().get_locus ();
664 : 6 : rich_location r (line_table, placeholder_locus);
665 : :
666 : 6 : bool have_expected_type
667 : 12 : = block_expr_ty != nullptr && !block_expr_ty->is<TyTy::ErrorType> ();
668 : 6 : if (!have_expected_type)
669 : : {
670 : 0 : r.add_range (type_locus);
671 : : }
672 : : else
673 : : {
674 : 6 : std::string fixit
675 : 6 : = "replace with the correct type " + block_expr_ty->get_name ();
676 : 6 : r.add_fixit_replace (type_locus, fixit.c_str ());
677 : 6 : }
678 : :
679 : 6 : rust_error_at (r, ErrorCode::E0121,
680 : : "the type placeholder %<_%> is not allowed within types "
681 : : "on item signatures");
682 : 6 : }
683 : :
684 : 6653 : location_t fn_return_locus = function.has_function_return_type ()
685 : 6653 : ? function.get_return_type ().get_locus ()
686 : 3826 : : function.get_locus ();
687 : 13306 : coercion_site (function.get_definition ().get_mappings ().get_hirid (),
688 : 6653 : TyTy::TyWithLocation (expected_ret_tyty, fn_return_locus),
689 : 6653 : TyTy::TyWithLocation (block_expr_ty),
690 : 6653 : function.get_definition ().get_locus ());
691 : :
692 : 6653 : context->pop_return_type ();
693 : :
694 : 6653 : infered = fn_type;
695 : 13310 : }
696 : :
697 : : void
698 : 929 : TypeCheckItem::visit (HIR::Module &module)
699 : : {
700 : 4022 : for (auto &item : module.get_items ())
701 : 3095 : TypeCheckItem::Resolve (*item);
702 : 927 : }
703 : :
704 : : void
705 : 3406 : TypeCheckItem::visit (HIR::Trait &trait)
706 : : {
707 : 3406 : if (trait.has_type_param_bounds ())
708 : : {
709 : 712 : for (auto &tp_bound : trait.get_type_param_bounds ())
710 : : {
711 : 357 : if (tp_bound.get ()->get_bound_type ()
712 : : == HIR::TypeParamBound::BoundType::TRAITBOUND)
713 : : {
714 : 357 : HIR::TraitBound &tb
715 : 357 : = static_cast<HIR::TraitBound &> (*tp_bound.get ());
716 : 357 : if (tb.get_polarity () == BoundPolarity::AntiBound)
717 : : {
718 : 2 : rust_error_at (tb.get_locus (),
719 : : "%<?Trait%> is not permitted in supertraits");
720 : : }
721 : : }
722 : : }
723 : : }
724 : :
725 : 3406 : TraitReference *trait_ref = TraitResolver::Resolve (trait);
726 : 3406 : if (trait_ref->is_error ())
727 : : {
728 : 8 : infered = new TyTy::ErrorType (trait.get_mappings ().get_hirid ());
729 : 8 : return;
730 : : }
731 : :
732 : 3398 : RustIdent ident{CanonicalPath::create_empty (), trait.get_locus ()};
733 : 3398 : infered = new TyTy::DynamicObjectType (
734 : 3398 : trait.get_mappings ().get_hirid (), ident,
735 : : {TyTy::TypeBoundPredicate (*trait_ref, BoundPolarity::RegularBound,
736 : 10194 : trait.get_locus ())});
737 : 3398 : }
738 : :
739 : : void
740 : 1246 : TypeCheckItem::visit (HIR::ExternBlock &extern_block)
741 : : {
742 : 3324 : for (auto &item : extern_block.get_extern_items ())
743 : : {
744 : 2080 : TypeCheckTopLevelExternItem::Resolve (*item, extern_block);
745 : : }
746 : 1244 : }
747 : :
748 : : std::pair<std::vector<TyTy::SubstitutionParamMapping>, TyTy::RegionConstraints>
749 : 21325 : TypeCheckItem::resolve_impl_block_substitutions (HIR::ImplBlock &impl_block,
750 : : bool &failure_flag)
751 : : {
752 : 21325 : std::vector<TyTy::SubstitutionParamMapping> substitutions;
753 : 21325 : if (impl_block.has_generics ())
754 : 5949 : resolve_generic_params (impl_block.get_generic_params (), substitutions);
755 : :
756 : 21325 : TyTy::RegionConstraints region_constraints;
757 : 21812 : for (auto &where_clause_item : impl_block.get_where_clause ().get_items ())
758 : : {
759 : 487 : ResolveWhereClauseItem::Resolve (*where_clause_item, region_constraints);
760 : : }
761 : :
762 : 21325 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
763 : 21325 : TraitReference *trait_reference = &TraitReference::error_node ();
764 : 21325 : if (impl_block.has_trait_ref ())
765 : : {
766 : 15526 : auto &ref = impl_block.get_trait_ref ();
767 : 15526 : trait_reference = TraitResolver::Resolve (ref);
768 : 15526 : rust_assert (!trait_reference->is_error ());
769 : :
770 : : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
771 : : // for example
772 : 31052 : specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
773 : 15526 : impl_block.get_polarity ());
774 : : }
775 : :
776 : 21325 : TyTy::BaseType *self = TypeCheckType::Resolve (impl_block.get_type ());
777 : 21325 : if (self->is<TyTy::ErrorType> ())
778 : : {
779 : : // we cannot check for unconstrained type arguments when the Self type is
780 : : // not resolved it will just add extra errors that dont help as well as
781 : : // the case where this could just be a recursive type query that should
782 : : // fail and will work later on anyway
783 : 4 : return {substitutions, region_constraints};
784 : : }
785 : :
786 : : // inherit the bounds
787 : 21321 : if (!specified_bound.is_error ())
788 : 31042 : self->inherit_bounds ({specified_bound});
789 : :
790 : : // check for any unconstrained type-params
791 : 21321 : const TyTy::SubstitutionArgumentMappings trait_constraints
792 : 21321 : = specified_bound.get_substitution_arguments ();
793 : 21321 : const TyTy::SubstitutionArgumentMappings impl_constraints
794 : 21321 : = GetUsedSubstArgs::From (self);
795 : :
796 : 21321 : failure_flag = check_for_unconstrained (substitutions, trait_constraints,
797 : : impl_constraints, self);
798 : :
799 : 21321 : return {substitutions, region_constraints};
800 : 42650 : }
801 : :
802 : : void
803 : 4914 : TypeCheckItem::validate_trait_impl_block (
804 : : TraitReference *trait_reference, HIR::ImplBlock &impl_block,
805 : : TyTy::BaseType *self,
806 : : std::vector<TyTy::SubstitutionParamMapping> &substitutions)
807 : : {
808 : 4914 : auto specified_bound = TyTy::TypeBoundPredicate::error ();
809 : 4914 : if (impl_block.has_trait_ref ())
810 : : {
811 : 3947 : auto &ref = impl_block.get_trait_ref ();
812 : 3947 : trait_reference = TraitResolver::Resolve (ref);
813 : 3947 : if (trait_reference->is_error ())
814 : 0 : return;
815 : :
816 : : // we don't error out here see: gcc/testsuite/rust/compile/traits2.rs
817 : : // for example
818 : 7894 : specified_bound = get_predicate_from_bound (ref, impl_block.get_type (),
819 : 3947 : impl_block.get_polarity ());
820 : :
821 : : // need to check that if this specified bound has super traits does this
822 : : // Self
823 : : // implement them?
824 : 3947 : specified_bound.validate_type_implements_super_traits (
825 : 3947 : *self, impl_block.get_type (), impl_block.get_trait_ref ());
826 : : }
827 : :
828 : 4914 : bool is_trait_impl_block = !trait_reference->is_error ();
829 : 4914 : std::vector<const TraitItemReference *> trait_item_refs;
830 : 11999 : for (auto &impl_item : impl_block.get_impl_items ())
831 : : {
832 : 7085 : if (!specified_bound.is_error ())
833 : : {
834 : 4245 : auto trait_item_ref
835 : 4245 : = TypeCheckImplItemWithTrait::Resolve (impl_block, *impl_item, self,
836 : : specified_bound,
837 : 4245 : substitutions);
838 : 4245 : if (!trait_item_ref.is_error ())
839 : 4239 : trait_item_refs.push_back (trait_item_ref.get_raw_item ());
840 : 4245 : }
841 : : }
842 : :
843 : 4914 : bool impl_block_missing_trait_items
844 : 4914 : = !specified_bound.is_error ()
845 : 4914 : && trait_reference->size () != trait_item_refs.size ();
846 : 1157 : if (impl_block_missing_trait_items
847 : 1157 : && impl_block.get_polarity () == BoundPolarity::RegularBound)
848 : : {
849 : : // filter the missing impl_items
850 : 1153 : std::vector<std::reference_wrapper<const TraitItemReference>>
851 : 1153 : missing_trait_items;
852 : 3415 : for (const auto &trait_item_ref : trait_reference->get_trait_items ())
853 : : {
854 : 2262 : bool found = false;
855 : 3369 : for (auto implemented_trait_item : trait_item_refs)
856 : : {
857 : 2198 : std::string trait_item_name = trait_item_ref.get_identifier ();
858 : 2198 : std::string impl_item_name
859 : 2198 : = implemented_trait_item->get_identifier ();
860 : 2198 : found = trait_item_name == impl_item_name;
861 : 2198 : if (found)
862 : : break;
863 : 2198 : }
864 : :
865 : 2262 : bool is_required_trait_item = !trait_item_ref.is_optional ();
866 : 2262 : if (!found && is_required_trait_item)
867 : 12 : missing_trait_items.emplace_back (trait_item_ref);
868 : : }
869 : :
870 : 1153 : if (!missing_trait_items.empty ())
871 : : {
872 : 8 : std::string missing_items_buf;
873 : 8 : rich_location r (line_table, impl_block.get_locus ());
874 : 20 : for (size_t i = 0; i < missing_trait_items.size (); i++)
875 : : {
876 : 12 : bool has_more = (i + 1) < missing_trait_items.size ();
877 : 12 : const TraitItemReference &missing_trait_item
878 : 12 : = missing_trait_items.at (i);
879 : 12 : missing_items_buf += missing_trait_item.get_identifier ()
880 : 36 : + (has_more ? ", " : "");
881 : 12 : r.add_range (missing_trait_item.get_locus ());
882 : : }
883 : :
884 : 8 : rust_error_at (r, ErrorCode::E0046,
885 : : "missing %s in implementation of trait %qs",
886 : : missing_items_buf.c_str (),
887 : 8 : trait_reference->get_name ().c_str ());
888 : 8 : }
889 : 1153 : }
890 : :
891 : 4914 : if (is_trait_impl_block)
892 : : {
893 : 3947 : trait_reference->clear_associated_types ();
894 : :
895 : 3947 : AssociatedImplTrait associated (trait_reference, specified_bound,
896 : 3947 : &impl_block, self, context);
897 : 3947 : context->insert_associated_trait_impl (
898 : 3947 : impl_block.get_mappings ().get_hirid (), std::move (associated));
899 : 3947 : context->insert_associated_impl_mapping (
900 : 3947 : trait_reference->get_mappings ().get_hirid (), self,
901 : 3947 : impl_block.get_mappings ().get_hirid ());
902 : 3947 : }
903 : 4914 : }
904 : :
905 : : TyTy::BaseType *
906 : 21315 : TypeCheckItem::resolve_impl_block_self (HIR::ImplBlock &impl_block)
907 : : {
908 : 21315 : return TypeCheckType::Resolve (impl_block.get_type ());
909 : : }
910 : :
911 : : } // namespace Resolver
912 : : } // namespace Rust
|