Line data Source code
1 : // Copyright (C) 2020-2026 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 : #include "rust-hir-path-probe-type.h"
20 : #include "rust-hir-map.h"
21 : #include "rust-hir-trait-resolve.h"
22 : #include "rust-hir.h"
23 : #include "rust-type-util.h"
24 : #include "rust-tyty.h"
25 :
26 : namespace Rust {
27 : namespace Resolver {
28 :
29 : TypePathProbeResult
30 207 : TypePathProbe::Probe (TyTy::BaseType *receiver,
31 : const HIR::PathIdentSegment &segment_name)
32 : {
33 207 : TypePathProbe probe (receiver, segment_name);
34 207 : return probe.probe ();
35 207 : }
36 :
37 : TypePathProbeResult
38 207 : TypePathProbe::probe ()
39 : {
40 207 : switch (receiver->get_kind ())
41 : {
42 183 : case TyTy::TypeKind::PARAM:
43 183 : case TyTy::TypeKind::DYNAMIC:
44 183 : probe_generic ();
45 183 : break;
46 :
47 14 : case TyTy::TypeKind::ADT:
48 14 : probe_adt (static_cast<TyTy::ADTType *> (receiver));
49 14 : break;
50 :
51 10 : default:
52 10 : probe_fallback ();
53 10 : break;
54 : }
55 :
56 207 : return std::move (result);
57 : }
58 :
59 : void
60 183 : TypePathProbe::probe_generic ()
61 : {
62 355 : for (const TyTy::TypeBoundPredicate &predicate :
63 538 : receiver->get_specified_bounds ())
64 : {
65 355 : auto candidate = process_predicate_for_candidates (predicate);
66 355 : insert_candidate (std::move (candidate));
67 : }
68 183 : }
69 :
70 : void
71 14 : TypePathProbe::probe_adt (TyTy::ADTType *adt)
72 : {
73 14 : auto adt_item = mappings.lookup_defid (adt->get_id ());
74 14 : if (!adt_item.has_value ())
75 : {
76 0 : probe_fallback ();
77 0 : return;
78 : }
79 :
80 14 : DefId adt_id = adt_item.value ()->get_mappings ().get_defid ();
81 14 : mappings.iterate_adt_impl_items (adt_id,
82 28 : [this] (HirId id, HIR::ImplItem *item,
83 : HIR::ImplBlock *impl) -> bool {
84 98 : return process_impl_item (id, item, impl);
85 : });
86 : }
87 :
88 : void
89 10 : TypePathProbe::probe_fallback ()
90 : {
91 10 : mappings.iterate_impl_items (
92 10 : [&] (HirId id, HIR::ImplItem *item, HIR::ImplBlock *impl) mutable -> bool {
93 22 : return process_impl_item (id, item, impl);
94 : });
95 10 : }
96 :
97 : bool
98 120 : TypePathProbe::process_impl_item (HirId id, HIR::ImplItem *item,
99 : HIR::ImplBlock *impl)
100 : {
101 120 : auto item_name = item->get_impl_item_name ();
102 240 : if (search.to_string () != item_name)
103 : return true;
104 :
105 52 : HirId impl_ty_id = impl->get_type ().get_mappings ().get_hirid ();
106 52 : TyTy::BaseType *impl_block_ty = nullptr;
107 52 : if (!query_type (impl_ty_id, &impl_block_ty))
108 : return true;
109 :
110 52 : if (!types_compatable (TyTy::TyWithLocation (receiver),
111 52 : TyTy::TyWithLocation (impl_block_ty),
112 : impl->get_locus (), false))
113 : return true;
114 :
115 : // Keep trait impl items at trait position. In particular, do not query the
116 : // type of an impl associated-type alias here: projection normalization will
117 : // select and evaluate the concrete alias later.
118 24 : if (impl->has_trait_ref ())
119 : {
120 24 : process_trait_impl_item (impl);
121 24 : return true;
122 : }
123 :
124 0 : TyTy::BaseType *item_ty = nullptr;
125 0 : if (!query_type (id, &item_ty))
126 : return true;
127 :
128 0 : PathProbeCandidate::CandidateType candidate_type;
129 0 : switch (item->get_impl_item_type ())
130 : {
131 : case HIR::ImplItem::FUNCTION:
132 : candidate_type = PathProbeCandidate::IMPL_FUNC;
133 : break;
134 :
135 : case HIR::ImplItem::TYPE_ALIAS:
136 : candidate_type = PathProbeCandidate::IMPL_TYPE_ALIAS;
137 : break;
138 :
139 : case HIR::ImplItem::CONSTANT:
140 : candidate_type = PathProbeCandidate::IMPL_CONST;
141 : break;
142 :
143 : default:
144 : return true;
145 : }
146 :
147 0 : PathProbeCandidate::ImplItemCandidate impl_candidate{item, impl};
148 :
149 0 : insert_candidate (
150 0 : {candidate_type, item_ty, item->get_locus (), impl_candidate});
151 :
152 0 : return true;
153 120 : }
154 :
155 : void
156 24 : TypePathProbe::process_trait_impl_item (HIR::ImplBlock *impl)
157 : {
158 24 : HIR::TypePath &trait_path = impl->get_trait_ref ();
159 24 : TraitReference *trait_ref = TraitResolver::Lookup (trait_path);
160 24 : if (trait_ref->is_error ())
161 0 : trait_ref = TraitResolver::Resolve (trait_path);
162 24 : if (trait_ref->is_error ())
163 0 : return;
164 :
165 24 : TyTy::TypeBoundPredicate predicate (*trait_ref, BoundPolarity::RegularBound,
166 24 : impl->get_locus ());
167 24 : auto candidate = process_predicate_for_candidates (predicate);
168 24 : if (candidate.is_error ())
169 0 : return;
170 :
171 24 : rust_assert (candidate.is_trait_candidate ());
172 24 : candidate.item.trait.impl = impl;
173 24 : insert_candidate (std::move (candidate));
174 24 : }
175 :
176 : PathProbeCandidate
177 379 : TypePathProbe::process_predicate_for_candidates (
178 : const TyTy::TypeBoundPredicate &predicate)
179 : {
180 379 : tl::optional<TyTy::TypeBoundPredicateItem> item
181 758 : = predicate.lookup_associated_item (search.to_string ());
182 379 : if (!item.has_value ())
183 173 : return PathProbeCandidate::get_error ();
184 :
185 206 : const TraitReference *trait_ref = item->get_parent ()->get ();
186 206 : const TraitItemReference *trait_item_ref = item->get_raw_item ();
187 206 : PathProbeCandidate::CandidateType candidate_type;
188 206 : switch (trait_item_ref->get_trait_item_type ())
189 : {
190 : case TraitItemReference::TraitItemType::FN:
191 : candidate_type = PathProbeCandidate::CandidateType::TRAIT_FUNC;
192 : break;
193 : case TraitItemReference::TraitItemType::CONST:
194 : candidate_type = PathProbeCandidate::CandidateType::TRAIT_ITEM_CONST;
195 : break;
196 : case TraitItemReference::TraitItemType::TYPE:
197 : candidate_type = PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
198 : break;
199 :
200 0 : case TraitItemReference::TraitItemType::ERROR:
201 0 : default:
202 0 : return PathProbeCandidate::get_error ();
203 : }
204 :
205 206 : TyTy::BaseType *trait_item_tyty = item->get_raw_item ()->get_tyty ();
206 206 : if (receiver->get_kind () != TyTy::DYNAMIC)
207 206 : trait_item_tyty = item->get_tyty_for_receiver (receiver);
208 :
209 206 : PathProbeCandidate::TraitItemCandidate trait_item_candidate{trait_ref,
210 : trait_item_ref,
211 206 : nullptr};
212 206 : return {candidate_type, trait_item_tyty, trait_item_ref->get_locus (),
213 206 : trait_item_candidate};
214 379 : }
215 :
216 : void
217 379 : TypePathProbe::insert_candidate (PathProbeCandidate candidate)
218 : {
219 379 : if (candidate.is_error ())
220 : return;
221 :
222 206 : bool is_type
223 206 : = candidate.type == PathProbeCandidate::CandidateType::IMPL_TYPE_ALIAS
224 206 : || candidate.type == PathProbeCandidate::CandidateType::TRAIT_TYPE_ALIAS;
225 206 : if (is_type)
226 206 : result.type_candidates.insert (std::move (candidate));
227 : else
228 0 : result.non_type_matches.insert (std::move (candidate));
229 : }
230 :
231 : } // namespace Resolver
232 : } // namespace Rust
|