Line data Source code
1 : // Copyright (C) 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-compile-drop.h"
20 : #include "rust-compile-drop-builder.h"
21 : #include "rust-compile-base.h"
22 : #include "rust-compile-context.h"
23 : #include "rust-compile-implitem.h"
24 : #include "rust-hir-path-probe.h"
25 : #include "rust-hir-trait-reference.h"
26 : #include "rust-hir-type-bounds.h"
27 : #include "rust-lang-item.h"
28 : #include "rust-tyty.h"
29 :
30 : namespace Rust {
31 : namespace Compile {
32 :
33 54303 : CompileDrop::CompileDrop (Context *ctx) : ctx (ctx) {}
34 :
35 : bool
36 17835 : CompileDrop::type_has_drop_impl (TyTy::BaseType *ty)
37 : {
38 17835 : auto drop_lang_item
39 17835 : = ctx->get_mappings ().lookup_lang_item (LangItem::Kind::DROP);
40 :
41 17835 : if (!drop_lang_item.has_value ())
42 : return false;
43 :
44 51 : DefId drop_id = drop_lang_item.value ();
45 :
46 51 : auto candidates = Resolver::TypeBoundsProbe::Probe (ty);
47 76 : for (auto &candidate : candidates)
48 : {
49 51 : Resolver::TraitReference *trait_ref = candidate.first;
50 76 : if (trait_ref != nullptr && trait_ref->get_defid () == drop_id)
51 26 : return true;
52 : }
53 :
54 : return false;
55 51 : }
56 :
57 : // Find the Drop trait, look for the drop method, and build the function call.
58 : tree
59 25 : CompileDrop::compile_drop_call (Bvariable *var, TyTy::BaseType *ty,
60 : location_t locus)
61 : {
62 25 : auto drop_lang = ctx->get_mappings ().lookup_lang_item (LangItem::Kind::DROP);
63 25 : if (!drop_lang.has_value ())
64 : return NULL_TREE;
65 :
66 25 : Resolver::TraitReference *drop_ref = nullptr;
67 25 : bool ok
68 25 : = ctx->get_tyctx ()->lookup_trait_reference (drop_lang.value (), &drop_ref);
69 25 : if (!ok)
70 : return NULL_TREE;
71 :
72 25 : HIR::PathIdentSegment segment ("drop");
73 25 : auto candidates
74 25 : = Resolver::PathProbeImplTrait::Probe (ty->get_root (), segment, drop_ref);
75 :
76 25 : rust_assert (candidates.size () == 1);
77 :
78 25 : auto &candidate = *candidates.begin ();
79 25 : rust_assert (candidate.is_impl_candidate ());
80 25 : rust_assert (candidate.ty->get_kind () == TyTy::TypeKind::FNDEF);
81 :
82 25 : auto *fn_type = static_cast<TyTy::FnType *> (candidate.ty);
83 25 : tree fn_addr
84 25 : = CompileInherentImplItem::Compile (candidate.item.impl.impl_item, ctx,
85 : fn_type, locus);
86 :
87 25 : tree var_expr = Backend::var_expression (var, locus);
88 25 : tree var_addr = HIRCompileBase::address_expression (var_expr, locus);
89 :
90 25 : return Backend::call_expression (fn_addr, {var_addr}, nullptr, locus);
91 25 : }
92 :
93 : tree
94 36468 : CompileDrop::build_current_scope_drop_cleanup ()
95 : {
96 36468 : std::vector<tree> drop_stmts;
97 :
98 36468 : DropBuilder drop_builder (*ctx);
99 36468 : auto &drop_candidates = drop_builder.peek_block_drop_candidates ();
100 :
101 36493 : for (auto it = drop_candidates.rbegin (); it != drop_candidates.rend (); ++it)
102 : {
103 25 : TyTy::BaseType *ty = nullptr;
104 25 : Bvariable *var = nullptr;
105 :
106 25 : bool ok = ctx->get_tyctx ()->lookup_type (it->hirid, &ty);
107 25 : rust_assert (ok);
108 :
109 25 : ok = ctx->lookup_var_decl (it->hirid, &var);
110 25 : rust_assert (ok);
111 :
112 25 : tree drop_call = compile_drop_call (var, ty, it->locus);
113 25 : if (drop_call != NULL_TREE)
114 25 : drop_stmts.push_back (convert_to_void (drop_call, ICV_STATEMENT));
115 : }
116 :
117 36468 : if (drop_stmts.empty ())
118 : return NULL_TREE;
119 :
120 21 : return Backend::statement_list (drop_stmts);
121 36468 : }
122 :
123 : } // namespace Compile
124 : } // namespace Rust
|