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 1297 : TraitItemReference::as_string () const
27 : {
28 5188 : return "(" + trait_item_type_as_string (type) + " " + identifier + " " + ")";
29 : }
30 :
31 : bool
32 166166 : TraitItemReference::is_error () const
33 : {
34 166166 : return type == ERROR;
35 : }
36 :
37 : bool
38 6396 : TraitItemReference::is_optional () const
39 : {
40 6396 : return optional_flag;
41 : }
42 :
43 : std::string
44 273879 : TraitItemReference::get_identifier () const
45 : {
46 273879 : return identifier;
47 : }
48 :
49 : TraitItemReference::TraitItemType
50 261271 : TraitItemReference::get_trait_item_type () const
51 : {
52 261271 : return type;
53 : }
54 :
55 : HIR::TraitItem *
56 23738 : TraitItemReference::get_hir_trait_item () const
57 : {
58 23738 : return hir_trait_item;
59 : }
60 :
61 : location_t
62 2016 : TraitItemReference::get_locus () const
63 : {
64 2016 : return locus;
65 : }
66 :
67 : const Analysis::NodeMapping
68 33560 : TraitItemReference::get_mappings () const
69 : {
70 33560 : return hir_trait_item->get_mappings ();
71 : }
72 :
73 : TyTy::BaseType *
74 43624 : TraitItemReference::get_tyty () const
75 : {
76 43624 : rust_assert (hir_trait_item != nullptr);
77 :
78 43624 : switch (type)
79 : {
80 31 : case CONST:
81 31 : return get_type_from_constant (
82 31 : static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
83 18639 : break;
84 :
85 18639 : case TYPE:
86 18639 : return get_type_from_typealias (
87 18639 : static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
88 :
89 24954 : case FN:
90 24954 : return get_type_from_fn (
91 24954 : static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
92 0 : break;
93 :
94 0 : default:
95 0 : return get_error ();
96 : }
97 :
98 : rust_unreachable ();
99 : return get_error ();
100 : }
101 :
102 : TyTy::ErrorType *
103 2 : TraitItemReference::get_error () const
104 : {
105 2 : return new TyTy::ErrorType (get_mappings ().get_hirid ());
106 : }
107 :
108 5913 : TraitReference::TraitReference (
109 : const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
110 : std::vector<TyTy::TypeBoundPredicate> super_traits,
111 5913 : std::vector<TyTy::SubstitutionParamMapping> substs)
112 5913 : : hir_trait_ref (hir_trait_ref), item_refs (item_refs),
113 5913 : super_traits (super_traits)
114 : {
115 5913 : trait_substs.clear ();
116 5913 : trait_substs.reserve (substs.size ());
117 10472 : for (const auto &p : substs)
118 4559 : trait_substs.push_back (p.clone ());
119 5913 : }
120 :
121 0 : TraitReference::TraitReference (TraitReference const &other)
122 0 : : hir_trait_ref (other.hir_trait_ref), item_refs (other.item_refs),
123 0 : super_traits (other.super_traits)
124 : {
125 0 : trait_substs.clear ();
126 0 : trait_substs.reserve (other.trait_substs.size ());
127 0 : for (const auto &p : other.trait_substs)
128 0 : trait_substs.push_back (p.clone ());
129 0 : }
130 :
131 : TraitReference &
132 0 : TraitReference::operator= (TraitReference const &other)
133 : {
134 0 : hir_trait_ref = other.hir_trait_ref;
135 0 : item_refs = other.item_refs;
136 0 : super_traits = other.super_traits;
137 :
138 0 : trait_substs.clear ();
139 0 : trait_substs.reserve (other.trait_substs.size ());
140 0 : for (const auto &p : other.trait_substs)
141 0 : trait_substs.push_back (p.clone ());
142 :
143 0 : return *this;
144 : }
145 :
146 : bool
147 567849 : TraitReference::is_error () const
148 : {
149 567849 : return hir_trait_ref == nullptr;
150 : }
151 :
152 : location_t
153 1 : TraitReference::get_locus () const
154 : {
155 1 : return hir_trait_ref->get_locus ();
156 : }
157 :
158 : std::string
159 62958 : TraitReference::get_name () const
160 : {
161 62958 : rust_assert (!is_error ());
162 125916 : return hir_trait_ref->get_name ().as_string ();
163 : }
164 :
165 : std::string
166 1184 : TraitReference::as_string () const
167 : {
168 1184 : if (is_error ())
169 0 : return "<trait-ref-error-node>";
170 :
171 1184 : std::string item_buf;
172 2481 : for (auto &item : item_refs)
173 : {
174 3891 : item_buf += item.as_string () + ", ";
175 : }
176 2368 : return "HIR Trait: " + get_name () + "->"
177 5920 : + hir_trait_ref->get_mappings ().as_string () + " [" + item_buf + "]";
178 1184 : }
179 :
180 : const HIR::Trait *
181 19842 : TraitReference::get_hir_trait_ref () const
182 : {
183 19842 : return hir_trait_ref;
184 : }
185 :
186 : const Analysis::NodeMapping &
187 1133176 : TraitReference::get_mappings () const
188 : {
189 1133176 : return hir_trait_ref->get_mappings ();
190 : }
191 :
192 : DefId
193 186 : TraitReference::get_defid () const
194 : {
195 186 : return get_mappings ().get_defid ();
196 : }
197 :
198 : bool
199 241 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
200 : TraitItemReference **ref)
201 : {
202 241 : return lookup_trait_item (item.trait_identifier (), ref);
203 : }
204 :
205 : bool
206 241 : TraitReference::lookup_trait_item (const std::string &ident,
207 : TraitItemReference **ref)
208 : {
209 542 : for (auto &item : item_refs)
210 : {
211 542 : if (ident.compare (item.get_identifier ()) == 0)
212 : {
213 241 : *ref = &item;
214 241 : return true;
215 : }
216 : }
217 : return false;
218 : }
219 :
220 : bool
221 0 : TraitReference::lookup_trait_item_by_type (
222 : const std::string &ident, TraitItemReference::TraitItemType type,
223 : TraitItemReference **ref)
224 : {
225 0 : for (auto &item : item_refs)
226 : {
227 0 : if (item.get_trait_item_type () != type)
228 0 : continue;
229 :
230 0 : if (ident.compare (item.get_identifier ()) == 0)
231 : {
232 0 : *ref = &item;
233 0 : return true;
234 : }
235 : }
236 : return false;
237 : }
238 :
239 : bool
240 6082 : TraitReference::lookup_trait_item_by_type (
241 : const std::string &ident, TraitItemReference::TraitItemType type,
242 : const TraitItemReference **ref) const
243 : {
244 9287 : for (auto &item : item_refs)
245 : {
246 9283 : if (item.get_trait_item_type () != type)
247 1276 : continue;
248 :
249 8007 : if (ident.compare (item.get_identifier ()) == 0)
250 : {
251 6078 : *ref = &item;
252 6078 : return true;
253 : }
254 : }
255 : return false;
256 : }
257 :
258 : bool
259 0 : TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
260 : const TraitItemReference **ref) const
261 : {
262 0 : return lookup_trait_item (item.trait_identifier (), ref);
263 : }
264 :
265 : bool
266 26564 : TraitReference::lookup_trait_item (const std::string &ident,
267 : const TraitItemReference **ref,
268 : bool lookup_supers) const
269 : {
270 32736 : for (auto &item : item_refs)
271 : {
272 31186 : if (ident.compare (item.get_identifier ()) == 0)
273 : {
274 25014 : *ref = &item;
275 25014 : return true;
276 : }
277 : }
278 :
279 1550 : if (!lookup_supers)
280 : return false;
281 :
282 : // lookup super traits
283 85 : for (const auto &super_trait : super_traits)
284 : {
285 14 : bool found = super_trait.get ()->lookup_trait_item (ident, ref);
286 14 : if (found)
287 25028 : return true;
288 : }
289 :
290 : return false;
291 : }
292 :
293 : const TraitItemReference *
294 160088 : TraitReference::lookup_trait_item (const std::string &ident,
295 : TraitItemReference::TraitItemType type) const
296 : {
297 385304 : for (auto &item : item_refs)
298 : {
299 240786 : if (item.get_trait_item_type () != type)
300 26517 : continue;
301 :
302 214269 : if (ident.compare (item.get_identifier ()) == 0)
303 160088 : return &item;
304 : }
305 :
306 : // lookup super traits
307 197525 : for (const auto &super_trait : super_traits)
308 : {
309 67412 : const TraitItemReference *res
310 67412 : = super_trait.get ()->lookup_trait_item (ident, type);
311 67412 : if (!res->is_error ())
312 160088 : return res;
313 : }
314 :
315 130113 : return &TraitItemReference::error_node ();
316 : }
317 :
318 : size_t
319 4718 : TraitReference::size () const
320 : {
321 4718 : return item_refs.size ();
322 : }
323 :
324 : const std::vector<TraitItemReference> &
325 8765 : TraitReference::get_trait_items () const
326 : {
327 8765 : return item_refs;
328 : }
329 :
330 : void
331 1451 : TraitReference::get_trait_items_and_supers (
332 : std::vector<const TraitItemReference *> &result) const
333 : {
334 2971 : for (const auto &item : item_refs)
335 1520 : result.push_back (&item);
336 :
337 1822 : for (const auto &super_trait : super_traits)
338 371 : super_trait.get ()->get_trait_items_and_supers (result);
339 1451 : }
340 :
341 : void
342 3915 : TraitReference::on_resolved ()
343 : {
344 7270 : for (auto &item : item_refs)
345 : {
346 3355 : if (item.get_trait_item_type ()
347 : == TraitItemReference::TraitItemType::TYPE)
348 739 : item.on_resolved (this);
349 : }
350 7270 : for (auto &item : item_refs)
351 : {
352 3355 : if (item.get_trait_item_type ()
353 : != TraitItemReference::TraitItemType::TYPE)
354 2616 : item.on_resolved (this);
355 : }
356 3915 : }
357 :
358 : bool
359 553388 : TraitReference::is_equal (const TraitReference &other) const
360 : {
361 553388 : DefId this_id = get_mappings ().get_defid ();
362 553388 : DefId other_id = other.get_mappings ().get_defid ();
363 553388 : return this_id == other_id;
364 : }
365 :
366 : std::vector<TyTy::TypeBoundPredicate>
367 21160 : TraitReference::get_super_traits () const
368 : {
369 21160 : return super_traits;
370 : }
371 :
372 : bool
373 305 : TraitReference::is_object_safe (bool emit_error, location_t locus) const
374 : {
375 : // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
376 305 : std::vector<const TraitReference *> non_object_super_traits;
377 361 : for (auto &super_trait : super_traits)
378 : {
379 56 : if (!super_trait.get ()->is_object_safe (false, UNDEF_LOCATION))
380 1 : non_object_super_traits.push_back (super_trait.get ());
381 : }
382 :
383 305 : std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
384 618 : for (auto &item : get_trait_items ())
385 : {
386 313 : if (!item.is_object_safe ())
387 4 : non_object_safe_items.push_back (&item);
388 : }
389 :
390 305 : bool is_safe
391 305 : = non_object_super_traits.empty () && non_object_safe_items.empty ();
392 305 : if (emit_error && !is_safe)
393 : {
394 2 : rich_location r (line_table, locus);
395 3 : for (auto &item : non_object_super_traits)
396 1 : r.add_range (item->get_locus ());
397 4 : for (auto &item : non_object_safe_items)
398 2 : r.add_range (item->get_locus ());
399 :
400 2 : rust_error_at (r, "trait bound is not object safe");
401 2 : }
402 :
403 305 : return is_safe;
404 305 : }
405 :
406 : bool
407 0 : TraitReference::trait_has_generics () const
408 : {
409 0 : return !trait_substs.empty ();
410 : }
411 :
412 : std::vector<TyTy::SubstitutionParamMapping> &
413 8 : TraitReference::get_trait_substs ()
414 : {
415 8 : return trait_substs;
416 : }
417 :
418 : const std::vector<TyTy::SubstitutionParamMapping> &
419 50615 : TraitReference::get_trait_substs () const
420 : {
421 50615 : return trait_substs;
422 : }
423 :
424 : bool
425 297499 : TraitReference::satisfies_bound (const TraitReference &reference) const
426 : {
427 297499 : if (is_equal (reference))
428 : return true;
429 :
430 302269 : for (const auto &super_trait : super_traits)
431 : {
432 98623 : if (super_trait.get ()->satisfies_bound (reference))
433 93853 : return true;
434 : }
435 :
436 : return false;
437 : }
438 :
439 4719 : AssociatedImplTrait::AssociatedImplTrait (TraitReference *trait,
440 : TyTy::TypeBoundPredicate predicate,
441 : HIR::ImplBlock *impl,
442 : TyTy::BaseType *self,
443 4719 : ImplTraitContextFrame frame)
444 4719 : : trait (trait), predicate (predicate), impl (impl), self (self),
445 4719 : context (TypeCheckContext::get ()), frame (frame)
446 4719 : {}
447 :
448 : TyTy::TypeBoundPredicate &
449 17665 : AssociatedImplTrait::get_predicate ()
450 : {
451 17665 : return predicate;
452 : }
453 :
454 : HIR::ImplBlock *
455 54 : AssociatedImplTrait::get_impl_block ()
456 : {
457 54 : return impl;
458 : }
459 :
460 : TyTy::BaseType *
461 0 : AssociatedImplTrait::get_self ()
462 : {
463 0 : return self;
464 : }
465 :
466 : const TyTy::BaseType *
467 0 : AssociatedImplTrait::get_self () const
468 : {
469 0 : return self;
470 : }
471 :
472 : ImplTraitContextFrame
473 6128 : AssociatedImplTrait::get_frame () const
474 : {
475 6128 : return frame;
476 : }
477 :
478 : } // namespace Resolver
479 : } // namespace Rust
|