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
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_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"
28 class OverlappingImplItemPass
: public TypeCheckBase
33 OverlappingImplItemPass pass
;
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 ())
42 pass
.process_impl_item (id
, impl_item
, impl
);
49 void process_impl_item (HirId id
, HIR::ImplItem
*impl_item
,
52 // lets make a mapping of impl-item Self type to (impl-item,name):
54 // impl-type -> [ (item, name), ... ]
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
);
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
));
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
)
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
92 bool a
= query
->is_concrete ();
93 bool b
= candidate
->is_concrete ();
94 bool both_generic
= !a
&& !b
;
97 if (!query
->is_equal (*candidate
))
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",
140 OverlappingImplItemPass () : TypeCheckBase () {}
142 std::map
<TyTy::BaseType
*,
143 std::set
<std::pair
<HIR::ImplItem
*, std::string
> > >
147 } // namespace Resolver
150 #endif // RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H