[PR testsuite/116860] Testsuite adjustment for recently added tests
[official-gcc.git] / gcc / rust / typecheck / rust-hir-inherent-impl-overlap.h
blob60f8345c9a5190c6c4ba9c453c118bba75ec6b3d
1 // Copyright (C) 2020-2025 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_INHERENT_IMPL_ITEM_OVERLAP_H
20 #define RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H
22 #include "rust-hir-type-check-base.h"
23 #include "rust-type-util.h"
25 namespace Rust {
26 namespace Resolver {
28 class OverlappingImplItemPass : public TypeCheckBase
30 public:
31 static void go ()
33 OverlappingImplItemPass pass;
35 // generate mappings
36 pass.mappings->iterate_impl_items (
37 [&] (HirId id, HIR::ImplItem *impl_item, HIR::ImplBlock *impl) -> bool {
38 // ignoring trait-impls might need thought later on
39 if (impl->has_trait_ref ())
40 return true;
42 pass.process_impl_item (id, impl_item, impl);
43 return true;
44 });
46 pass.scan ();
49 void process_impl_item (HirId id, HIR::ImplItem *impl_item,
50 HIR::ImplBlock *impl)
52 // lets make a mapping of impl-item Self type to (impl-item,name):
53 // {
54 // impl-type -> [ (item, name), ... ]
55 // }
57 HirId impl_type_id = impl->get_type ()->get_mappings ().get_hirid ();
58 TyTy::BaseType *impl_type = nullptr;
59 bool ok = query_type (impl_type_id, &impl_type);
60 if (!ok)
61 return;
63 std::string impl_item_name = impl_item->get_impl_item_name ();
64 std::pair<HIR::ImplItem *, std::string> elem (impl_item, impl_item_name);
65 impl_mappings[impl_type].insert (std::move (elem));
68 void scan ()
70 // we can now brute force the map looking for can_eq on each of the
71 // impl_items_types to look for possible colliding impl blocks;
72 for (auto it = impl_mappings.begin (); it != impl_mappings.end (); it++)
74 TyTy::BaseType *query = it->first;
76 for (auto iy = impl_mappings.begin (); iy != impl_mappings.end (); iy++)
78 TyTy::BaseType *candidate = iy->first;
79 if (query == candidate)
80 continue;
82 if (query->can_eq (candidate, false))
84 // we might be in the case that we have:
86 // *const T vs *const [T]
88 // so lets use an equality check when the
89 // candidates are both generic to be sure we dont emit a false
90 // positive
92 bool a = query->is_concrete ();
93 bool b = candidate->is_concrete ();
94 bool both_generic = !a && !b;
95 if (both_generic)
97 if (!query->is_equal (*candidate))
98 continue;
101 possible_collision (it->second, iy->second);
107 void possible_collision (
108 std::set<std::pair<HIR::ImplItem *, std::string> > query,
109 std::set<std::pair<HIR::ImplItem *, std::string> > candidate)
111 for (auto &q : query)
113 HIR::ImplItem *query_impl_item = q.first;
114 std::string query_impl_item_name = q.second;
116 for (auto &c : candidate)
118 HIR::ImplItem *candidate_impl_item = c.first;
119 std::string candidate_impl_item_name = c.second;
121 if (query_impl_item_name.compare (candidate_impl_item_name) == 0)
122 collision_detected (query_impl_item, candidate_impl_item,
123 candidate_impl_item_name);
128 void collision_detected (HIR::ImplItem *query, HIR::ImplItem *dup,
129 const std::string &name)
131 rich_location r (line_table, dup->get_locus ());
132 std::string msg = "duplicate definitions for " + name;
133 r.add_fixit_replace (query->get_locus (), msg.c_str ());
134 r.add_range (query->get_locus ());
135 rust_error_at (r, ErrorCode::E0592, "duplicate definitions with name %qs",
136 name.c_str ());
139 private:
140 OverlappingImplItemPass () : TypeCheckBase () {}
142 std::map<TyTy::BaseType *,
143 std::set<std::pair<HIR::ImplItem *, std::string> > >
144 impl_mappings;
147 } // namespace Resolver
148 } // namespace Rust
150 #endif // RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H