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-trait-reference.h"
20 : #include "rust-hir-type-check.h"
21 :
22 : namespace Rust {
23 : namespace Resolver {
24 :
25 : std::string
26 299 : TraitItemReference::as_string () const
27 : {
28 1196 : return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
29 : }
30 :
31 : bool
32 9034 : TraitItemReference::is_error () const
33 : {
34 9034 : return type == ERROR;
35 : }
36 :
37 : bool
38 10335 : TraitItemReference::is_optional () const
39 : {
40 10335 : return optional_flag;
41 : }
42 :
43 : std::string
44 53862 : TraitItemReference::get_identifier () const
45 : {
46 53862 : return identifier;
47 : }
48 :
49 : TraitItemReference::TraitItemType
50 27637 : TraitItemReference::get_trait_item_type () const
51 : {
52 27637 : return type;
53 : }
54 :
55 : HIR::TraitItem *
56 10517 : TraitItemReference::get_hir_trait_item () const
57 : {
58 10517 : return hir_trait_item;
59 : }
60 :
61 : location_t
62 2123 : TraitItemReference::get_locus () const
63 : {
64 2123 : return locus;
65 : }
66 :
67 : const Analysis::NodeMapping
68 34240 : TraitItemReference::get_mappings () const
69 : {
70 34240 : return hir_trait_item->get_mappings ();
71 : }
72 :
73 : TyTy::BaseType *
74 21860 : TraitItemReference::get_tyty () const
75 : {
76 21860 : rust_assert (hir_trait_item != nullptr);
77 :
78 21860 : TyTy::BaseType *resolved = nullptr;
79 21860 : if (type == FN
80 21860 : && context->lookup_type (get_mappings ().get_hirid (), &resolved))
81 10643 : return resolved;
82 :
83 11217 : switch (type)
84 : {
85 32 : case CONST:
86 32 : return get_type_from_constant (
87 32 : static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
88 8437 : break;
89 :
90 8437 : case TYPE:
91 8437 : return get_type_from_typealias (
92 8437 : static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
93 :
94 2748 : case FN:
95 2748 : return get_type_from_fn (
96 2748 : static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
97 0 : break;
98 :
99 0 : default:
100 0 : return get_error ();
101 : }
102 :
103 : rust_unreachable ();
104 : return get_error ();
105 : }
106 :
107 : TyTy::ErrorType *
108 2 : TraitItemReference::get_error () const
109 : {
110 2 : return new TyTy::ErrorType (get_mappings ().get_hirid ());
111 : }
112 :
113 6254 : TraitReference::TraitReference (
114 : const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
115 : std::vector<TyTy::TypeBoundPredicate> super_traits,
116 : std::vector<TyTy::SubstitutionParamMapping> substs)
117 6254 : : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
118 6254 : super_traits (super_traits)
119 : {
120 6254 : trait_substs.clear ();
121 6254 : trait_substs.reserve (substs.size ());
122 11134 : for (const auto &p : substs)
123 4880 : trait_substs.push_back (p.clone ());
124 6254 : }
125 :
126 0 : TraitReference::TraitReference (TraitReference const &other)
127 0 : : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
128 0 : super_traits (other.super_traits)
129 : {
130 0 : trait_substs.clear ();
131 0 : trait_substs.reserve (other.trait_substs.size ());
132 0 : for (const auto &p : other.trait_substs)
133 0 : trait_substs.push_back (p.clone ());
134 0 : }
135 :
136 : TraitReference &
137 0 : TraitReference::operator= (TraitReference const &other)
138 : {
139 0 : hir_trait_ref = other.hir_trait_ref;
140 0 : item_refs = other.item_refs;
141 0 : super_traits = other.super_traits;
142 :
143 0 : trait_substs.clear ();
144 0 : trait_substs.reserve (other.trait_substs.size ());
145 0 : for (const auto &p : other.trait_substs)
146 0 : trait_substs.push_back (p.clone ());
147 :
148 0 : return *this;
149 : }
150 :
151 : bool
152 81534 : TraitReference::is_error () const
153 : {
154 81534 : return hir_trait_ref == nullptr;
155 : }
156 :
157 : location_t
158 952 : TraitReference::get_locus () const
159 : {
160 952 : return hir_trait_ref->get_locus ();
161 : }
162 :
163 : std::string
164 8587 : TraitReference::get_name () const
165 : {
166 8587 : rust_assert (!is_error ());
167 17174 : return hir_trait_ref->get_name ().as_string ();
168 : }
169 :
170 : std::string
171 235 : TraitReference::as_string () const
172 : {
173 235 : if (is_error ())
174 0 : return "<trait-ref-error-node>";
175 :
176 235 : std::string item_buf;
177 534 : for (auto &item : item_refs)
178 : {
179 897 : item_buf += item.as_string () + ", ";
180 : }
181 470 : return "HIR Trait: " + get_name () + "->"
182 1175 : + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]";
183 235 : }
184 :
185 : const HIR::Trait *
186 75264 : TraitReference::get_hir_trait_ref () const
187 : {
188 75264 : return hir_trait_ref;
189 : }
190 :
191 : const Analysis::NodeMapping &
192 379423 : TraitReference::get_mappings () const
193 : {
194 379423 : return hir_trait_ref->get_mappings ();
195 : }
196 :
197 : DefId
198 402 : TraitReference::get_defid () const
199 : {
200 402 : return get_mappings ().get_defid ();
201 : }
202 :
203 : bool
204 290 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
205 : TraitItemReference **ref)
206 : {
207 290 : return lookup_trait_item (item.trait_identifier (), ref);
208 : }
209 :
210 : bool
211 290 : TraitReference::lookup_trait_item (const std::string &ident,
212 : TraitItemReference **ref)
213 : {
214 667 : for (auto &item : item_refs)
215 : {
216 667 : if (ident.compare (item.get_identifier ()) == 0)
217 : {
218 290 : *ref = &item;
219 290 : return true;
220 : }
221 : }
222 : return false;
223 : }
224 :
225 : bool
226 0 : TraitReference::lookup_trait_item_by_type (
227 : const std::string &ident, TraitItemReference::TraitItemType type,
228 : TraitItemReference **ref)
229 : {
230 0 : for (auto &item : item_refs)
231 : {
232 0 : if (item.get_trait_item_type () != type)
233 0 : continue;
234 :
235 0 : if (ident.compare (item.get_identifier ()) == 0)
236 : {
237 0 : *ref = &item;
238 0 : return true;
239 : }
240 : }
241 : return false;
242 : }
243 :
244 : bool
245 6920 : TraitReference::lookup_trait_item_by_type (
246 : const std::string &ident, TraitItemReference::TraitItemType type,
247 : const TraitItemReference **ref) const
248 : {
249 10487 : for (auto &item : item_refs)
250 : {
251 10483 : if (item.get_trait_item_type () != type)
252 1502 : continue;
253 :
254 8981 : if (ident.compare (item.get_identifier ()) == 0)
255 : {
256 6916 : *ref = &item;
257 6916 : return true;
258 : }
259 : }
260 : return false;
261 : }
262 :
263 : bool
264 0 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
265 : const TraitItemReference **ref) const
266 : {
267 0 : return lookup_trait_item (item.trait_identifier (), ref);
268 : }
269 :
270 : bool
271 17092 : TraitReference::lookup_trait_item (const std::string &ident,
272 : const TraitItemReference **ref,
273 : bool lookup_supers) const
274 : {
275 23783 : for (auto &item : item_refs)
276 : {
277 22066 : if (ident.compare (item.get_identifier ()) == 0)
278 : {
279 15375 : *ref = &item;
280 15375 : return true;
281 : }
282 : }
283 :
284 1717 : if (!lookup_supers)
285 : return false;
286 :
287 : // lookup super traits
288 86 : for (const auto &super_trait : super_traits)
289 : {
290 14 : bool found = super_trait.get ()->lookup_trait_item (ident, ref);
291 14 : if (found)
292 17092 : return true;
293 : }
294 :
295 : return false;
296 : }
297 :
298 : const TraitItemReference *
299 2118 : TraitReference::lookup_trait_item (const std::string &ident,
300 : TraitItemReference::TraitItemType type) const
301 : {
302 5831 : for (auto &item : item_refs)
303 : {
304 5159 : if (item.get_trait_item_type () != type)
305 121 : continue;
306 :
307 5038 : if (ident.compare (item.get_identifier ()) == 0)
308 2118 : return &item;
309 : }
310 :
311 : // lookup super traits
312 1008 : for (const auto &super_trait : super_traits)
313 : {
314 336 : const TraitItemReference *res
315 336 : = super_trait.get ()->lookup_trait_item (ident, type);
316 336 : if (!res->is_error ())
317 2118 : return res;
318 : }
319 :
320 672 : return &TraitItemReference::error_node ();
321 : }
322 :
323 : size_t
324 5334 : TraitReference::size () const
325 : {
326 5334 : return item_refs.size ();
327 : }
328 :
329 : const std::vector<TraitItemReference> &
330 4877 : TraitReference::get_trait_items () const
331 : {
332 4877 : return item_refs;
333 : }
334 :
335 : void
336 1502 : TraitReference::get_trait_items_and_supers (
337 : std::vector<const TraitItemReference *> &result) const
338 : {
339 3073 : for (const auto &item : item_refs)
340 1571 : result.push_back (&item);
341 :
342 1873 : for (const auto &super_trait : super_traits)
343 371 : super_trait.get ()->get_trait_items_and_supers (result);
344 1502 : }
345 :
346 : void
347 4167 : TraitReference::on_resolved ()
348 : {
349 7769 : for (auto &item : item_refs)
350 : {
351 3602 : if (item.get_trait_item_type ()
352 : == TraitItemReference::TraitItemType::TYPE)
353 814 : item.on_resolved (this);
354 : }
355 7769 : for (auto &item : item_refs)
356 : {
357 3602 : if (item.get_trait_item_type ()
358 : != TraitItemReference::TraitItemType::TYPE)
359 2788 : item.on_resolved (this);
360 : }
361 4167 : }
362 :
363 : void
364 4148 : TraitReference::resolve_default_function_bodies ()
365 : {
366 7739 : for (auto &item : item_refs)
367 3591 : item.resolve_default_function_body (this);
368 4148 : }
369 :
370 : bool
371 166463 : TraitReference::is_equal (const TraitReference &other) const
372 : {
373 166463 : DefId this_id = get_mappings ().get_defid ();
374 166463 : DefId other_id = other.get_mappings ().get_defid ();
375 166463 : return this_id == other_id;
376 : }
377 :
378 : std::vector<TyTy::TypeBoundPredicate>
379 38860 : TraitReference::get_super_traits () const
380 : {
381 38860 : return super_traits;
382 : }
383 :
384 : bool
385 327 : TraitReference::is_object_safe (bool emit_error, location_t locus) const
386 : {
387 : // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
388 327 : std::vector<const TraitReference *> non_object_super_traits;
389 383 : for (auto &super_trait : super_traits)
390 : {
391 56 : if (!super_trait.get ()->is_object_safe (false, UNDEF_LOCATION))
392 1 : non_object_super_traits.push_back (super_trait.get ());
393 : }
394 :
395 327 : std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
396 663 : for (auto &item : get_trait_items ())
397 : {
398 336 : if (!item.is_object_safe ())
399 4 : non_object_safe_items.push_back (&item);
400 : }
401 :
402 327 : bool is_safe
403 327 : = non_object_super_traits.empty () && non_object_safe_items.empty ();
404 327 : if (emit_error && !is_safe)
405 : {
406 2 : rich_location r (line_table, locus);
407 3 : for (auto &item : non_object_super_traits)
408 1 : r.add_range (item->get_locus ());
409 4 : for (auto &item : non_object_safe_items)
410 2 : r.add_range (item->get_locus ());
411 :
412 2 : rust_error_at (r, "trait bound is not object safe");
413 2 : }
414 :
415 327 : return is_safe;
416 327 : }
417 :
418 : bool
419 0 : TraitReference::trait_has_generics () const
420 : {
421 0 : return !trait_substs.empty ();
422 : }
423 :
424 : std::vector<TyTy::SubstitutionParamMapping> &
425 0 : TraitReference::get_trait_substs ()
426 : {
427 0 : return trait_substs;
428 : }
429 :
430 : const std::vector<TyTy::SubstitutionParamMapping> &
431 86946 : TraitReference::get_trait_substs () const
432 : {
433 86946 : return trait_substs;
434 : }
435 :
436 : bool
437 80785 : TraitReference::satisfies_bound (const TraitReference &reference) const
438 : {
439 80785 : if (is_equal (reference))
440 : return true;
441 :
442 12598 : for (const auto &super_trait : super_traits)
443 : {
444 1709 : if (super_trait.get ()->satisfies_bound (reference))
445 80785 : return true;
446 : }
447 :
448 : return false;
449 : }
450 :
451 5335 : AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
452 : TyTy::TypeBoundPredicate predicate,
453 : HIR::ImplBlock *impl,
454 : TyTy::BaseType *self,
455 : ImplTraitContextFrame frame)
456 5335 : : trait (trait), predicate (predicate), impl (impl), self (self),
457 5335 : context (TypeCheckContext::get ()), frame (frame)
458 5335 : {}
459 :
460 : TyTy::TypeBoundPredicate &
461 2598 : AssociatedImplTrait::get_predicate ()
462 : {
463 2598 : return predicate;
464 : }
465 :
466 : HIR::ImplBlock *
467 53 : AssociatedImplTrait::get_impl_block ()
468 : {
469 53 : return impl;
470 : }
471 :
472 : TyTy::BaseType *
473 0 : AssociatedImplTrait::get_self ()
474 : {
475 0 : return self;
476 : }
477 :
478 : const TyTy::BaseType *
479 0 : AssociatedImplTrait::get_self () const
480 : {
481 0 : return self;
482 : }
483 :
484 : ImplTraitContextFrame
485 6753 : AssociatedImplTrait::get_frame () const
486 : {
487 6753 : return frame;
488 : }
489 :
490 : } // namespace Resolver
491 : } // namespace Rust
|