From: lishin <[email protected]>
Add a helper for building Drop calls, and use it when leaving a block.
Add a block-exit test case.
gcc/rust/ChangeLog:
* backend/rust-compile-block.cc (compile_drop_call): New helper to
build a drop call.
(CompileBlock::visit): Add drop calls for candidates.
* backend/rust-compile-pattern.cc (type_has_drop_impl): New helper to
check whether a type implements Drop.
(CompilePatternLet::visit): Save initialized simple drop candidates.
gcc/testsuite/ChangeLog:
* rust/execute/drop-block-scope.rs: New test.
Signed-off-by: lishin <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/f04080f419b936719b22b2d6816661e12a4ea1f5
The commit has NOT been mentioned in any issue.
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4564
gcc/rust/backend/rust-compile-block.cc | 58 +++++++++++++++++++
gcc/rust/backend/rust-compile-pattern.cc | 30 ++++++++++
.../rust/execute/drop-block-scope.rs | 34 +++++++++++
3 files changed, 122 insertions(+)
create mode 100644 gcc/testsuite/rust/execute/drop-block-scope.rs
diff --git a/gcc/rust/backend/rust-compile-block.cc
b/gcc/rust/backend/rust-compile-block.cc
index 9a95d4e15..21ee37c48 100644
--- a/gcc/rust/backend/rust-compile-block.cc
+++ b/gcc/rust/backend/rust-compile-block.cc
@@ -19,11 +19,51 @@
#include "rust-compile-block.h"
#include "rust-compile-stmt.h"
#include "rust-compile-expr.h"
+#include "rust-compile-implitem.h"
#include "rust-hir-expr.h"
+#include "rust-hir-path-probe.h"
+#include "rust-lang-item.h"
namespace Rust {
namespace Compile {
+static tree
+compile_drop_call (Context *ctx, Bvariable *var, TyTy::BaseType *ty,
+ location_t locus)
+{
+ auto drop_lang = ctx->get_mappings ().lookup_lang_item
(LangItem::Kind::DROP);
+ if (!drop_lang.has_value ())
+ return NULL_TREE;
+
+ Resolver::TraitReference *drop_ref = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_trait_reference (drop_lang.value (),
&drop_ref);
+ if (!ok)
+ return NULL_TREE;
+
+ HIR::PathIdentSegment segment ("drop");
+ auto candidates
+ = Resolver::PathProbeImplTrait::Probe (ty->get_root (), segment, drop_ref);
+
+ for (auto &candidate : candidates)
+ {
+ if (!candidate.is_impl_candidate ()
+ || candidate.ty->get_kind () != TyTy::TypeKind::FNDEF)
+ continue;
+
+ auto *fn_type = static_cast<TyTy::FnType *> (candidate.ty);
+ tree fn_addr
+ = CompileInherentImplItem::Compile (candidate.item.impl.impl_item, ctx,
+ fn_type, locus);
+
+ tree var_expr = Backend::var_expression (var, locus);
+ tree var_addr = HIRCompileBase::address_expression (var_expr, locus);
+
+ return Backend::call_expression (fn_addr, {var_addr}, nullptr, locus);
+ }
+ return NULL_TREE;
+}
+
CompileBlock::CompileBlock (Context *ctx, Bvariable *result)
: HIRCompileBase (ctx), translated (nullptr), result (result)
{}
@@ -85,6 +125,24 @@ CompileBlock::visit (HIR::BlockExpr &expr)
ctx->add_statement (assignment);
}
+ auto &drop_candidates = ctx->peek_block_drop_candidates ();
+
+ for (auto it = drop_candidates.rbegin (); it != drop_candidates.rend ();
++it)
+ {
+ TyTy::BaseType *ty = nullptr;
+ Bvariable *var = nullptr;
+
+ bool ok = ctx->get_tyctx ()->lookup_type (it->hirid, &ty);
+ rust_assert (ok);
+
+ ok = ctx->lookup_var_decl (it->hirid, &var);
+ rust_assert (ok);
+
+ tree drop_call = compile_drop_call (ctx, var, ty, it->locus);
+ if (drop_call != NULL_TREE)
+ ctx->add_statement (convert_to_void (drop_call, ICV_STATEMENT));
+ }
+
ctx->pop_block ();
translated = new_block;
}
diff --git a/gcc/rust/backend/rust-compile-pattern.cc
b/gcc/rust/backend/rust-compile-pattern.cc
index d57616e6d..eb1541c8a 100644
--- a/gcc/rust/backend/rust-compile-pattern.cc
+++ b/gcc/rust/backend/rust-compile-pattern.cc
@@ -27,11 +27,36 @@
#include "rust-hir-pattern.h"
#include "rust-system.h"
#include "rust-tyty.h"
+#include "rust-hir-type-bounds.h"
+#include "rust-hir-trait-reference.h"
+#include "rust-lang-item.h"
#include "tree.h"
namespace Rust {
namespace Compile {
+static bool
+type_has_drop_impl (Context *ctx, TyTy::BaseType *ty)
+{
+ auto drop_lang_item
+ = ctx->get_mappings ().lookup_lang_item (LangItem::Kind::DROP);
+
+ if (!drop_lang_item.has_value ())
+ return false;
+
+ DefId drop_id = drop_lang_item.value ();
+
+ auto candidates = Resolver::TypeBoundsProbe::Probe (ty);
+ for (auto &candidate : candidates)
+ {
+ Resolver::TraitReference *trait_ref = candidate.first;
+ if (trait_ref != nullptr && trait_ref->get_defid () == drop_id)
+ return true;
+ }
+
+ return false;
+}
+
void
CompilePatternCheckExpr::visit (HIR::PathInExpression &pattern)
{
@@ -1343,6 +1368,11 @@ CompilePatternLet::visit (HIR::IdentifierPattern
&pattern)
auto s = Backend::init_statement (fnctx.fndecl, var, init_expr);
ctx->add_statement (s);
}
+
+ if (!pattern.has_subpattern () && !pattern.get_is_ref ()
+ && type_has_drop_impl (ctx, ty))
+ ctx->note_simple_drop_candidate (pattern.get_mappings ().get_hirid (),
+ pattern.get_locus ());
}
void
diff --git a/gcc/testsuite/rust/execute/drop-block-scope.rs
b/gcc/testsuite/rust/execute/drop-block-scope.rs
new file mode 100644
index 000000000..678ad63d7
--- /dev/null
+++ b/gcc/testsuite/rust/execute/drop-block-scope.rs
@@ -0,0 +1,34 @@
+// { dg-output "d\r*\n" }
+#![feature(no_core)]
+#![feature(lang_items)]
+#![no_core]
+
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "drop"]
+pub trait Drop {
+ fn drop(&mut self);
+}
+
+struct Droppable;
+
+impl Drop for Droppable {
+ fn drop(&mut self) {
+ let msg = "d\n\0" as *const str as *const i8;
+ unsafe {
+ printf(msg);
+ }
+ }
+}
+
+fn main() -> i32 {
+ {
+ let _x = Droppable;
+ }
+ 0
+}
--
2.54.0