1 // Copyright (C) 2020-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_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-hir-full.h"
28 class ImplItemToName
: private TypeCheckBase
, private HIR::HIRImplVisitor
31 static bool resolve (HIR::ImplItem
*item
, std::string
&name_result
)
33 ImplItemToName
resolver (name_result
);
34 item
->accept_vis (resolver
);
38 void visit (HIR::TypeAlias
&alias
) override
41 result
.assign (alias
.get_new_type_name ());
44 void visit (HIR::Function
&function
) override
47 result
.assign (function
.get_function_name ());
50 void visit (HIR::ConstantItem
&constant
) override
53 result
.assign (constant
.get_identifier ());
57 ImplItemToName (std::string
&result
)
58 : TypeCheckBase (), ok (false), result (result
)
65 class OverlappingImplItemPass
: public TypeCheckBase
70 OverlappingImplItemPass pass
;
73 pass
.mappings
->iterate_impl_items (
74 [&] (HirId id
, HIR::ImplItem
*impl_item
, HIR::ImplBlock
*impl
) -> bool {
75 // ignoring trait-impls might need thought later on
76 if (impl
->has_trait_ref ())
79 pass
.process_impl_item (id
, impl_item
, impl
);
86 void process_impl_item (HirId id
, HIR::ImplItem
*impl_item
,
89 // lets make a mapping of impl-item Self type to (impl-item,name):
91 // impl-type -> [ (item, name), ... ]
94 HirId impl_type_id
= impl
->get_type ()->get_mappings ().get_hirid ();
95 TyTy::BaseType
*impl_type
= nullptr;
96 bool ok
= query_type (impl_type_id
, &impl_type
);
100 std::string impl_item_name
;
101 ok
= ImplItemToName::resolve (impl_item
, impl_item_name
);
104 std::pair
<HIR::ImplItem
*, std::string
> elem (impl_item
, impl_item_name
);
105 impl_mappings
[impl_type
].insert (std::move (elem
));
110 // we can now brute force the map looking for can_eq on each of the
111 // impl_items_types to look for possible colliding impl blocks;
112 for (auto it
= impl_mappings
.begin (); it
!= impl_mappings
.end (); it
++)
114 TyTy::BaseType
*query
= it
->first
;
116 for (auto iy
= impl_mappings
.begin (); iy
!= impl_mappings
.end (); iy
++)
118 TyTy::BaseType
*candidate
= iy
->first
;
119 if (query
== candidate
)
122 if (query
->can_eq (candidate
, false))
124 // we might be in the case that we have:
126 // *const T vs *const [T]
128 // so lets use an equality check when the
129 // candidates are both generic to be sure we dont emit a false
132 bool a
= query
->is_concrete ();
133 bool b
= candidate
->is_concrete ();
134 bool both_generic
= !a
&& !b
;
137 if (!query
->is_equal (*candidate
))
141 possible_collision (it
->second
, iy
->second
);
147 void possible_collision (
148 std::set
<std::pair
<HIR::ImplItem
*, std::string
> > query
,
149 std::set
<std::pair
<HIR::ImplItem
*, std::string
> > candidate
)
151 for (auto &q
: query
)
153 HIR::ImplItem
*query_impl_item
= q
.first
;
154 std::string query_impl_item_name
= q
.second
;
156 for (auto &c
: candidate
)
158 HIR::ImplItem
*candidate_impl_item
= c
.first
;
159 std::string candidate_impl_item_name
= c
.second
;
161 if (query_impl_item_name
.compare (candidate_impl_item_name
) == 0)
162 collision_detected (query_impl_item
, candidate_impl_item
,
163 candidate_impl_item_name
);
168 void collision_detected (HIR::ImplItem
*query
, HIR::ImplItem
*dup
,
169 const std::string
&name
)
171 RichLocation
r (dup
->get_locus ());
172 r
.add_range (query
->get_locus ());
173 rust_error_at (r
, "duplicate definitions with name %s", name
.c_str ());
177 OverlappingImplItemPass () : TypeCheckBase () {}
179 std::map
<TyTy::BaseType
*,
180 std::set
<std::pair
<HIR::ImplItem
*, std::string
> > >
184 } // namespace Resolver
187 #endif // RUST_HIR_INHERENT_IMPL_ITEM_OVERLAP_H