gccrs: Fix higher ranked trait bounds computation of self
[official-gcc.git] / gcc / rust / typecheck / rust-hir-trait-reference.h
blobadb63b468d1c7df41ef55728e6bf1e3188e379e4
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
8 // version.
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.
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"
26 namespace Rust {
27 namespace Resolver {
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
34 public:
35 enum TraitItemType
37 FN,
38 CONST,
39 TYPE,
40 ERROR
43 TraitItemReference (std::string identifier, bool optional, TraitItemType type,
44 HIR::TraitItem *hir_trait_item, TyTy::BaseType *self,
45 std::vector<TyTy::SubstitutionParamMapping> substitutions,
46 Location locus);
48 TraitItemReference (TraitItemReference const &other);
50 TraitItemReference &operator= (TraitItemReference const &other);
52 static TraitItemReference error ()
54 return TraitItemReference ("", false, ERROR, nullptr, nullptr, {},
55 Location ());
58 static TraitItemReference &error_node ()
60 static TraitItemReference error = TraitItemReference::error ();
61 return error;
64 bool is_error () const { return type == ERROR; }
66 std::string as_string () const
68 return "(" + trait_item_type_as_string (type) + " " + identifier + " "
69 + ")";
72 static std::string trait_item_type_as_string (TraitItemType ty)
74 switch (ty)
76 case FN:
77 return "FN";
78 case CONST:
79 return "CONST";
80 case TYPE:
81 return "TYPE";
82 case ERROR:
83 return "ERROR";
85 return "ERROR";
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);
107 switch (type)
109 case CONST:
110 return get_type_from_constant (
111 static_cast</*const*/ HIR::TraitItemConst &> (*hir_trait_item));
112 break;
114 case TYPE:
115 return get_type_from_typealias (
116 static_cast</*const*/ HIR::TraitItemType &> (*hir_trait_item));
118 case FN:
119 return get_type_from_fn (
120 static_cast</*const*/ HIR::TraitItemFunc &> (*hir_trait_item));
121 break;
123 default:
124 return get_error ();
127 gcc_unreachable ();
128 return get_error ();
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
138 void on_resolved ();
140 void associated_type_set (TyTy::BaseType *ty) const;
142 void associated_type_reset () const;
144 bool is_object_safe () const;
146 private:
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;
155 TyTy::BaseType *
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;
166 bool optional_flag;
167 TraitItemType type;
168 HIR::TraitItem *hir_trait_item;
169 std::vector<TyTy::SubstitutionParamMapping> inherited_substitutions;
170 Location locus;
172 TyTy::BaseType
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
179 class TraitReference
181 public:
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 ());
216 return *this;
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
245 if (is_error ())
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
255 + "]";
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)
279 *ref = &item;
280 return true;
283 return false;
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)
293 continue;
295 if (ident.compare (item.get_identifier ()) == 0)
297 *ref = &item;
298 return true;
301 return false;
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)
311 continue;
313 if (ident.compare (item.get_identifier ()) == 0)
315 *ref = &item;
316 return true;
319 return false;
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)
335 *ref = &item;
336 return true;
340 // lookup super traits
341 for (const auto &super_trait : super_traits)
343 bool found = super_trait->lookup_trait_item (ident, ref);
344 if (found)
345 return true;
348 return false;
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)
358 continue;
360 if (ident.compare (item.get_identifier ()) == 0)
361 return &item;
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 ())
370 return res;
373 return &TraitItemReference::error_node ();
376 size_t size () const { return item_refs.size (); }
378 const std::vector<TraitItemReference> &get_trait_items () const
380 return item_refs;
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);
393 void on_resolved ()
395 for (auto &item : item_refs)
397 item.on_resolved ();
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;
407 if (is_assoc_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
421 return super_traits;
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);
441 bool is_safe
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");
454 return is_safe;
457 bool trait_has_generics () const { return !trait_substs.empty (); }
459 std::vector<TyTy::SubstitutionParamMapping> get_trait_substs () const
461 return trait_substs;
464 bool satisfies_bound (const TraitReference &reference) const
466 if (is_equal (reference))
467 return true;
469 for (const auto &super_trait : super_traits)
471 if (super_trait->satisfies_bound (reference))
472 return true;
475 return false;
478 private:
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
487 public:
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; }
501 TyTy::BaseType *
502 setup_associated_types (const TyTy::BaseType *self,
503 const TyTy::TypeBoundPredicate &bound);
505 void reset_associated_types ();
507 private:
508 TraitReference *trait;
509 HIR::ImplBlock *impl;
510 TyTy::BaseType *self;
511 Resolver::TypeCheckContext *context;
514 } // namespace Resolver
515 } // namespace Rust
517 #endif // RUST_HIR_TRAIT_REF_H