1 // Copyright (C) 2021-2023 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
19 #ifndef RUST_HIR_TRAIT_REF_H
20 #define RUST_HIR_TRAIT_REF_H
22 #include "rust-hir-full.h"
23 #include "rust-tyty-visitor.h"
24 #include "rust-hir-type-check-util.h"
29 // Data Objects for the associated trait items in a structure we can work with
30 // https://doc.rust-lang.org/edition-guide/rust-2018/trait-system/associated-constants.html
31 class TypeCheckContext
;
32 class TraitItemReference
43 TraitItemReference (std::string identifier
, bool optional
, TraitItemType type
,
44 HIR::TraitItem
*hir_trait_item
, TyTy::BaseType
*self
,
45 std::vector
<TyTy::SubstitutionParamMapping
> substitutions
,
48 TraitItemReference (TraitItemReference
const &other
);
50 TraitItemReference
&operator= (TraitItemReference
const &other
);
52 static TraitItemReference
error ()
54 return TraitItemReference ("", false, ERROR
, nullptr, nullptr, {},
58 static TraitItemReference
&error_node ()
60 static TraitItemReference error
= TraitItemReference::error ();
64 bool is_error () const { return type
== ERROR
; }
66 std::string
as_string () const
68 return "(" + trait_item_type_as_string (type
) + " " + identifier
+ " "
72 static std::string
trait_item_type_as_string (TraitItemType ty
)
88 bool is_optional () const { return optional_flag
; }
90 std::string
get_identifier () const { return identifier
; }
92 TraitItemType
get_trait_item_type () const { return type
; }
94 HIR::TraitItem
*get_hir_trait_item () const { return hir_trait_item
; }
96 Location
get_locus () const { return locus
; }
98 const Analysis::NodeMapping
get_mappings () const
100 return hir_trait_item
->get_mappings ();
103 TyTy::BaseType
*get_tyty () const
105 rust_assert (hir_trait_item
!= nullptr);
110 return get_type_from_constant (
111 static_cast</*const*/ HIR::TraitItemConst
&> (*hir_trait_item
));
115 return get_type_from_typealias (
116 static_cast</*const*/ HIR::TraitItemType
&> (*hir_trait_item
));
119 return get_type_from_fn (
120 static_cast</*const*/ HIR::TraitItemFunc
&> (*hir_trait_item
));
131 Analysis::NodeMapping
get_parent_trait_mappings () const;
133 // this is called when the trait is completed resolution and gives the items a
134 // chance to run their specific type resolution passes. If we call their
135 // resolution on construction it can lead to a case where the trait being
136 // resolved recursively trying to resolve the trait itself infinitely since
137 // the trait will not be stored in its own map yet
140 void associated_type_set (TyTy::BaseType
*ty
) const;
142 void associated_type_reset () const;
144 bool is_object_safe () const;
147 TyTy::ErrorType
*get_error () const
149 return new TyTy::ErrorType (get_mappings ().get_hirid ());
152 TyTy::BaseType
*get_type_from_typealias (/*const*/
153 HIR::TraitItemType
&type
) const;
156 get_type_from_constant (/*const*/ HIR::TraitItemConst
&constant
) const;
158 TyTy::BaseType
*get_type_from_fn (/*const*/ HIR::TraitItemFunc
&fn
) const;
160 bool is_item_resolved () const;
161 void resolve_item (HIR::TraitItemType
&type
);
162 void resolve_item (HIR::TraitItemConst
&constant
);
163 void resolve_item (HIR::TraitItemFunc
&func
);
165 std::string identifier
;
168 HIR::TraitItem
*hir_trait_item
;
169 std::vector
<TyTy::SubstitutionParamMapping
> inherited_substitutions
;
173 *self
; // this is the implict Self TypeParam required for methods
174 Resolver::TypeCheckContext
*context
;
177 // this wraps up the HIR::Trait so we can do analysis on it
182 TraitReference (const HIR::Trait
*hir_trait_ref
,
183 std::vector
<TraitItemReference
> item_refs
,
184 std::vector
<const TraitReference
*> super_traits
,
185 std::vector
<TyTy::SubstitutionParamMapping
> substs
)
186 : hir_trait_ref (hir_trait_ref
), item_refs (item_refs
),
187 super_traits (super_traits
)
189 trait_substs
.clear ();
190 trait_substs
.reserve (substs
.size ());
191 for (const auto &p
: substs
)
192 trait_substs
.push_back (p
.clone ());
195 TraitReference (TraitReference
const &other
)
196 : hir_trait_ref (other
.hir_trait_ref
), item_refs (other
.item_refs
),
197 super_traits (other
.super_traits
)
199 trait_substs
.clear ();
200 trait_substs
.reserve (other
.trait_substs
.size ());
201 for (const auto &p
: other
.trait_substs
)
202 trait_substs
.push_back (p
.clone ());
205 TraitReference
&operator= (TraitReference
const &other
)
207 hir_trait_ref
= other
.hir_trait_ref
;
208 item_refs
= other
.item_refs
;
209 super_traits
= other
.super_traits
;
211 trait_substs
.clear ();
212 trait_substs
.reserve (other
.trait_substs
.size ());
213 for (const auto &p
: other
.trait_substs
)
214 trait_substs
.push_back (p
.clone ());
219 TraitReference (TraitReference
&&other
) = default;
220 TraitReference
&operator= (TraitReference
&&other
) = default;
222 static TraitReference
error ()
224 return TraitReference (nullptr, {}, {}, {});
227 bool is_error () const { return hir_trait_ref
== nullptr; }
229 static TraitReference
&error_node ()
231 static TraitReference trait_error_node
= TraitReference::error ();
232 return trait_error_node
;
235 Location
get_locus () const { return hir_trait_ref
->get_locus (); }
237 std::string
get_name () const
239 rust_assert (!is_error ());
240 return hir_trait_ref
->get_name ();
243 std::string
as_string () const
246 return "<trait-ref-error-node>";
248 std::string item_buf
;
249 for (auto &item
: item_refs
)
251 item_buf
+= item
.as_string () + ", ";
253 return "HIR Trait: " + get_name () + "->"
254 + hir_trait_ref
->get_mappings ().as_string () + " [" + item_buf
258 const HIR::Trait
*get_hir_trait_ref () const { return hir_trait_ref
; }
260 const Analysis::NodeMapping
&get_mappings () const
262 return hir_trait_ref
->get_mappings ();
265 DefId
get_defid () const { return get_mappings ().get_defid (); }
267 bool lookup_hir_trait_item (const HIR::TraitItem
&item
,
268 TraitItemReference
**ref
)
270 return lookup_trait_item (item
.trait_identifier (), ref
);
273 bool lookup_trait_item (const std::string
&ident
, TraitItemReference
**ref
)
275 for (auto &item
: item_refs
)
277 if (ident
.compare (item
.get_identifier ()) == 0)
286 bool lookup_trait_item_by_type (const std::string
&ident
,
287 TraitItemReference::TraitItemType type
,
288 TraitItemReference
**ref
)
290 for (auto &item
: item_refs
)
292 if (item
.get_trait_item_type () != type
)
295 if (ident
.compare (item
.get_identifier ()) == 0)
304 bool lookup_trait_item_by_type (const std::string
&ident
,
305 TraitItemReference::TraitItemType type
,
306 const TraitItemReference
**ref
) const
308 for (auto &item
: item_refs
)
310 if (item
.get_trait_item_type () != type
)
313 if (ident
.compare (item
.get_identifier ()) == 0)
322 bool lookup_hir_trait_item (const HIR::TraitItem
&item
,
323 const TraitItemReference
**ref
) const
325 return lookup_trait_item (item
.trait_identifier (), ref
);
328 bool lookup_trait_item (const std::string
&ident
,
329 const TraitItemReference
**ref
) const
331 for (auto &item
: item_refs
)
333 if (ident
.compare (item
.get_identifier ()) == 0)
340 // lookup super traits
341 for (const auto &super_trait
: super_traits
)
343 bool found
= super_trait
->lookup_trait_item (ident
, ref
);
351 const TraitItemReference
*
352 lookup_trait_item (const std::string
&ident
,
353 TraitItemReference::TraitItemType type
) const
355 for (auto &item
: item_refs
)
357 if (item
.get_trait_item_type () != type
)
360 if (ident
.compare (item
.get_identifier ()) == 0)
364 // lookup super traits
365 for (const auto &super_trait
: super_traits
)
367 const TraitItemReference
*res
368 = super_trait
->lookup_trait_item (ident
, type
);
369 if (!res
->is_error ())
373 return &TraitItemReference::error_node ();
376 size_t size () const { return item_refs
.size (); }
378 const std::vector
<TraitItemReference
> &get_trait_items () const
383 void get_trait_items_and_supers (
384 std::vector
<const TraitItemReference
*> &result
) const
386 for (const auto &item
: item_refs
)
387 result
.push_back (&item
);
389 for (const auto &super_trait
: super_traits
)
390 super_trait
->get_trait_items_and_supers (result
);
395 for (auto &item
: item_refs
)
401 void clear_associated_types ()
403 for (auto &item
: item_refs
)
405 bool is_assoc_type
= item
.get_trait_item_type ()
406 == TraitItemReference::TraitItemType::TYPE
;
408 item
.associated_type_reset ();
412 bool is_equal (const TraitReference
&other
) const
414 DefId this_id
= get_mappings ().get_defid ();
415 DefId other_id
= other
.get_mappings ().get_defid ();
416 return this_id
== other_id
;
419 const std::vector
<const TraitReference
*> get_super_traits () const
424 bool is_object_safe (bool emit_error
, Location locus
) const
426 // https: // doc.rust-lang.org/reference/items/traits.html#object-safety
427 std::vector
<const TraitReference
*> non_object_super_traits
;
428 for (auto &item
: super_traits
)
430 if (!item
->is_object_safe (false, Location ()))
431 non_object_super_traits
.push_back (item
);
434 std::vector
<const Resolver::TraitItemReference
*> non_object_safe_items
;
435 for (auto &item
: get_trait_items ())
437 if (!item
.is_object_safe ())
438 non_object_safe_items
.push_back (&item
);
442 = non_object_super_traits
.empty () && non_object_safe_items
.empty ();
443 if (emit_error
&& !is_safe
)
445 RichLocation
r (locus
);
446 for (auto &item
: non_object_super_traits
)
447 r
.add_range (item
->get_locus ());
448 for (auto &item
: non_object_safe_items
)
449 r
.add_range (item
->get_locus ());
451 rust_error_at (r
, "trait bound is not object safe");
457 bool trait_has_generics () const { return !trait_substs
.empty (); }
459 std::vector
<TyTy::SubstitutionParamMapping
> get_trait_substs () const
464 bool satisfies_bound (const TraitReference
&reference
) const
466 if (is_equal (reference
))
469 for (const auto &super_trait
: super_traits
)
471 if (super_trait
->satisfies_bound (reference
))
479 const HIR::Trait
*hir_trait_ref
;
480 std::vector
<TraitItemReference
> item_refs
;
481 std::vector
<const TraitReference
*> super_traits
;
482 std::vector
<TyTy::SubstitutionParamMapping
> trait_substs
;
485 class AssociatedImplTrait
488 AssociatedImplTrait (TraitReference
*trait
, HIR::ImplBlock
*impl
,
489 TyTy::BaseType
*self
,
490 Resolver::TypeCheckContext
*context
)
491 : trait (trait
), impl (impl
), self (self
), context (context
)
494 TraitReference
*get_trait () { return trait
; }
496 HIR::ImplBlock
*get_impl_block () { return impl
; }
498 TyTy::BaseType
*get_self () { return self
; }
499 const TyTy::BaseType
*get_self () const { return self
; }
502 setup_associated_types (const TyTy::BaseType
*self
,
503 const TyTy::TypeBoundPredicate
&bound
);
505 void reset_associated_types ();
508 TraitReference
*trait
;
509 HIR::ImplBlock
*impl
;
510 TyTy::BaseType
*self
;
511 Resolver::TypeCheckContext
*context
;
514 } // namespace Resolver
517 #endif // RUST_HIR_TRAIT_REF_H