1 // Copyright (C) 2020-2023 Free Software Foundation, Inc.
2
3 // This file is part of GCC.
4
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.
9
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.
14
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/>.
18
19 #ifndef RUST_HIR_PATH_PROBE_H
20 #define RUST_HIR_PATH_PROBE_H
21
22 #include "rust-hir-type-check-base.h"
23 #include "rust-hir-full.h"
24 #include "rust-tyty.h"
25 #include "rust-substitution-mapper.h"
26 #include "rust-hir-type-bounds.h"
27
28 namespace Rust {
29 namespace Resolver {
30
31 struct PathProbeCandidate
32 {
33 enum CandidateType
34 {
35 ERROR,
36
37 ENUM_VARIANT,
38
39 IMPL_CONST,
40 IMPL_TYPE_ALIAS,
41 IMPL_FUNC,
42
43 TRAIT_ITEM_CONST,
44 TRAIT_TYPE_ALIAS,
45 TRAIT_FUNC,
46 };
47
48 struct EnumItemCandidate
49 {
50 const TyTy::ADTType *parent;
51 const TyTy::VariantDef *variant;
52 };
53
54 struct ImplItemCandidate
55 {
56 HIR::ImplItem *impl_item;
57 HIR::ImplBlock *parent;
58 };
59
60 struct TraitItemCandidate
61 {
62 const TraitReference *trait_ref;
63 const TraitItemReference *item_ref;
64 HIR::ImplBlock *impl;
65 };
66
67 CandidateType type;
68 TyTy::BaseType *ty;
69 Location locus;
70 union Candidate
71 {
72 EnumItemCandidate enum_field;
73 ImplItemCandidate impl;
74 TraitItemCandidate trait;
75
76 Candidate (EnumItemCandidate enum_field);
77 Candidate (ImplItemCandidate impl);
78 Candidate (TraitItemCandidate trait);
79 } item;
80
81 PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
82 EnumItemCandidate enum_field);
83
84 PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
85 ImplItemCandidate impl);
86
87 PathProbeCandidate (CandidateType type, TyTy::BaseType *ty, Location locus,
88 TraitItemCandidate trait);
89
90 std::string as_string () const;
91
92 bool is_enum_candidate () const;
93
94 bool is_impl_candidate () const;
95
96 bool is_trait_candidate () const;
97
98 bool is_full_trait_item_candidate () const;
99
100 static PathProbeCandidate get_error ();
101
102 bool is_error () const;
103
104 DefId get_defid () const;
105
106 bool operator< (const PathProbeCandidate &c) const;
107 };
108
109 class PathProbeType : public TypeCheckBase, public HIR::HIRImplVisitor
110 {
111 public:
112 static std::set<PathProbeCandidate>
113 Probe (const TyTy::BaseType *receiver,
114 const HIR::PathIdentSegment &segment_name, bool probe_impls,
115 bool probe_bounds, bool ignore_mandatory_trait_items,
116 DefId specific_trait_id = UNKNOWN_DEFID);
117
118 void visit (HIR::TypeAlias &alias) override;
119 void visit (HIR::ConstantItem &constant) override;
120 void visit (HIR::Function &function) override;
121
122 protected:
123 void process_enum_item_for_candiates (const TyTy::ADTType *adt);
124
125 void process_impl_items_for_candidates ();
126
127 void process_impl_item_candidate (HirId id, HIR::ImplItem *item,
128 HIR::ImplBlock *impl);
129
130 void
131 process_associated_trait_for_candidates (const TraitReference *trait_ref,
132 HIR::ImplBlock *impl,
133 bool ignore_mandatory_trait_items);
134
135 void
136 process_predicate_for_candidates (const TyTy::TypeBoundPredicate &predicate,
137 bool ignore_mandatory_trait_items);
138
139 protected:
140 PathProbeType (const TyTy::BaseType *receiver,
141 const HIR::PathIdentSegment &query, DefId specific_trait_id);
142
143 std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>>
144 union_bounds (
145 const std::vector<std::pair</*const*/ TraitReference *, HIR::ImplBlock *>>
146 a,
147 const std::vector<std::pair<const TraitReference *, HIR::ImplBlock *>> b)
148 const;
149
150 bool is_reciever_generic () const;
151
152 const TyTy::BaseType *receiver;
153 const HIR::PathIdentSegment &search;
154 std::set<PathProbeCandidate> candidates;
155 HIR::ImplBlock *current_impl;
156 DefId specific_trait_id;
157 };
158
159 class ReportMultipleCandidateError : private TypeCheckBase
160 {
161 public:
162 static void Report (std::set<PathProbeCandidate> &candidates,
163 const HIR::PathIdentSegment &query, Location query_locus)
164 {
165 RichLocation r (query_locus);
166 for (auto &c : candidates)
167 r.add_range (c.locus);
168
169 rust_error_at (r, "multiple applicable items in scope for: %s",
170 query.as_string ().c_str ());
171 }
172 };
173
174 class PathProbeImplTrait : public PathProbeType
175 {
176 public:
177 static std::set<PathProbeCandidate>
178 Probe (const TyTy::BaseType *receiver,
179 const HIR::PathIdentSegment &segment_name,
180 const TraitReference *trait_reference);
181
182 private:
183 PathProbeImplTrait (const TyTy::BaseType *receiver,
184 const HIR::PathIdentSegment &query,
185 const TraitReference *trait_reference);
186
187 void process_trait_impl_items_for_candidates ();
188
189 const TraitReference *trait_reference;
190 };
191
192 } // namespace Resolver
193 } // namespace Rust
194
195 #endif // RUST_HIR_PATH_PROBE_H