Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 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-compile-resolve-path.h"
20 : : #include "options.h"
21 : : #include "rust-compile-intrinsic.h"
22 : : #include "rust-compile-item.h"
23 : : #include "rust-compile-implitem.h"
24 : : #include "rust-compile-expr.h"
25 : : #include "rust-hir-map.h"
26 : : #include "rust-hir-trait-resolve.h"
27 : : #include "rust-hir-path-probe.h"
28 : : #include "rust-compile-extern.h"
29 : : #include "rust-constexpr.h"
30 : : #include "rust-tyty.h"
31 : :
32 : : namespace Rust {
33 : : namespace Compile {
34 : :
35 : : void
36 : 79 : ResolvePathRef::visit (HIR::QualifiedPathInExpression &expr)
37 : : {
38 : 79 : resolved = resolve (expr.get_final_segment ().get_segment (),
39 : : expr.get_mappings (), expr.get_locus (), true);
40 : 79 : }
41 : :
42 : : void
43 : 23453 : ResolvePathRef::visit (HIR::PathInExpression &expr)
44 : : {
45 : 23453 : resolved = resolve (expr.get_final_segment ().get_segment (),
46 : : expr.get_mappings (), expr.get_locus (), false);
47 : 23453 : }
48 : :
49 : : tree
50 : 259 : ResolvePathRef::attempt_constructor_expression_lookup (
51 : : TyTy::BaseType *lookup, Context *ctx, const Analysis::NodeMapping &mappings,
52 : : location_t expr_locus)
53 : : {
54 : : // it might be an enum data-less enum variant
55 : 259 : if (lookup->get_kind () != TyTy::TypeKind::ADT)
56 : 1 : return error_mark_node;
57 : :
58 : 258 : TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (lookup);
59 : 258 : if (adt->is_unit ())
60 : 99 : return unit_expression (ctx, expr_locus);
61 : :
62 : 159 : if (!adt->is_enum ())
63 : 0 : return error_mark_node;
64 : :
65 : 159 : HirId variant_id;
66 : 159 : if (!ctx->get_tyctx ()->lookup_variant_definition (mappings.get_hirid (),
67 : : &variant_id))
68 : 0 : return error_mark_node;
69 : :
70 : 159 : int union_disriminator = -1;
71 : 159 : TyTy::VariantDef *variant = nullptr;
72 : 159 : if (!adt->lookup_variant_by_id (variant_id, &variant, &union_disriminator))
73 : 0 : return error_mark_node;
74 : :
75 : : // this can only be for discriminant variants the others are built up
76 : : // using call-expr or struct-init
77 : 159 : rust_assert (variant->get_variant_type ()
78 : : == TyTy::VariantDef::VariantType::NUM);
79 : :
80 : : // we need the actual gcc type
81 : 159 : tree compiled_adt_type = TyTyResolveCompile::compile (ctx, adt);
82 : :
83 : : // make the ctor for the union
84 : 159 : HIR::Expr *discrim_expr = variant->get_discriminant ();
85 : 159 : tree discrim_expr_node = CompileExpr::Compile (discrim_expr, ctx);
86 : 159 : tree folded_discrim_expr = fold_expr (discrim_expr_node);
87 : 159 : tree qualifier = folded_discrim_expr;
88 : :
89 : 159 : return Backend::constructor_expression (compiled_adt_type, true, {qualifier},
90 : : union_disriminator, expr_locus);
91 : : }
92 : :
93 : : tree
94 : 23532 : ResolvePathRef::resolve (const HIR::PathIdentSegment &final_segment,
95 : : const Analysis::NodeMapping &mappings,
96 : : location_t expr_locus, bool is_qualified_path)
97 : : {
98 : 23532 : TyTy::BaseType *lookup = nullptr;
99 : 23532 : bool ok = ctx->get_tyctx ()->lookup_type (mappings.get_hirid (), &lookup);
100 : 23532 : rust_assert (ok);
101 : :
102 : : // need to look up the reference for this identifier
103 : :
104 : : // this can fail because it might be a Constructor for something
105 : : // in that case the caller should attempt ResolvePathType::Compile
106 : 23532 : NodeId ref_node_id = UNKNOWN_NODEID;
107 : 23532 : if (flag_name_resolution_2_0)
108 : : {
109 : 40 : auto nr_ctx
110 : 40 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
111 : :
112 : 40 : auto resolved = nr_ctx.lookup (mappings.get_nodeid ());
113 : :
114 : 40 : if (!resolved)
115 : 0 : return attempt_constructor_expression_lookup (lookup, ctx, mappings,
116 : : expr_locus);
117 : :
118 : 40 : ref_node_id = *resolved;
119 : 40 : }
120 : : else
121 : : {
122 : 23492 : if (!ctx->get_resolver ()->lookup_resolved_name (mappings.get_nodeid (),
123 : : &ref_node_id))
124 : 259 : return attempt_constructor_expression_lookup (lookup, ctx, mappings,
125 : 259 : expr_locus);
126 : : }
127 : :
128 : 23273 : HirId ref;
129 : 23273 : if (!ctx->get_mappings ()->lookup_node_to_hir (ref_node_id, &ref))
130 : : {
131 : 0 : rust_error_at (expr_locus, "reverse call path lookup failure");
132 : 0 : return error_mark_node;
133 : : }
134 : :
135 : : // might be a constant
136 : 23273 : tree constant_expr;
137 : 23273 : if (ctx->lookup_const_decl (ref, &constant_expr))
138 : : {
139 : 757 : TREE_USED (constant_expr) = 1;
140 : 757 : return constant_expr;
141 : : }
142 : :
143 : : // maybe closure binding
144 : 22516 : tree closure_binding = error_mark_node;
145 : 22516 : if (ctx->lookup_closure_binding (ref, &closure_binding))
146 : : {
147 : 7 : TREE_USED (closure_binding) = 1;
148 : 7 : return closure_binding;
149 : : }
150 : :
151 : : // this might be a variable reference or a function reference
152 : 22509 : Bvariable *var = nullptr;
153 : 22509 : if (ctx->lookup_var_decl (ref, &var))
154 : : {
155 : : // TREE_USED is setup in the gcc abstraction here
156 : 16022 : return Backend::var_expression (var, expr_locus);
157 : : }
158 : :
159 : : // might be a match pattern binding
160 : 6487 : tree binding = error_mark_node;
161 : 6487 : if (ctx->lookup_pattern_binding (ref, &binding))
162 : : {
163 : 185 : TREE_USED (binding) = 1;
164 : 185 : return binding;
165 : : }
166 : :
167 : : // it might be a function call
168 : 6302 : if (lookup->get_kind () == TyTy::TypeKind::FNDEF)
169 : : {
170 : 6246 : TyTy::FnType *fntype = static_cast<TyTy::FnType *> (lookup);
171 : 6246 : tree fn = NULL_TREE;
172 : 6246 : if (ctx->lookup_function_decl (fntype->get_ty_ref (), &fn))
173 : : {
174 : 3520 : TREE_USED (fn) = 1;
175 : 5193 : return address_expression (fn, expr_locus);
176 : : }
177 : 2726 : else if (fntype->get_abi () == ABI::INTRINSIC)
178 : : {
179 : 1673 : Intrinsics compile (ctx);
180 : 1673 : fn = compile.compile (fntype);
181 : 1673 : TREE_USED (fn) = 1;
182 : 1673 : return address_expression (fn, expr_locus);
183 : : }
184 : : }
185 : :
186 : : // let the query system figure it out
187 : 1109 : tree resolved_item = query_compile (ref, lookup, final_segment, mappings,
188 : : expr_locus, is_qualified_path);
189 : 1109 : if (resolved_item != error_mark_node)
190 : : {
191 : 1109 : TREE_USED (resolved_item) = 1;
192 : : }
193 : : return resolved_item;
194 : : }
195 : :
196 : : tree
197 : 1109 : HIRCompileBase::query_compile (HirId ref, TyTy::BaseType *lookup,
198 : : const HIR::PathIdentSegment &final_segment,
199 : : const Analysis::NodeMapping &mappings,
200 : : location_t expr_locus, bool is_qualified_path)
201 : : {
202 : 1109 : HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item (ref);
203 : 1109 : HirId parent_block;
204 : 1109 : HIR::ExternalItem *resolved_extern_item
205 : 1109 : = ctx->get_mappings ()->lookup_hir_extern_item (ref, &parent_block);
206 : 1109 : bool is_hir_item = resolved_item != nullptr;
207 : 1109 : bool is_hir_extern_item = resolved_extern_item != nullptr;
208 : 1109 : bool is_fn = lookup->get_kind () == TyTy::TypeKind::FNDEF;
209 : 1109 : if (is_hir_item)
210 : : {
211 : 578 : if (!lookup->has_substitutions_defined ())
212 : 134 : return CompileItem::compile (resolved_item, ctx, nullptr, true,
213 : 134 : expr_locus);
214 : : else
215 : 444 : return CompileItem::compile (resolved_item, ctx, lookup, true,
216 : 444 : expr_locus);
217 : : }
218 : 531 : else if (is_hir_extern_item)
219 : : {
220 : 9 : if (!lookup->has_substitutions_defined ())
221 : 9 : return CompileExternItem::compile (resolved_extern_item, ctx, nullptr,
222 : 9 : true, expr_locus);
223 : : else
224 : 0 : return CompileExternItem::compile (resolved_extern_item, ctx, lookup,
225 : 0 : true, expr_locus);
226 : : }
227 : : else
228 : : {
229 : 522 : if (is_fn)
230 : : {
231 : 522 : TyTy::FnType *fn = static_cast<TyTy::FnType *> (lookup);
232 : 522 : TyTy::BaseType *receiver = nullptr;
233 : :
234 : 522 : if (fn->is_method ())
235 : : {
236 : 92 : receiver = fn->get_self_type ();
237 : 92 : receiver = receiver->destructure ();
238 : :
239 : 92 : return resolve_method_address (fn, receiver, expr_locus);
240 : : }
241 : : }
242 : :
243 : 430 : HirId parent_impl_id = UNKNOWN_HIRID;
244 : 430 : HIR::ImplItem *resolved_item
245 : 430 : = ctx->get_mappings ()->lookup_hir_implitem (ref, &parent_impl_id);
246 : 430 : bool is_impl_item = resolved_item != nullptr;
247 : 430 : if (is_impl_item)
248 : : {
249 : 292 : if (!lookup->has_substitutions_defined ())
250 : 150 : return CompileInherentImplItem::Compile (resolved_item, ctx,
251 : 150 : nullptr, true, expr_locus);
252 : : else
253 : 142 : return CompileInherentImplItem::Compile (resolved_item, ctx, lookup,
254 : 142 : true, expr_locus);
255 : : }
256 : : else
257 : : {
258 : : // it might be resolved to a trait item
259 : 138 : HIR::TraitItem *trait_item
260 : 138 : = ctx->get_mappings ()->lookup_hir_trait_item (ref);
261 : 138 : HIR::Trait *trait = ctx->get_mappings ()->lookup_trait_item_mapping (
262 : 138 : trait_item->get_mappings ().get_hirid ());
263 : :
264 : 138 : Resolver::TraitReference *trait_ref
265 : 138 : = &Resolver::TraitReference::error_node ();
266 : 138 : bool ok = ctx->get_tyctx ()->lookup_trait_reference (
267 : 138 : trait->get_mappings ().get_defid (), &trait_ref);
268 : 138 : rust_assert (ok);
269 : :
270 : 138 : TyTy::BaseType *receiver = nullptr;
271 : 138 : ok = ctx->get_tyctx ()->lookup_receiver (mappings.get_hirid (),
272 : : &receiver);
273 : 138 : rust_assert (ok);
274 : 138 : receiver = receiver->destructure ();
275 : :
276 : : // the type resolver can only resolve type bounds to their trait
277 : : // item so its up to us to figure out if this path should resolve
278 : : // to an trait-impl-block-item or if it can be defaulted to the
279 : : // trait-impl-item's definition
280 : 138 : auto candidates
281 : : = Resolver::PathProbeImplTrait::Probe (receiver, final_segment,
282 : 138 : trait_ref);
283 : 138 : if (candidates.size () == 0)
284 : : {
285 : : // this means we are defaulting back to the trait_item if
286 : : // possible
287 : 107 : Resolver::TraitItemReference *trait_item_ref = nullptr;
288 : 107 : bool ok = trait_ref->lookup_hir_trait_item (*trait_item,
289 : : &trait_item_ref);
290 : 107 : rust_assert (ok); // found
291 : 107 : rust_assert (trait_item_ref->is_optional ()); // has definition
292 : :
293 : 107 : return CompileTraitItem::Compile (
294 : : trait_item_ref->get_hir_trait_item (), ctx, lookup, true,
295 : : expr_locus);
296 : : }
297 : : else
298 : : {
299 : 31 : rust_assert (candidates.size () == 1);
300 : :
301 : 31 : auto candidate = *candidates.begin ();
302 : 31 : rust_assert (candidate.is_impl_candidate ());
303 : :
304 : 31 : HIR::ImplBlock *impl = candidate.item.impl.parent;
305 : 31 : HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
306 : :
307 : 31 : TyTy::BaseType *self = nullptr;
308 : 31 : bool ok = ctx->get_tyctx ()->lookup_type (
309 : 31 : impl->get_type ()->get_mappings ().get_hirid (), &self);
310 : 31 : rust_assert (ok);
311 : :
312 : 31 : if (!lookup->has_substitutions_defined ())
313 : 0 : return CompileInherentImplItem::Compile (impl_item, ctx,
314 : : nullptr, true,
315 : 0 : expr_locus);
316 : : else
317 : 31 : return CompileInherentImplItem::Compile (impl_item, ctx, lookup,
318 : 31 : true, expr_locus);
319 : : }
320 : 138 : }
321 : : }
322 : :
323 : : return error_mark_node;
324 : : }
325 : :
326 : : } // namespace Compile
327 : : } // namespace Rust
|