1 // Copyright (C) 2020-2024 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 #include "rust-compile-resolve-path.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"
36 ResolvePathRef::visit (HIR::QualifiedPathInExpression
&expr
)
38 resolved
= resolve (expr
.get_final_segment ().get_segment (),
39 expr
.get_mappings (), expr
.get_locus (), true);
43 ResolvePathRef::visit (HIR::PathInExpression
&expr
)
45 resolved
= resolve (expr
.get_final_segment ().get_segment (),
46 expr
.get_mappings (), expr
.get_locus (), false);
50 ResolvePathRef::attempt_constructor_expression_lookup (
51 TyTy::BaseType
*lookup
, Context
*ctx
, const Analysis::NodeMapping
&mappings
,
52 location_t expr_locus
)
54 // it might be an enum data-less enum variant
55 if (lookup
->get_kind () != TyTy::TypeKind::ADT
)
56 return error_mark_node
;
58 TyTy::ADTType
*adt
= static_cast<TyTy::ADTType
*> (lookup
);
60 return unit_expression (ctx
, expr_locus
);
63 return error_mark_node
;
66 if (!ctx
->get_tyctx ()->lookup_variant_definition (mappings
.get_hirid (),
68 return error_mark_node
;
70 int union_disriminator
= -1;
71 TyTy::VariantDef
*variant
= nullptr;
72 if (!adt
->lookup_variant_by_id (variant_id
, &variant
, &union_disriminator
))
73 return error_mark_node
;
75 // this can only be for discriminant variants the others are built up
76 // using call-expr or struct-init
77 rust_assert (variant
->get_variant_type ()
78 == TyTy::VariantDef::VariantType::NUM
);
80 // we need the actual gcc type
81 tree compiled_adt_type
= TyTyResolveCompile::compile (ctx
, adt
);
83 // make the ctor for the union
84 HIR::Expr
*discrim_expr
= variant
->get_discriminant ();
85 tree discrim_expr_node
= CompileExpr::Compile (discrim_expr
, ctx
);
86 tree folded_discrim_expr
= fold_expr (discrim_expr_node
);
87 tree qualifier
= folded_discrim_expr
;
89 return Backend::constructor_expression (compiled_adt_type
, true, {qualifier
},
90 union_disriminator
, expr_locus
);
94 ResolvePathRef::resolve (const HIR::PathIdentSegment
&final_segment
,
95 const Analysis::NodeMapping
&mappings
,
96 location_t expr_locus
, bool is_qualified_path
)
98 TyTy::BaseType
*lookup
= nullptr;
99 bool ok
= ctx
->get_tyctx ()->lookup_type (mappings
.get_hirid (), &lookup
);
102 // need to look up the reference for this identifier
104 // this can fail because it might be a Constructor for something
105 // in that case the caller should attempt ResolvePathType::Compile
106 NodeId ref_node_id
= UNKNOWN_NODEID
;
107 if (flag_name_resolution_2_0
)
110 = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
112 auto resolved
= nr_ctx
.lookup (mappings
.get_nodeid ());
115 return attempt_constructor_expression_lookup (lookup
, ctx
, mappings
,
118 ref_node_id
= *resolved
;
122 if (!ctx
->get_resolver ()->lookup_resolved_name (mappings
.get_nodeid (),
124 return attempt_constructor_expression_lookup (lookup
, ctx
, mappings
,
129 if (!ctx
->get_mappings ()->lookup_node_to_hir (ref_node_id
, &ref
))
131 rust_error_at (expr_locus
, "reverse call path lookup failure");
132 return error_mark_node
;
135 // might be a constant
137 if (ctx
->lookup_const_decl (ref
, &constant_expr
))
139 TREE_USED (constant_expr
) = 1;
140 return constant_expr
;
143 // maybe closure binding
144 tree closure_binding
= error_mark_node
;
145 if (ctx
->lookup_closure_binding (ref
, &closure_binding
))
147 TREE_USED (closure_binding
) = 1;
148 return closure_binding
;
151 // this might be a variable reference or a function reference
152 Bvariable
*var
= nullptr;
153 if (ctx
->lookup_var_decl (ref
, &var
))
155 // TREE_USED is setup in the gcc abstraction here
156 return Backend::var_expression (var
, expr_locus
);
159 // might be a match pattern binding
160 tree binding
= error_mark_node
;
161 if (ctx
->lookup_pattern_binding (ref
, &binding
))
163 TREE_USED (binding
) = 1;
167 // it might be a function call
168 if (lookup
->get_kind () == TyTy::TypeKind::FNDEF
)
170 TyTy::FnType
*fntype
= static_cast<TyTy::FnType
*> (lookup
);
172 if (ctx
->lookup_function_decl (fntype
->get_ty_ref (), &fn
))
175 return address_expression (fn
, expr_locus
);
177 else if (fntype
->get_abi () == ABI::INTRINSIC
)
179 Intrinsics
compile (ctx
);
180 fn
= compile
.compile (fntype
);
182 return address_expression (fn
, expr_locus
);
186 // let the query system figure it out
187 tree resolved_item
= query_compile (ref
, lookup
, final_segment
, mappings
,
188 expr_locus
, is_qualified_path
);
189 if (resolved_item
!= error_mark_node
)
191 TREE_USED (resolved_item
) = 1;
193 return resolved_item
;
197 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
)
202 HIR::Item
*resolved_item
= ctx
->get_mappings ()->lookup_hir_item (ref
);
204 HIR::ExternalItem
*resolved_extern_item
205 = ctx
->get_mappings ()->lookup_hir_extern_item (ref
, &parent_block
);
206 bool is_hir_item
= resolved_item
!= nullptr;
207 bool is_hir_extern_item
= resolved_extern_item
!= nullptr;
208 bool is_fn
= lookup
->get_kind () == TyTy::TypeKind::FNDEF
;
211 if (!lookup
->has_substitutions_defined ())
212 return CompileItem::compile (resolved_item
, ctx
, nullptr, true,
215 return CompileItem::compile (resolved_item
, ctx
, lookup
, true,
218 else if (is_hir_extern_item
)
220 if (!lookup
->has_substitutions_defined ())
221 return CompileExternItem::compile (resolved_extern_item
, ctx
, nullptr,
224 return CompileExternItem::compile (resolved_extern_item
, ctx
, lookup
,
231 TyTy::FnType
*fn
= static_cast<TyTy::FnType
*> (lookup
);
232 TyTy::BaseType
*receiver
= nullptr;
234 if (fn
->is_method ())
236 receiver
= fn
->get_self_type ();
237 receiver
= receiver
->destructure ();
239 return resolve_method_address (fn
, receiver
, expr_locus
);
243 HirId parent_impl_id
= UNKNOWN_HIRID
;
244 HIR::ImplItem
*resolved_item
245 = ctx
->get_mappings ()->lookup_hir_implitem (ref
, &parent_impl_id
);
246 bool is_impl_item
= resolved_item
!= nullptr;
249 if (!lookup
->has_substitutions_defined ())
250 return CompileInherentImplItem::Compile (resolved_item
, ctx
,
251 nullptr, true, expr_locus
);
253 return CompileInherentImplItem::Compile (resolved_item
, ctx
, lookup
,
258 // it might be resolved to a trait item
259 HIR::TraitItem
*trait_item
260 = ctx
->get_mappings ()->lookup_hir_trait_item (ref
);
261 HIR::Trait
*trait
= ctx
->get_mappings ()->lookup_trait_item_mapping (
262 trait_item
->get_mappings ().get_hirid ());
264 Resolver::TraitReference
*trait_ref
265 = &Resolver::TraitReference::error_node ();
266 bool ok
= ctx
->get_tyctx ()->lookup_trait_reference (
267 trait
->get_mappings ().get_defid (), &trait_ref
);
270 TyTy::BaseType
*receiver
= nullptr;
271 ok
= ctx
->get_tyctx ()->lookup_receiver (mappings
.get_hirid (),
274 receiver
= receiver
->destructure ();
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
281 = Resolver::PathProbeImplTrait::Probe (receiver
, final_segment
,
283 if (candidates
.size () == 0)
285 // this means we are defaulting back to the trait_item if
287 Resolver::TraitItemReference
*trait_item_ref
= nullptr;
288 bool ok
= trait_ref
->lookup_hir_trait_item (*trait_item
,
290 rust_assert (ok
); // found
291 rust_assert (trait_item_ref
->is_optional ()); // has definition
293 return CompileTraitItem::Compile (
294 trait_item_ref
->get_hir_trait_item (), ctx
, lookup
, true,
299 rust_assert (candidates
.size () == 1);
301 auto candidate
= *candidates
.begin ();
302 rust_assert (candidate
.is_impl_candidate ());
304 HIR::ImplBlock
*impl
= candidate
.item
.impl
.parent
;
305 HIR::ImplItem
*impl_item
= candidate
.item
.impl
.impl_item
;
307 TyTy::BaseType
*self
= nullptr;
308 bool ok
= ctx
->get_tyctx ()->lookup_type (
309 impl
->get_type ()->get_mappings ().get_hirid (), &self
);
312 if (!lookup
->has_substitutions_defined ())
313 return CompileInherentImplItem::Compile (impl_item
, ctx
,
317 return CompileInherentImplItem::Compile (impl_item
, ctx
, lookup
,
323 return error_mark_node
;
326 } // namespace Compile