Skip to content

Commit 99da9cc

Browse files
committed
Add codegen support for destructible lambdas
1 parent a35ace0 commit 99da9cc

4 files changed

Lines changed: 35 additions & 0 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,14 @@ void Converter::EmitScopedDestructor(const clang::VarDecl *decl) {
592592
return;
593593
}
594594
auto type = decl->getType();
595+
if (auto lambda = AsLambdaClass(type);
596+
lambda && LambdaNeedsDestruction(lambda)) {
597+
StrCat(token::kSemiColon,
598+
std::format("let _dtor_{0} = ScopedDestructorUnsafe::new(&raw mut "
599+
"{0}, |__f| __f.destroy())",
600+
GetNamedDeclAsString(decl)));
601+
return;
602+
}
595603
if (type->isReferenceType() || type->isArrayType() ||
596604
!TypeNeedsDestruction(type)) {
597605
return;
@@ -3865,6 +3873,11 @@ bool Converter::VisitLambdaExpr(clang::LambdaExpr *expr) {
38653873
StrCat(token::kComma);
38663874
ConvertLambdaClosure(decl);
38673875
ConvertLambdaCopyAndMove(decl);
3876+
if (LambdaNeedsDestruction(decl)) {
3877+
StrCat(token::kComma, "destroy", token::kAssign);
3878+
PushBrace destroy(*this);
3879+
StrCat(DestroyMembers(decl));
3880+
}
38683881
computed_expr_type_ = ComputedExprType::FreshValue;
38693882
return false;
38703883
}

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,12 @@ bool IsLambdaCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor) {
10881088
!decl->captures().empty();
10891089
}
10901090

1091+
bool LambdaNeedsDestruction(const clang::CXXRecordDecl *decl) {
1092+
return llvm::any_of(decl->fields(), [](const clang::FieldDecl *field) {
1093+
return TypeNeedsDestruction(field->getType());
1094+
});
1095+
}
1096+
10911097
clang::Expr *AsLambdaUncapturedConstant(const clang::FunctionDecl *fn,
10921098
clang::DeclRefExpr *expr) {
10931099
if (!AsLambdaOperatorCall(fn)) {

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,8 @@ const clang::LambdaCapture *AsLambdaCapture(const clang::FieldDecl *field);
206206

207207
bool IsLambdaCopyOrMoveConstructor(const clang::CXXConstructorDecl *ctor);
208208

209+
bool LambdaNeedsDestruction(const clang::CXXRecordDecl *decl);
210+
209211
clang::Expr *AsLambdaUncapturedConstant(const clang::FunctionDecl *fn,
210212
clang::DeclRefExpr *expr);
211213

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -873,6 +873,14 @@ void ConverterRefCount::EmitScopedDestructor(const clang::VarDecl *decl) {
873873
return;
874874
}
875875
auto type = decl->getType();
876+
if (auto lambda = AsLambdaClass(type);
877+
lambda && LambdaNeedsDestruction(lambda)) {
878+
StrCat(token::kSemiColon,
879+
std::format("let _dtor_{0} = ScopedDestructor::new(&{0}, |__p| "
880+
"__p.with(|__f| __f.destroy()))",
881+
GetNamedDeclAsString(decl)));
882+
return;
883+
}
876884
if (type->isReferenceType() || type->isArrayType() ||
877885
!TypeNeedsDestruction(type)) {
878886
return;
@@ -3423,6 +3431,12 @@ ConverterRefCount::DestroyMembers(const clang::CXXRecordDecl *decl) {
34233431
std::string out;
34243432
for (auto *field : std::ranges::reverse_view(fields)) {
34253433
auto name = GetNamedDeclAsString(field);
3434+
if (decl->isLambda()) {
3435+
assert(!field->getType()->isArrayType());
3436+
out +=
3437+
std::format("self.{0}.as_pointer().{1}();\n", name, kDestructorName);
3438+
continue;
3439+
}
34263440
if (field->getType()->isArrayType()) {
34273441
auto *elem =
34283442
field->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();

0 commit comments

Comments
 (0)