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 :
21 : namespace Rust {
22 : namespace Resolver {
23 :
24 : std::string
25 5930 : TraitItemReference::as_string () const
26 : {
27 23720 : return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
28 : }
29 :
30 : bool
31 165354 : TraitItemReference::is_error () const
32 : {
33 165354 : return type == ERROR;
34 : }
35 :
36 : bool
37 6345 : TraitItemReference::is_optional () const
38 : {
39 6345 : return optional_flag;
40 : }
41 :
42 : std::string
43 265685 : TraitItemReference::get_identifier () const
44 : {
45 265685 : return identifier;
46 : }
47 :
48 : TraitItemReference::TraitItemType
49 286111 : TraitItemReference::get_trait_item_type () const
50 : {
51 286111 : return type;
52 : }
53 :
54 : HIR::TraitItem *
55 22754 : TraitItemReference::get_hir_trait_item () const
56 : {
57 22754 : return hir_trait_item;
58 : }
59 :
60 : location_t
61 1953 : TraitItemReference::get_locus () const
62 : {
63 1953 : return locus;
64 : }
65 :
66 : const Analysis::NodeMapping
67 26044 : TraitItemReference::get_mappings () const
68 : {
69 26044 : return hir_trait_item->get_mappings ();
70 : }
71 :
72 : TyTy::BaseType *
73 46019 : TraitItemReference::get_tyty () const
74 : {
75 46019 : rust_assert (hir_trait_item != nullptr);
76 :
77 46019 : switch (type)
78 : {
79 31 : case CONST:
80 31 : return get_type_from_constant (
81 31 : static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
82 21251 : break;
83 :
84 21251 : case TYPE:
85 21251 : return get_type_from_typealias (
86 21251 : static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
87 :
88 24737 : case FN:
89 24737 : return get_type_from_fn (
90 24737 : static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
91 0 : break;
92 :
93 0 : default:
94 0 : return get_error ();
95 : }
96 :
97 : rust_unreachable ();
98 : return get_error ();
99 : }
100 :
101 : TyTy::ErrorType *
102 2 : TraitItemReference::get_error () const
103 : {
104 2 : return new TyTy::ErrorType (get_mappings ().get_hirid ());
105 : }
106 :
107 5477 : TraitReference::TraitReference (
108 : const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
109 : std::vector<TyTy::TypeBoundPredicate> super_traits,
110 5477 : std::vector<TyTy::SubstitutionParamMapping> substs)
111 5477 : : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
112 5477 : super_traits (super_traits)
113 : {
114 5477 : trait_substs.clear ();
115 5477 : trait_substs.reserve (substs.size ());
116 9798 : for (const auto &p : substs)
117 4321 : trait_substs.push_back (p.clone ());
118 5477 : }
119 :
120 0 : TraitReference::TraitReference (TraitReference const &other)
121 0 : : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
122 0 : super_traits (other.super_traits)
123 : {
124 0 : trait_substs.clear ();
125 0 : trait_substs.reserve (other.trait_substs.size ());
126 0 : for (const auto &p : other.trait_substs)
127 0 : trait_substs.push_back (p.clone ());
128 0 : }
129 :
130 : TraitReference &
131 0 : TraitReference::operator= (TraitReference const &other)
132 : {
133 0 : hir_trait_ref = other.hir_trait_ref;
134 0 : item_refs = other.item_refs;
135 0 : super_traits = other.super_traits;
136 :
137 0 : trait_substs.clear ();
138 0 : trait_substs.reserve (other.trait_substs.size ());
139 0 : for (const auto &p : other.trait_substs)
140 0 : trait_substs.push_back (p.clone ());
141 :
142 0 : return *this;
143 : }
144 :
145 : bool
146 500839 : TraitReference::is_error () const
147 : {
148 500839 : return hir_trait_ref == nullptr;
149 : }
150 :
151 : location_t
152 1 : TraitReference::get_locus () const
153 : {
154 1 : return hir_trait_ref->get_locus ();
155 : }
156 :
157 : std::string
158 61429 : TraitReference::get_name () const
159 : {
160 61429 : rust_assert (!is_error ());
161 122858 : return hir_trait_ref->get_name ().as_string ();
162 : }
163 :
164 : std::string
165 3271 : TraitReference::as_string () const
166 : {
167 3271 : if (is_error ())
168 0 : return "<trait-ref-error-node>";
169 :
170 3271 : std::string item_buf;
171 9201 : for (auto &item : item_refs)
172 : {
173 17790 : item_buf += item.as_string () + ", ";
174 : }
175 6542 : return "HIR Trait: " + get_name () + "->"
176 16355 : + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]";
177 3271 : }
178 :
179 : const HIR::Trait *
180 19640 : TraitReference::get_hir_trait_ref () const
181 : {
182 19640 : return hir_trait_ref;
183 : }
184 :
185 : const Analysis::NodeMapping &
186 849547 : TraitReference::get_mappings () const
187 : {
188 849547 : return hir_trait_ref->get_mappings ();
189 : }
190 :
191 : DefId
192 165 : TraitReference::get_defid () const
193 : {
194 165 : return get_mappings ().get_defid ();
195 : }
196 :
197 : bool
198 241 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
199 : TraitItemReference **ref)
200 : {
201 241 : return lookup_trait_item (item.trait_identifier (), ref);
202 : }
203 :
204 : bool
205 1837 : TraitReference::lookup_trait_item (const std::string &ident,
206 : TraitItemReference **ref)
207 : {
208 2204 : for (auto &item : item_refs)
209 : {
210 2204 : if (ident.compare (item.get_identifier ()) == 0)
211 : {
212 1837 : *ref = &item;
213 1837 : return true;
214 : }
215 : }
216 : return false;
217 : }
218 :
219 : bool
220 100 : TraitReference::lookup_trait_item_by_type (
221 : const std::string &ident, TraitItemReference::TraitItemType type,
222 : TraitItemReference **ref)
223 : {
224 100 : for (auto &item : item_refs)
225 : {
226 100 : if (item.get_trait_item_type () != type)
227 0 : continue;
228 :
229 100 : if (ident.compare (item.get_identifier ()) == 0)
230 : {
231 100 : *ref = &item;
232 100 : return true;
233 : }
234 : }
235 : return false;
236 : }
237 :
238 : bool
239 5350 : TraitReference::lookup_trait_item_by_type (
240 : const std::string &ident, TraitItemReference::TraitItemType type,
241 : const TraitItemReference **ref) const
242 : {
243 8544 : for (auto &item : item_refs)
244 : {
245 8541 : if (item.get_trait_item_type () != type)
246 1267 : continue;
247 :
248 7274 : if (ident.compare (item.get_identifier ()) == 0)
249 : {
250 5347 : *ref = &item;
251 5347 : return true;
252 : }
253 : }
254 : return false;
255 : }
256 :
257 : bool
258 0 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
259 : const TraitItemReference **ref) const
260 : {
261 0 : return lookup_trait_item (item.trait_identifier (), ref);
262 : }
263 :
264 : bool
265 24909 : TraitReference::lookup_trait_item (const std::string &ident,
266 : const TraitItemReference **ref,
267 : bool lookup_supers) const
268 : {
269 31031 : for (auto &item : item_refs)
270 : {
271 29465 : if (ident.compare (item.get_identifier ()) == 0)
272 : {
273 23343 : *ref = &item;
274 23343 : return true;
275 : }
276 : }
277 :
278 1566 : if (!lookup_supers)
279 : return false;
280 :
281 : // lookup super traits
282 85 : for (const auto &super_trait : super_traits)
283 : {
284 14 : bool found = super_trait.get ()->lookup_trait_item (ident, ref);
285 14 : if (found)
286 23357 : return true;
287 : }
288 :
289 : return false;
290 : }
291 :
292 : const TraitItemReference *
293 160007 : TraitReference::lookup_trait_item (const std::string &ident,
294 : TraitItemReference::TraitItemType type) const
295 : {
296 385173 : for (auto &item : item_refs)
297 : {
298 240730 : if (item.get_trait_item_type () != type)
299 26514 : continue;
300 :
301 214216 : if (ident.compare (item.get_identifier ()) == 0)
302 160007 : return &item;
303 : }
304 :
305 : // lookup super traits
306 197450 : for (const auto &super_trait : super_traits)
307 : {
308 67403 : const TraitItemReference *res
309 67403 : = super_trait.get ()->lookup_trait_item (ident, type);
310 67403 : if (!res->is_error ())
311 160007 : return res;
312 : }
313 :
314 130047 : return &TraitItemReference::error_node ();
315 : }
316 :
317 : size_t
318 4650 : TraitReference::size () const
319 : {
320 4650 : return item_refs.size ();
321 : }
322 :
323 : const std::vector<TraitItemReference> &
324 2001 : TraitReference::get_trait_items () const
325 : {
326 2001 : return item_refs;
327 : }
328 :
329 : void
330 1229 : TraitReference::get_trait_items_and_supers (
331 : std::vector<const TraitItemReference *> &result) const
332 : {
333 2548 : for (const auto &item : item_refs)
334 1319 : result.push_back (&item);
335 :
336 1600 : for (const auto &super_trait : super_traits)
337 371 : super_trait.get ()->get_trait_items_and_supers (result);
338 1229 : }
339 :
340 : void
341 3680 : TraitReference::on_resolved ()
342 : {
343 6990 : for (auto &item : item_refs)
344 : {
345 3310 : if (item.get_trait_item_type ()
346 : == TraitItemReference::TraitItemType::TYPE)
347 736 : item.on_resolved ();
348 : }
349 6990 : for (auto &item : item_refs)
350 : {
351 3310 : if (item.get_trait_item_type ()
352 : != TraitItemReference::TraitItemType::TYPE)
353 2574 : item.on_resolved ();
354 : }
355 3680 : }
356 :
357 : void
358 4651 : TraitReference::clear_associated_types () const
359 : {
360 12050 : for (const auto &item : item_refs)
361 : {
362 7399 : bool is_assoc_type = item.get_trait_item_type ()
363 7399 : == TraitItemReference::TraitItemType::TYPE;
364 7399 : if (is_assoc_type)
365 1177 : item.associated_type_reset (false);
366 : }
367 4651 : }
368 :
369 : void
370 3384 : TraitReference::clear_associated_type_projections () const
371 : {
372 8905 : for (const auto &item : item_refs)
373 : {
374 5521 : bool is_assoc_type = item.get_trait_item_type ()
375 5521 : == TraitItemReference::TraitItemType::TYPE;
376 5521 : if (is_assoc_type)
377 176 : item.associated_type_reset (true);
378 : }
379 3384 : }
380 :
381 : bool
382 412086 : TraitReference::is_equal (const TraitReference &other) const
383 : {
384 412086 : DefId this_id = get_mappings ().get_defid ();
385 412086 : DefId other_id = other.get_mappings ().get_defid ();
386 412086 : return this_id == other_id;
387 : }
388 :
389 : std::vector<TyTy::TypeBoundPredicate>
390 20224 : TraitReference::get_super_traits () const
391 : {
392 20224 : return super_traits;
393 : }
394 :
395 : bool
396 256 : TraitReference::is_object_safe (bool emit_error, location_t locus) const
397 : {
398 : // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
399 256 : std::vector<const TraitReference *> non_object_super_traits;
400 312 : for (auto &super_trait : super_traits)
401 : {
402 56 : if (!super_trait.get ()->is_object_safe (false, UNDEF_LOCATION))
403 1 : non_object_super_traits.push_back (super_trait.get ());
404 : }
405 :
406 256 : std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
407 527 : for (auto &item : get_trait_items ())
408 : {
409 271 : if (!item.is_object_safe ())
410 4 : non_object_safe_items.push_back (&item);
411 : }
412 :
413 256 : bool is_safe
414 256 : = non_object_super_traits.empty () && non_object_safe_items.empty ();
415 256 : if (emit_error && !is_safe)
416 : {
417 2 : rich_location r (line_table, locus);
418 3 : for (auto &item : non_object_super_traits)
419 1 : r.add_range (item->get_locus ());
420 4 : for (auto &item : non_object_safe_items)
421 2 : r.add_range (item->get_locus ());
422 :
423 2 : rust_error_at (r, "trait bound is not object safe");
424 2 : }
425 :
426 256 : return is_safe;
427 256 : }
428 :
429 : bool
430 0 : TraitReference::trait_has_generics () const
431 : {
432 0 : return !trait_substs.empty ();
433 : }
434 :
435 : std::vector<TyTy::SubstitutionParamMapping> &
436 8 : TraitReference::get_trait_substs ()
437 : {
438 8 : return trait_substs;
439 : }
440 :
441 : const std::vector<TyTy::SubstitutionParamMapping> &
442 40448 : TraitReference::get_trait_substs () const
443 : {
444 40448 : return trait_substs;
445 : }
446 :
447 : bool
448 233893 : TraitReference::satisfies_bound (const TraitReference &reference) const
449 : {
450 233893 : if (is_equal (reference))
451 : return true;
452 :
453 232476 : for (const auto &super_trait : super_traits)
454 : {
455 74368 : if (super_trait.get ()->satisfies_bound (reference))
456 75785 : return true;
457 : }
458 :
459 : return false;
460 : }
461 :
462 4651 : AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
463 : TyTy::TypeBoundPredicate predicate,
464 : HIR::ImplBlock *impl,
465 : TyTy::BaseType *self,
466 4651 : Resolver::TypeCheckContext *context)
467 4651 : : trait (trait), predicate (predicate), impl (impl), self (self),
468 4651 : context (context)
469 4651 : {}
470 :
471 : TyTy::TypeBoundPredicate &
472 20536 : AssociatedImplTrait::get_predicate ()
473 : {
474 20536 : return predicate;
475 : }
476 :
477 : HIR::ImplBlock *
478 4795 : AssociatedImplTrait::get_impl_block ()
479 : {
480 4795 : return impl;
481 : }
482 :
483 : TyTy::BaseType *
484 2242 : AssociatedImplTrait::get_self ()
485 : {
486 2242 : return self;
487 : }
488 :
489 : const TyTy::BaseType *
490 0 : AssociatedImplTrait::get_self () const
491 : {
492 0 : return self;
493 : }
494 :
495 : } // namespace Resolver
496 : } // namespace Rust
|