From: Enes Cevik <[email protected]>
This patch implement the lang item `owned_box` and add support box
expression.
gcc/rust/ChangeLog:
* ast/rust-expr.h (BoxExpr): Add comment description to class.
* backend/rust-compile-block.h (visit): Add stub for BoxExpr.
* backend/rust-compile-expr.cc (compile_box_struct): New
function.
(compile_box): New function.
(build_box_inner_ptr): New function.
(CompileExpr::visit): Implement BoxExpr lowering using
exchange_malloc and constructor expressions. Handle owned_box
in FieldAccessExpr and DereferenceExpr.
(HIRCompileBase::resolve_deref_adjustment): Support owned_box
in deref adjustments.
* backend/rust-compile-expr.h (visit): Declare BoxExpr visitor.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
(ExprStmtBuilder::visit): Evaluate inner expression and push
tmp assignment for BoxExpr.
* checks/errors/borrowck/rust-bir-builder-expr-stmt.h (visit):
Declare BoxExpr visitor.
* checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
(visit): Mark BoxExpr as unreachable.
* checks/errors/borrowck/rust-bir-builder-struct.h (visit):
Likewise.
* checks/errors/borrowck/rust-function-collector.h (visit):
Add visit stub for BoxExpr.
* checks/errors/privacy/rust-privacy-reporter.cc
(PrivacyReporter::visit): Delegate privacy reporting to inner
expression of BoxExpr.
* checks/errors/privacy/rust-privacy-reporter.h (visit):
Declare BoxExpr visitor.
* checks/errors/rust-const-checker.cc (ConstChecker::visit):
Delegate const checking to inner expression.
* checks/errors/rust-const-checker.h (visit): Declare BoxExpr
visitor.
* checks/errors/rust-hir-pattern-analysis.cc
(PatternChecker::visit): Delegate pattern analysis to inner
expression.
* checks/errors/rust-hir-pattern-analysis.h (visit): Declare
BoxExpr visitor.
* checks/errors/rust-unsafe-checker.cc (UnsafeChecker::visit):
Delegate unsafe checking to inner expression.
* checks/errors/rust-unsafe-checker.h (visit): Declare BoxExpr
visitor.
* checks/lints/rust-lint-marklive.cc (MarkLive::visit): Resolve
inner ADT type for owned_box when marking live fields.
* checks/lints/rust-lint-marklive.h (visit): Declare BoxExpr
visitor.
* hir/rust-ast-lower-expr.cc (ASTLoweringExpr::visit): Translate
AST BoxExpr to HIR BoxExpr.
* hir/rust-hir-dump.cc (Dump::visit): Dump HIR BoxExpr.
* hir/rust-hir-dump.h (visit): Declare BoxExpr visitor.
* hir/tree/rust-hir-expr-abstract.h (ExprType): Add Box to enum.
* hir/tree/rust-hir-expr.cc (BoxExpr::BoxExpr): Implement
constructors for BoxExpr. (BoxExpr::operator=): Implement
assignment operator.
* hir/tree/rust-hir-expr.h (class BoxExpr): Define HIR BoxExpr
node.
* hir/tree/rust-hir-full-decls.h (class BoxExpr): Forward
declaration.
* hir/tree/rust-hir-visitor.cc (DefaultHIRVisitor::walk): Walk
inner expression of BoxExpr.
* hir/tree/rust-hir-visitor.h (visit): Add routing for BoxExpr.
* hir/tree/rust-hir.cc (BoxExpr::to_string): Implement
to_string.
(BoxExpr::accept_vis): Implement visitor acceptance.
* typecheck/rust-autoderef.cc (AutoderefCycle::cycle): Attempt
autoderef using the owned_box lang item.
* typecheck/rust-hir-type-check-expr.cc (TypeCheckExpr::visit):
Implement type checking, validation, and generic substitution
for BoxExpr. Support owned_box autoderef in field access and
dereferencing operations.
* typecheck/rust-tyty.cc (try_get_box_inner_type): New function.
* typecheck/rust-tyty.h (try_get_box_inner_type): New
declaration.
* typecheck/rust-hir-type-check-expr.h (visit): Declare BoxExpr
visitor.
* util/rust-lang-item.cc (Rust::LangItem::lang_items): Register
owned_box to BiMap.
* util/rust-lang-item.h (LangItem::Kind): Add OWNED_BOX.
gcc/testsuite/ChangeLog:
* rust/compile/box-expr.rs: New test.
* rust/compile/lang-owned-box-error1.rs: New test.
* rust/compile/lang-owned-box-error2.rs: New test.
Signed-off-by: Enes Cevik <[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/06e19241a8a023f58a0ca9dcd3b9f3d3dea0f0bf
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/4574
gcc/rust/ast/rust-expr.h | 1 +
gcc/rust/backend/rust-compile-block.h | 2 +
gcc/rust/backend/rust-compile-expr.cc | 171 +++++++++++++++++-
gcc/rust/backend/rust-compile-expr.h | 1 +
.../borrowck/rust-bir-builder-expr-stmt.cc | 9 +
.../borrowck/rust-bir-builder-expr-stmt.h | 1 +
.../borrowck/rust-bir-builder-lazyboolexpr.h | 1 +
.../errors/borrowck/rust-bir-builder-struct.h | 1 +
.../errors/borrowck/rust-function-collector.h | 1 +
.../errors/privacy/rust-privacy-reporter.cc | 6 +
.../errors/privacy/rust-privacy-reporter.h | 1 +
gcc/rust/checks/errors/rust-const-checker.cc | 6 +
gcc/rust/checks/errors/rust-const-checker.h | 1 +
.../errors/rust-hir-pattern-analysis.cc | 6 +
.../checks/errors/rust-hir-pattern-analysis.h | 1 +
gcc/rust/checks/errors/rust-unsafe-checker.cc | 6 +
gcc/rust/checks/errors/rust-unsafe-checker.h | 1 +
gcc/rust/checks/lints/rust-lint-marklive.cc | 7 +
gcc/rust/checks/lints/rust-lint-marklive.h | 5 +
gcc/rust/hir/rust-ast-lower-expr.cc | 11 +-
gcc/rust/hir/rust-hir-dump.cc | 11 ++
gcc/rust/hir/rust-hir-dump.h | 1 +
gcc/rust/hir/tree/rust-hir-expr-abstract.h | 1 +
gcc/rust/hir/tree/rust-hir-expr.cc | 27 +++
gcc/rust/hir/tree/rust-hir-expr.h | 46 +++++
gcc/rust/hir/tree/rust-hir-full-decls.h | 1 +
gcc/rust/hir/tree/rust-hir-visitor.cc | 7 +
gcc/rust/hir/tree/rust-hir-visitor.h | 5 +
gcc/rust/hir/tree/rust-hir.cc | 21 +++
gcc/rust/typecheck/rust-autoderef.cc | 15 ++
.../typecheck/rust-hir-type-check-expr.cc | 76 +++++++-
gcc/rust/typecheck/rust-hir-type-check-expr.h | 1 +
gcc/rust/typecheck/rust-tyty.cc | 23 +++
gcc/rust/typecheck/rust-tyty.h | 3 +
gcc/rust/util/rust-lang-item.cc | 1 +
gcc/rust/util/rust-lang-item.h | 3 +-
gcc/testsuite/rust/compile/box-expr.rs | 55 ++++++
.../rust/compile/lang-owned-box-error1.rs | 15 ++
.../rust/compile/lang-owned-box-error2.rs | 12 ++
39 files changed, 556 insertions(+), 7 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/box-expr.rs
create mode 100644 gcc/testsuite/rust/compile/lang-owned-box-error1.rs
create mode 100644 gcc/testsuite/rust/compile/lang-owned-box-error2.rs
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 90e4daec4..921b79800 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3751,6 +3751,7 @@ protected:
}
};
+// Box expression AST node representation
class BoxExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> expr;
diff --git a/gcc/rust/backend/rust-compile-block.h
b/gcc/rust/backend/rust-compile-block.h
index 680b4fb6c..9d29e8fc5 100644
--- a/gcc/rust/backend/rust-compile-block.h
+++ b/gcc/rust/backend/rust-compile-block.h
@@ -94,6 +94,7 @@ public:
void visit (HIR::RangeFullExpr &) override {}
void visit (HIR::RangeFromToInclExpr &) override {}
void visit (HIR::RangeToInclExpr &) override {}
+ void visit (HIR::BoxExpr &) override {}
void visit (HIR::ReturnExpr &) override {}
void visit (HIR::UnsafeBlockExpr &) override {}
void visit (HIR::LoopExpr &) override {}
@@ -184,6 +185,7 @@ public:
void visit (HIR::RangeFullExpr &) override {}
void visit (HIR::RangeFromToInclExpr &) override {}
void visit (HIR::RangeToInclExpr &) override {}
+ void visit (HIR::BoxExpr &) override {}
void visit (HIR::ReturnExpr &) override {}
void visit (HIR::UnsafeBlockExpr &) override {}
void visit (HIR::LoopExpr &) override {}
diff --git a/gcc/rust/backend/rust-compile-expr.cc
b/gcc/rust/backend/rust-compile-expr.cc
index 37a9c702a..55ff3263a 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -45,6 +45,114 @@
namespace Rust {
namespace Compile {
+namespace {
+tree
+compile_box_struct (Context *ctx, TyTy::BaseType *curr_ty, tree typed_ptr,
+ location_t locus, int depth = 0)
+{
+ // infinite loop guard
+ rust_assert (depth < 100);
+
+ if (curr_ty->get_kind () == TyTy::TypeKind::POINTER
+ || curr_ty->get_kind () == TyTy::TypeKind::REF)
+ return typed_ptr;
+
+ if (curr_ty->get_kind () == TyTy::TypeKind::ADT)
+ {
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (curr_ty);
+ tree adt_ty_tree = TyTyResolveCompile::compile (ctx, adt);
+ tree size_tree = TYPE_SIZE_UNIT (adt_ty_tree);
+
+ if (integer_zerop (size_tree))
+ return Backend::constructor_expression (adt_ty_tree, false, {}, -1,
+ locus);
+ rust_assert (!adt->is_enum ());
+ rust_assert (adt->number_of_variants () == 1);
+
+ std::vector<tree> args;
+ TyTy::VariantDef *variant = adt->get_variants ().at (0);
+ for (size_t i = 0; i < variant->num_fields (); i++)
+ {
+ TyTy::StructFieldType *field = variant->get_field_at_index (i);
+ TyTy::BaseType *field_ty = field->get_field_type ();
+ tree field_tree
+ = compile_box_struct (ctx, field_ty, typed_ptr, locus, depth + 1);
+ args.push_back (field_tree);
+ }
+ return Backend::constructor_expression (adt_ty_tree, false, args, -1,
+ locus);
+ }
+ if (curr_ty->get_kind () == TyTy::TypeKind::PARAM)
+ {
+ TyTy::ParamType *param_ty = static_cast<TyTy::ParamType *> (curr_ty);
+ TyTy::BaseType *resolved_ty = param_ty->resolve ();
+ rust_assert (resolved_ty != nullptr && resolved_ty != curr_ty);
+ return compile_box_struct (ctx, resolved_ty, typed_ptr, locus, depth +
1);
+ }
+ rust_unreachable ();
+ return error_mark_node;
+};
+
+tree
+compile_box (Context *ctx, TyTy::BaseType *box_tyty, TyTy::BaseType
*inner_tyty,
+ tree inner_expr_tree, location_t locus)
+{
+ tree inner_type_tree = TyTyResolveCompile::compile (ctx, inner_tyty);
+
+ if (!COMPLETE_TYPE_P (inner_type_tree))
+ {
+ rust_sorry_at (locus,
+ "dynamically sized types in boxes are not supported yet");
+ return error_mark_node;
+ }
+ tree size_tree = TYPE_SIZE_UNIT (inner_type_tree);
+ tree align_tree
+ = build_int_cst (size_type_node, TYPE_ALIGN_UNIT (inner_type_tree));
+
+ DefId exchange_malloc_defid
+ = ctx->get_mappings ().get_lang_item (LangItem::Kind::EXCHANGE_MALLOC,
+ locus);
+ HIR::Item *item
+ = ctx->get_mappings ().lookup_defid (exchange_malloc_defid).value ();
+
+ tree exchange_malloc_decl = nullptr;
+ ctx->lookup_function_decl (item->get_mappings ().get_hirid (),
+ &exchange_malloc_decl, exchange_malloc_defid);
+
+ tree raw_ptr = save_expr (build_call_expr_loc (locus, exchange_malloc_decl,
2,
+ size_tree, align_tree));
+ tree typed_ptr = fold_convert (build_pointer_type (inner_type_tree),
raw_ptr);
+
+ tree deref = build1_loc (locus, INDIRECT_REF, inner_type_tree, typed_ptr);
+ tree assignment
+ = build2_loc (locus, MODIFY_EXPR, inner_type_tree, deref, inner_expr_tree);
+
+ tree box_struct = compile_box_struct (ctx, box_tyty, typed_ptr, locus);
+
+ return build2_loc (locus, COMPOUND_EXPR, TREE_TYPE (box_struct), assignment,
+ box_struct);
+}
+
+tree
+build_box_inner_ptr (tree main_expr, location_t locus)
+{
+ // We continuously extract the first field of the struct until we hit the
+ // actual underlying raw pointer. This handles both simple Box layouts (ptr:
+ // *mut T) and complex ones like this (Box<Unique<NonNull<T>>>). This relies
+ // on the standard library's layout guarantees and will break if a stateful
+ // custom allocator is placed as the first field in the RECORD_TYPE.
+ while (TREE_CODE (TREE_TYPE (main_expr)) == RECORD_TYPE)
+ {
+ tree first_field = TYPE_FIELDS (TREE_TYPE (main_expr));
+ if (first_field == NULL_TREE)
+ break;
+ main_expr = build3_loc (locus, COMPONENT_REF, TREE_TYPE (first_field),
+ main_expr, first_field, NULL_TREE);
+ }
+ return main_expr;
+}
+} // namespace
+
CompileExpr::CompileExpr (Context *ctx)
: HIRCompileBase (ctx), translated (error_mark_node)
{}
@@ -115,6 +223,26 @@ CompileExpr::visit (HIR::TupleExpr &expr)
expr.get_locus ());
}
+void
+CompileExpr::visit (HIR::BoxExpr &expr)
+{
+ TyTy::BaseType *inner_tyty = nullptr;
+ bool ok = ctx->get_tyctx ()->lookup_type (
+ expr.get_expr ().get_mappings ().get_hirid (), &inner_tyty);
+ rust_assert (ok);
+
+ TyTy::BaseType *box_tyty = nullptr;
+ ok = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &box_tyty);
+ rust_assert (ok);
+
+ tree inner_expr_tree
+ = save_expr (CompileExpr::Compile (expr.get_expr (), ctx));
+
+ translated = compile_box (ctx, box_tyty, inner_tyty, inner_expr_tree,
+ expr.get_locus ());
+}
+
void
CompileExpr::visit (HIR::ReturnExpr &expr)
{
@@ -691,7 +819,21 @@ CompileExpr::visit (HIR::FieldAccessExpr &expr)
}
size_t field_index = 0;
- if (receiver->get_kind () == TyTy::TypeKind::ADT)
+
+ if (auto inner_ty = TyTy::try_get_box_inner_type (receiver))
+ {
+ rust_assert ((*inner_ty)->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *inner_adt = static_cast<TyTy::ADTType *> (*inner_ty);
+ TyTy::VariantDef *variant = inner_adt->get_variants ().at (0);
+
+ bool ok = variant->lookup_field (expr.get_field_name ().as_string (),
+ nullptr, &field_index);
+ rust_assert (ok);
+
+ receiver_ref = build_box_inner_ptr (receiver_ref, expr.get_locus ());
+ receiver_ref = indirect_expression (receiver_ref, expr.get_locus ());
+ }
+ else if (receiver->get_kind () == TyTy::TypeKind::ADT)
{
TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (receiver);
rust_assert (!adt->is_enum ());
@@ -1045,6 +1187,21 @@ CompileExpr::visit (HIR::DereferenceExpr &expr)
tree main_expr = CompileExpr::Compile (expr.get_expr (), ctx);
+ // Box<T> Dereference Hook
+ // Typechecker treats 'Box<T>' as a privileged pointer and allows
+ // explicit dereferencing.However, the backend sees Box as a normal
+ // RECORD_TYPE (struct). To solve this, if the type is the 'owned_box'
+ // lang item, we drill down.
+ TyTy::BaseType *base_tyty;
+ if (ctx->get_tyctx ()->lookup_type (
+ expr.get_expr ().get_mappings ().get_hirid (), &base_tyty))
+ {
+ if (TyTy::try_get_box_inner_type (base_tyty))
+ {
+ main_expr = build_box_inner_ptr (main_expr, expr.get_locus ());
+ }
+ }
+
// this might be an operator overload situation lets check
TyTy::FnType *fntype;
bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
@@ -2253,7 +2410,17 @@ HIRCompileBase::resolve_deref_adjustment
(Resolver::Adjustment &adjustment,
{
rust_assert (adjustment.is_deref_adjustment ()
|| adjustment.is_deref_mut_adjustment ());
- rust_assert (adjustment.has_operator_overload ());
+ if (!adjustment.has_operator_overload ())
+ {
+ TyTy::BaseType *receiver = adjustment.get_actual ();
+ if (TyTy::try_get_box_inner_type (receiver))
+ {
+ tree receiver_ref = expression;
+ receiver_ref = build_box_inner_ptr (receiver_ref, locus);
+ return indirect_expression (receiver_ref, locus);
+ }
+ rust_assert (false);
+ }
TyTy::FnType *lookup = adjustment.get_deref_operator_fn ();
TyTy::BaseType *receiver = adjustment.get_actual ();
diff --git a/gcc/rust/backend/rust-compile-expr.h
b/gcc/rust/backend/rust-compile-expr.h
index 532e140c9..90e1985c9 100644
--- a/gcc/rust/backend/rust-compile-expr.h
+++ b/gcc/rust/backend/rust-compile-expr.h
@@ -76,6 +76,7 @@ public:
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
void visit (HIR::OffsetOf &expr) override;
+ void visit (HIR::BoxExpr &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
index 0fe585c23..b14036092 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.cc
@@ -506,6 +506,15 @@ ExprStmtBuilder::visit (HIR::RangeToInclExpr &expr)
expr.get_locus ());
}
+void
+ExprStmtBuilder::visit (HIR::BoxExpr &expr)
+{
+ PlaceId result = visit_expr (expr.get_expr ());
+
+ rust_assert (result != INVALID_PLACE);
+ push_tmp_assignment (result, expr.get_locus ());
+}
+
void
ExprStmtBuilder::visit (HIR::ReturnExpr &ret)
{
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
index 198f3c8fd..8d50b0715 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-expr-stmt.h
@@ -95,6 +95,7 @@ protected: // Expr
void visit (HIR::RangeFullExpr &expr) override;
void visit (HIR::RangeFromToInclExpr &expr) override;
void visit (HIR::RangeToInclExpr &expr) override;
+ void visit (HIR::BoxExpr &expr) override;
void visit (HIR::ReturnExpr &ret) override;
void visit (HIR::UnsafeBlockExpr &expr) override;
void visit (HIR::LoopExpr &expr) override;
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
index e7de77b9f..d360508ef 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-lazyboolexpr.h
@@ -240,6 +240,7 @@ protected: // Illegal at this position.
void visit (HIR::RangeFromToInclExpr &expr) override { rust_unreachable (); }
void visit (HIR::RangeToInclExpr &expr) override { rust_unreachable (); }
void visit (HIR::ReturnExpr &expr) override { rust_unreachable (); }
+ void visit (HIR::BoxExpr &expr) override { rust_unreachable (); }
};
} // namespace BIR
diff --git a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
index 5311ba872..7c669e1cc 100644
--- a/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
+++ b/gcc/rust/checks/errors/borrowck/rust-bir-builder-struct.h
@@ -145,6 +145,7 @@ protected:
void visit (HIR::RangeFullExpr &expr) override { rust_unreachable (); }
void visit (HIR::RangeFromToInclExpr &expr) override { rust_unreachable (); }
void visit (HIR::RangeToInclExpr &expr) override { rust_unreachable (); }
+ void visit (HIR::BoxExpr &expr) override { rust_unreachable (); }
void visit (HIR::ReturnExpr &expr) override { rust_unreachable (); }
void visit (HIR::UnsafeBlockExpr &expr) override { rust_unreachable (); }
void visit (HIR::LoopExpr &expr) override { rust_unreachable (); }
diff --git a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
index a076bcaab..439f5b37b 100644
--- a/gcc/rust/checks/errors/borrowck/rust-function-collector.h
+++ b/gcc/rust/checks/errors/borrowck/rust-function-collector.h
@@ -115,6 +115,7 @@ public:
void visit (HIR::RangeFullExpr &expr) override {}
void visit (HIR::RangeFromToInclExpr &expr) override {}
void visit (HIR::RangeToInclExpr &expr) override {}
+ void visit (HIR::BoxExpr &expr) override {}
void visit (HIR::ReturnExpr &expr) override {}
void visit (HIR::UnsafeBlockExpr &expr) override {}
void visit (HIR::LoopExpr &expr) override {}
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
index 868c5679b..2b4e87421 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.cc
@@ -588,6 +588,12 @@ PrivacyReporter::visit (HIR::RangeToInclExpr &)
// Not handled yet
}
+void
+PrivacyReporter::visit (HIR::BoxExpr &expr)
+{
+ expr.get_expr ().accept_vis (*this);
+}
+
void
PrivacyReporter::visit (HIR::ReturnExpr &expr)
{
diff --git a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
index 07627b1d6..d8d37a537 100644
--- a/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
+++ b/gcc/rust/checks/errors/privacy/rust-privacy-reporter.h
@@ -127,6 +127,7 @@ types
virtual void visit (HIR::RangeFullExpr &expr);
virtual void visit (HIR::RangeFromToInclExpr &expr);
virtual void visit (HIR::RangeToInclExpr &expr);
+ virtual void visit (HIR::BoxExpr &expr);
virtual void visit (HIR::ReturnExpr &expr);
virtual void visit (HIR::UnsafeBlockExpr &expr);
virtual void visit (HIR::LoopExpr &expr);
diff --git a/gcc/rust/checks/errors/rust-const-checker.cc
b/gcc/rust/checks/errors/rust-const-checker.cc
index 39dd70956..7cfd81a4a 100644
--- a/gcc/rust/checks/errors/rust-const-checker.cc
+++ b/gcc/rust/checks/errors/rust-const-checker.cc
@@ -472,6 +472,12 @@ ConstChecker::visit (RangeToInclExpr &)
// FIXME: Visit to_expr
}
+void
+ConstChecker::visit (BoxExpr &expr)
+{
+ expr.get_expr ().accept_vis (*this);
+}
+
void
ConstChecker::visit (ReturnExpr &expr)
{
diff --git a/gcc/rust/checks/errors/rust-const-checker.h
b/gcc/rust/checks/errors/rust-const-checker.h
index 1dae715d8..d2c9b1bf4 100644
--- a/gcc/rust/checks/errors/rust-const-checker.h
+++ b/gcc/rust/checks/errors/rust-const-checker.h
@@ -123,6 +123,7 @@ private:
virtual void visit (RangeFullExpr &expr) override;
virtual void visit (RangeFromToInclExpr &expr) override;
virtual void visit (RangeToInclExpr &expr) override;
+ virtual void visit (BoxExpr &expr) override;
virtual void visit (ReturnExpr &expr) override;
virtual void visit (UnsafeBlockExpr &expr) override;
virtual void visit (LoopExpr &expr) override;
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
index 460ded1b2..ed1bd49ba 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.cc
@@ -343,6 +343,12 @@ PatternChecker::visit (RangeToInclExpr &expr)
expr.get_to_expr ().accept_vis (*this);
}
+void
+PatternChecker::visit (BoxExpr &expr)
+{
+ expr.get_expr ().accept_vis (*this);
+}
+
void
PatternChecker::visit (ReturnExpr &expr)
{
diff --git a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
index 433797ac0..eba88e306 100644
--- a/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
+++ b/gcc/rust/checks/errors/rust-hir-pattern-analysis.h
@@ -97,6 +97,7 @@ private:
virtual void visit (RangeFullExpr &expr) override;
virtual void visit (RangeFromToInclExpr &expr) override;
virtual void visit (RangeToInclExpr &expr) override;
+ virtual void visit (BoxExpr &expr) override;
virtual void visit (ReturnExpr &expr) override;
virtual void visit (UnsafeBlockExpr &expr) override;
virtual void visit (LoopExpr &expr) override;
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.cc
b/gcc/rust/checks/errors/rust-unsafe-checker.cc
index 379cd4c9a..0868aac3a 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.cc
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.cc
@@ -573,6 +573,12 @@ UnsafeChecker::visit (RangeToInclExpr &expr)
expr.get_to_expr ().accept_vis (*this);
}
+void
+UnsafeChecker::visit (BoxExpr &expr)
+{
+ expr.get_expr ().accept_vis (*this);
+}
+
void
UnsafeChecker::visit (ReturnExpr &expr)
{
diff --git a/gcc/rust/checks/errors/rust-unsafe-checker.h
b/gcc/rust/checks/errors/rust-unsafe-checker.h
index ee38c7e66..c964837ec 100644
--- a/gcc/rust/checks/errors/rust-unsafe-checker.h
+++ b/gcc/rust/checks/errors/rust-unsafe-checker.h
@@ -105,6 +105,7 @@ private:
virtual void visit (RangeFullExpr &expr) override;
virtual void visit (RangeFromToInclExpr &expr) override;
virtual void visit (RangeToInclExpr &expr) override;
+ virtual void visit (BoxExpr &expr) override;
virtual void visit (ReturnExpr &expr) override;
virtual void visit (UnsafeBlockExpr &expr) override;
virtual void visit (LoopExpr &expr) override;
diff --git a/gcc/rust/checks/lints/rust-lint-marklive.cc
b/gcc/rust/checks/lints/rust-lint-marklive.cc
index 8fc81b363..796e47de4 100644
--- a/gcc/rust/checks/lints/rust-lint-marklive.cc
+++ b/gcc/rust/checks/lints/rust-lint-marklive.cc
@@ -28,6 +28,7 @@
#include "rust-finalized-name-resolution-context.h"
#include "rust-rib.h"
#include "rust-system.h"
+#include "rust-tyty.h"
namespace Rust {
namespace Analysis {
@@ -199,6 +200,12 @@ MarkLive::visit (HIR::FieldAccessExpr &expr)
if (receiver->get_kind () == TyTy::TypeKind::ADT)
{
adt = static_cast<TyTy::ADTType *> (receiver);
+
+ if (auto inner_ty = TyTy::try_get_box_inner_type (receiver))
+ {
+ rust_assert ((*inner_ty)->get_kind () == TyTy::TypeKind::ADT);
+ adt = static_cast<TyTy::ADTType *> (*inner_ty);
+ }
}
else if (receiver->get_kind () == TyTy::TypeKind::REF)
{
diff --git a/gcc/rust/checks/lints/rust-lint-marklive.h
b/gcc/rust/checks/lints/rust-lint-marklive.h
index 562104f67..bea28e553 100644
--- a/gcc/rust/checks/lints/rust-lint-marklive.h
+++ b/gcc/rust/checks/lints/rust-lint-marklive.h
@@ -139,6 +139,11 @@ public:
function.get_definition ().accept_vis (*this);
}
+ void visit (HIR::BoxExpr &expr) override
+ {
+ expr.get_expr ().accept_vis (*this);
+ }
+
void visit (HIR::ReturnExpr &expr) override
{
if (expr.has_return_expr ())
diff --git a/gcc/rust/hir/rust-ast-lower-expr.cc
b/gcc/rust/hir/rust-ast-lower-expr.cc
index 47f98f3ad..f41ba8bcf 100644
--- a/gcc/rust/hir/rust-ast-lower-expr.cc
+++ b/gcc/rust/hir/rust-ast-lower-expr.cc
@@ -192,8 +192,15 @@ ASTLoweringExpr::visit (AST::QualifiedPathInExpression
&expr)
void
ASTLoweringExpr::visit (AST::BoxExpr &expr)
{
- rust_sorry_at (expr.get_locus (),
- "box expression syntax is not supported yet");
+ HIR::Expr *box_expr = ASTLoweringExpr::translate (expr.get_boxed_expr ());
+
+ auto crate_num = mappings.get_current_crate ();
+ Analysis::NodeMapping mapping (crate_num, expr.get_node_id (),
+ mappings.get_next_hir_id (crate_num),
+ UNKNOWN_LOCAL_DEFID);
+
+ translated = new HIR::BoxExpr (mapping, expr.get_locus (),
+ std::unique_ptr<HIR::Expr> (box_expr));
}
void
diff --git a/gcc/rust/hir/rust-hir-dump.cc b/gcc/rust/hir/rust-hir-dump.cc
index 4e6545d02..4228788bc 100644
--- a/gcc/rust/hir/rust-hir-dump.cc
+++ b/gcc/rust/hir/rust-hir-dump.cc
@@ -1412,6 +1412,17 @@ Dump::visit (RangeToInclExpr &e)
end ("RangeToInclExpr");
}
+void
+Dump::visit (BoxExpr &e)
+{
+ begin ("BoxExpr");
+ do_mappings (e.get_mappings ());
+
+ visit_field ("box_expr", e.get_expr ());
+
+ end ("BoxExpr");
+}
+
void
Dump::visit (ReturnExpr &e)
{
diff --git a/gcc/rust/hir/rust-hir-dump.h b/gcc/rust/hir/rust-hir-dump.h
index e97072dfb..c6496497d 100644
--- a/gcc/rust/hir/rust-hir-dump.h
+++ b/gcc/rust/hir/rust-hir-dump.h
@@ -156,6 +156,7 @@ private:
virtual void visit (RangeFullExpr &) override;
virtual void visit (RangeFromToInclExpr &) override;
virtual void visit (RangeToInclExpr &) override;
+ virtual void visit (BoxExpr &) override;
virtual void visit (ReturnExpr &) override;
virtual void visit (UnsafeBlockExpr &) override;
virtual void visit (LoopExpr &) override;
diff --git a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
index a3d77f668..24fbffac3 100644
--- a/gcc/rust/hir/tree/rust-hir-expr-abstract.h
+++ b/gcc/rust/hir/tree/rust-hir-expr-abstract.h
@@ -75,6 +75,7 @@ public:
InlineAsm,
LlvmInlineAsm,
OffsetOf,
+ Box,
};
BaseKind get_hir_kind () override final { return Node::BaseKind::EXPR; }
diff --git a/gcc/rust/hir/tree/rust-hir-expr.cc
b/gcc/rust/hir/tree/rust-hir-expr.cc
index fe5d4b7ac..b93309cdc 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.cc
+++ b/gcc/rust/hir/tree/rust-hir-expr.cc
@@ -972,6 +972,33 @@ RangeToInclExpr::operator= (RangeToInclExpr const &other)
return *this;
}
+BoxExpr::BoxExpr (Analysis::NodeMapping mappings, location_t locus,
+ std::unique_ptr<Expr> expr, AST::AttrVec outer_attribs)
+ : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)),
+ expr (std::move (expr)), locus (locus)
+{
+ rust_assert (this->expr != nullptr);
+}
+
+BoxExpr::BoxExpr (BoxExpr const &other)
+ : ExprWithoutBlock (other), locus (other.locus)
+{
+ rust_assert (other.expr != nullptr);
+ expr = other.expr->clone_expr ();
+}
+
+BoxExpr &
+BoxExpr::operator= (BoxExpr const &other)
+{
+ ExprWithoutBlock::operator= (other);
+
+ rust_assert (other.expr != nullptr);
+ expr = other.expr->clone_expr ();
+ locus = other.locus;
+
+ return *this;
+}
+
ReturnExpr::ReturnExpr (Analysis::NodeMapping mappings, location_t locus,
std::unique_ptr<Expr> returned_expr,
AST::AttrVec outer_attribs)
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h
b/gcc/rust/hir/tree/rust-hir-expr.h
index ffa2de76e..ad14764eb 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -2267,6 +2267,52 @@ protected:
}
};
+// Box expression HIR node representation
+class BoxExpr : public ExprWithoutBlock
+{
+public:
+ std::unique_ptr<Expr> expr;
+
+ location_t locus;
+
+ std::string to_string () const override;
+
+ // Constructor for BoxExpr.
+ BoxExpr (Analysis::NodeMapping mappings, location_t locus,
+ std::unique_ptr<Expr> expr,
+ AST::AttrVec outer_attribs = AST::AttrVec ());
+ // Copy constructor with clone
+ BoxExpr (BoxExpr const &other);
+
+ // Overloaded assignment operator to clone expr pointer
+ BoxExpr &operator= (BoxExpr const &other);
+
+ // move constructors
+ BoxExpr (BoxExpr &&other) = default;
+ BoxExpr &operator= (BoxExpr &&other) = default;
+
+ location_t get_locus () const override final { return locus; }
+
+ void accept_vis (HIRFullVisitor &vis) override;
+ void accept_vis (HIRExpressionVisitor &vis) override;
+
+ Expr &get_expr () { return *expr; }
+
+ ExprType get_expression_type () const override final { return ExprType::Box;
}
+
+protected:
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BoxExpr *clone_expr_impl () const override { return new BoxExpr (*this); }
+
+ /* Use covariance to implement clone function as returning this object rather
+ * than base */
+ BoxExpr *clone_expr_without_block_impl () const override
+ {
+ return new BoxExpr (*this);
+ }
+};
+
// Return expression HIR node representation
class ReturnExpr : public ExprWithoutBlock
{
diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h
b/gcc/rust/hir/tree/rust-hir-full-decls.h
index dfafee1a3..33a1986bc 100644
--- a/gcc/rust/hir/tree/rust-hir-full-decls.h
+++ b/gcc/rust/hir/tree/rust-hir-full-decls.h
@@ -106,6 +106,7 @@ class RangeToExpr;
class RangeFullExpr;
class RangeFromToInclExpr;
class RangeToInclExpr;
+class BoxExpr;
class ReturnExpr;
class UnsafeBlockExpr;
class LoopLabel;
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.cc
b/gcc/rust/hir/tree/rust-hir-visitor.cc
index db4b2daa8..5128ff4e1 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.cc
+++ b/gcc/rust/hir/tree/rust-hir-visitor.cc
@@ -435,6 +435,13 @@ DefaultHIRVisitor::walk (RangeToInclExpr &expr)
expr.get_to_expr ().accept_vis (*this);
}
+void
+DefaultHIRVisitor::walk (BoxExpr &expr)
+{
+ visit_outer_attrs (expr);
+ expr.get_expr ().accept_vis (*this);
+}
+
void
DefaultHIRVisitor::walk (ReturnExpr &expr)
{
diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h
b/gcc/rust/hir/tree/rust-hir-visitor.h
index e52938222..d39c84fbb 100644
--- a/gcc/rust/hir/tree/rust-hir-visitor.h
+++ b/gcc/rust/hir/tree/rust-hir-visitor.h
@@ -76,6 +76,7 @@ public:
virtual void visit (RangeFullExpr &expr) = 0;
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
+ virtual void visit (BoxExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
@@ -245,6 +246,7 @@ public:
virtual void visit (RangeFullExpr &node) override { walk (node); }
virtual void visit (RangeFromToInclExpr &node) override { walk (node); }
virtual void visit (RangeToInclExpr &node) override { walk (node); }
+ virtual void visit (BoxExpr &node) override { walk (node); }
virtual void visit (ReturnExpr &node) override { walk (node); }
virtual void visit (UnsafeBlockExpr &node) override { walk (node); }
virtual void visit (LoopExpr &node) override { walk (node); }
@@ -386,6 +388,7 @@ protected:
virtual void walk (RangeFullExpr &) final;
virtual void walk (RangeFromToInclExpr &) final;
virtual void walk (RangeToInclExpr &) final;
+ virtual void walk (BoxExpr &) final;
virtual void walk (ReturnExpr &) final;
virtual void walk (UnsafeBlockExpr &) final;
virtual void walk (LoopExpr &) final;
@@ -527,6 +530,7 @@ public:
virtual void visit (RangeFullExpr &) override {}
virtual void visit (RangeFromToInclExpr &) override {}
virtual void visit (RangeToInclExpr &) override {}
+ virtual void visit (BoxExpr &) override {}
virtual void visit (ReturnExpr &) override {}
virtual void visit (UnsafeBlockExpr &) override {}
virtual void visit (LoopExpr &) override {}
@@ -759,6 +763,7 @@ public:
virtual void visit (RangeFullExpr &expr) = 0;
virtual void visit (RangeFromToInclExpr &expr) = 0;
virtual void visit (RangeToInclExpr &expr) = 0;
+ virtual void visit (BoxExpr &expr) = 0;
virtual void visit (ReturnExpr &expr) = 0;
virtual void visit (UnsafeBlockExpr &expr) = 0;
virtual void visit (LoopExpr &expr) = 0;
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index ada104497..2b9bd5670 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -1308,6 +1308,15 @@ BorrowExpr::to_string () const
return str;
}
+std::string
+BoxExpr::to_string () const
+{
+ std::string str = "box ";
+ rust_assert (expr != nullptr);
+ str += expr->to_string ();
+ return str;
+}
+
std::string
ReturnExpr::to_string () const
{
@@ -4249,6 +4258,12 @@ RangeToInclExpr::accept_vis (HIRFullVisitor &vis)
vis.visit (*this);
}
+void
+BoxExpr::accept_vis (HIRFullVisitor &vis)
+{
+ vis.visit (*this);
+}
+
void
ReturnExpr::accept_vis (HIRFullVisitor &vis)
{
@@ -5131,6 +5146,12 @@ RangeToExpr::accept_vis (HIRExpressionVisitor &vis)
vis.visit (*this);
}
+void
+BoxExpr::accept_vis (HIRExpressionVisitor &vis)
+{
+ vis.visit (*this);
+}
+
void
ReturnExpr::accept_vis (HIRExpressionVisitor &vis)
{
diff --git a/gcc/rust/typecheck/rust-autoderef.cc
b/gcc/rust/typecheck/rust-autoderef.cc
index 0c20d41c5..4d323d628 100644
--- a/gcc/rust/typecheck/rust-autoderef.cc
+++ b/gcc/rust/typecheck/rust-autoderef.cc
@@ -330,6 +330,21 @@ AutoderefCycle::cycle (TyTy::BaseType *receiver)
if (autoderef_flag)
return false;
+ // try owned_box
+ if (auto deref_r = try_get_box_inner_type (r))
+ {
+ Adjustment box_deref (Adjustment::AdjustmentType::DEREF, r, *deref_r);
+ adjustments.push_back (box_deref);
+
+ rust_debug ("autoderef try owned_box: {%s}",
+ (*deref_r)->debug_str ().c_str ());
+
+ if (try_autoderefed (*deref_r))
+ return true;
+
+ adjustments.pop_back ();
+ }
+
// try unsize
Adjustment unsize = Adjuster::try_unsize_type (r);
if (!unsize.is_error ())
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index c46338fb2..8ed04d635 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -184,6 +184,65 @@ TypeCheckExpr::visit (HIR::TupleExpr &expr)
expr.get_locus (), fields);
}
+void
+TypeCheckExpr::visit (HIR::BoxExpr &expr)
+{
+ auto owned_box_defid
+ = mappings.get_lang_item (LangItem::Kind::OWNED_BOX, expr.get_locus ());
+
+ HIR::Item *item = mappings.lookup_defid (owned_box_defid).value ();
+ TyTy::BaseType *item_type = nullptr;
+
+ bool ok
+ = context->lookup_type (item->get_mappings ().get_hirid (), &item_type);
+ rust_assert (ok);
+ if (item_type->get_kind () != TyTy::TypeKind::ADT)
+ {
+ rust_error_at (item->get_locus (), ErrorCode::E0718,
+ "%qs language item must be applied to a struct",
+ "owned_box");
+ return;
+ }
+ TyTy::ADTType *adt = static_cast<TyTy::ADTType *> (item_type);
+ if (!adt->is_tuple_struct () && !adt->is_struct_struct ())
+ {
+ rust_error_at (item->get_locus (), ErrorCode::E0718,
+ "%qs language item must be applied to a struct",
+ "owned_box");
+ return;
+ }
+
+ // this is at least one generic item
+ if (adt->get_num_substitutions () < 1)
+ {
+ rust_error_at (expr.get_locus (),
+ "%qs lang item must be applied to a struct with at least "
+ "1 generic argument",
+ "owned_box");
+ return;
+ }
+
+ TyTy::BaseType *inner_ty = TypeCheckExpr::Resolve (expr.get_expr ());
+ if (inner_ty->get_kind () == TyTy::TypeKind::ERROR)
+ {
+ infered = inner_ty;
+ return;
+ }
+
+ auto lookup = SubstMapper::InferSubst (adt, expr.get_locus ());
+ rust_assert (lookup->get_kind () == TyTy::TypeKind::ADT);
+ TyTy::ADTType *adt_box = static_cast<TyTy::ADTType *> (lookup);
+
+ TyTy::BaseType *infer = adt_box->get_substs ().at (0).get_param_ty ();
+
+ unify_site (expr.get_mappings ().get_hirid (),
+ TyTy::TyWithLocation (infer, expr.get_locus ()),
+ TyTy::TyWithLocation (inner_ty, expr.get_locus ()),
+ expr.get_locus ());
+
+ infered = adt_box;
+}
+
void
TypeCheckExpr::visit (HIR::ReturnExpr &expr)
{
@@ -1285,6 +1344,12 @@ TypeCheckExpr::visit (HIR::FieldAccessExpr &expr)
{
auto struct_base = TypeCheckExpr::Resolve (expr.get_receiver_expr ());
+ // Box<T> autoderef
+ if (auto try_struct_base = TyTy::try_get_box_inner_type (struct_base))
+ {
+ struct_base = *try_struct_base;
+ }
+
// FIXME does this require autoderef here?
if (struct_base->get_kind () == TyTy::TypeKind::REF)
{
@@ -1728,14 +1793,21 @@ TypeCheckExpr::visit (HIR::DereferenceExpr &expr)
bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF
|| resolved_base->get_kind () == TyTy::TypeKind::POINTER;
- if (!is_valid_type)
+
+ auto try_owned_box = TyTy::try_get_box_inner_type (resolved_base);
+
+ if (!is_valid_type && !try_owned_box)
{
rust_error_at (expr.get_locus (), "expected reference type got %s",
resolved_base->as_string ().c_str ());
return;
}
- if (resolved_base->get_kind () == TyTy::TypeKind::REF)
+ if (try_owned_box)
+ {
+ infered = (*try_owned_box)->clone ();
+ }
+ else if (resolved_base->get_kind () == TyTy::TypeKind::REF)
{
TyTy::ReferenceType *ref_base
= static_cast<TyTy::ReferenceType *> (resolved_base);
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h
b/gcc/rust/typecheck/rust-hir-type-check-expr.h
index 03157bd28..44e870697 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.h
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h
@@ -80,6 +80,7 @@ public:
void visit (HIR::InlineAsm &expr) override;
void visit (HIR::LlvmInlineAsm &expr) override;
void visit (HIR::OffsetOf &expr) override;
+ void visit (HIR::BoxExpr &expr) override;
// TODO
void visit (HIR::ErrorPropagationExpr &) override {}
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index 9ad09a323..66f5fc5cb 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -4538,5 +4538,28 @@ DynamicObjectType::get_object_items () const
return items;
}
+WARN_UNUSED_RESULT tl::optional<BaseType *>
+try_get_box_inner_type (BaseType *base)
+{
+ if (base->get_kind () != TypeKind::ADT)
+ return tl::nullopt;
+
+ ADTType *adt = static_cast<ADTType *> (base);
+ auto owned_box_lookup
+ = Analysis::Mappings::get ().lookup_lang_item (LangItem::Kind::OWNED_BOX);
+
+ if (owned_box_lookup && adt->get_id () == *owned_box_lookup)
+ {
+ auto args = adt->get_substitution_arguments ();
+ if (!args.is_empty ())
+ {
+ auto inner = args.get_mappings ().front ().get_tyty ();
+ rust_assert (inner != nullptr);
+ return inner;
+ }
+ }
+ return tl::nullopt;
+}
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index b27de7422..b5e5f02c6 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -1960,6 +1960,9 @@ BaseType::try_as<const SubstitutionRef> () const
return nullptr;
}
+WARN_UNUSED_RESULT tl::optional<BaseType *>
+try_get_box_inner_type (BaseType *base);
+
} // namespace TyTy
} // namespace Rust
diff --git a/gcc/rust/util/rust-lang-item.cc b/gcc/rust/util/rust-lang-item.cc
index 2f7704546..91284e27b 100644
--- a/gcc/rust/util/rust-lang-item.cc
+++ b/gcc/rust/util/rust-lang-item.cc
@@ -125,6 +125,7 @@ const BiMap<std::string, LangItem::Kind>
Rust::LangItem::lang_items = {{
{"manually_drop", Kind::MANUALLY_DROP},
{"exchange_malloc", Kind::EXCHANGE_MALLOC},
+ {"owned_box", Kind::OWNED_BOX},
}};
tl::optional<LangItem::Kind>
diff --git a/gcc/rust/util/rust-lang-item.h b/gcc/rust/util/rust-lang-item.h
index 75f4090b9..d96fa9e6a 100644
--- a/gcc/rust/util/rust-lang-item.h
+++ b/gcc/rust/util/rust-lang-item.h
@@ -160,7 +160,8 @@ public:
MANUALLY_DROP,
- EXCHANGE_MALLOC
+ EXCHANGE_MALLOC,
+ OWNED_BOX,
};
static const BiMap<std::string, Kind> lang_items;
diff --git a/gcc/testsuite/rust/compile/box-expr.rs
b/gcc/testsuite/rust/compile/box-expr.rs
new file mode 100644
index 000000000..979977658
--- /dev/null
+++ b/gcc/testsuite/rust/compile/box-expr.rs
@@ -0,0 +1,55 @@
+#![no_core]
+#![feature(no_core, lang_items, box_syntax)]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "phantom_data"]
+pub struct PhantomData<T: ?Sized>;
+
+pub struct NonNull<T: ?Sized> {
+ _pointer: *const T,
+}
+
+pub struct Unique<T: ?Sized> {
+ _pointer: NonNull<T>,
+ _marker: PhantomData<T>,
+}
+
+pub struct Global;
+
+#[lang = "exchange_malloc"]
+fn _exchange_malloc() -> *mut u8 {
+ 0 as *mut u8
+}
+
+#[lang = "owned_box"]
+pub struct Box<T, A = Global>(Unique<T>, A);
+
+impl<T> Box<T> {
+ pub fn new(x: T) -> Self {
+ box x
+ }
+}
+
+struct NonCopyStruct {
+ id: i32,
+}
+
+impl NonCopyStruct {
+ fn get_id(&self) -> i32 {
+ self.id
+ }
+}
+
+fn main() {
+ let my_box: Box<NonCopyStruct> = Box::new(NonCopyStruct { id: 42 });
+ let _moved_val = *my_box;
+
+
+ let my_box2: Box<NonCopyStruct> = Box::new(NonCopyStruct { id: 100 });
+
+ let _val_id = my_box2.id;
+
+ let _val_method_id = my_box2.get_id();
+}
diff --git a/gcc/testsuite/rust/compile/lang-owned-box-error1.rs
b/gcc/testsuite/rust/compile/lang-owned-box-error1.rs
new file mode 100644
index 000000000..54258ddac
--- /dev/null
+++ b/gcc/testsuite/rust/compile/lang-owned-box-error1.rs
@@ -0,0 +1,15 @@
+#![feature(no_core, lang_items, box_syntax)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "owned_box"]
+pub enum EnumBox<T> { // { dg-error "language item must be applied to a
struct" }
+ Some(T),
+ None,
+}
+
+fn _foo() {
+ let _ = box 5;
+}
diff --git a/gcc/testsuite/rust/compile/lang-owned-box-error2.rs
b/gcc/testsuite/rust/compile/lang-owned-box-error2.rs
new file mode 100644
index 000000000..8a57dfa69
--- /dev/null
+++ b/gcc/testsuite/rust/compile/lang-owned-box-error2.rs
@@ -0,0 +1,12 @@
+#![feature(no_core, lang_items, box_syntax)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+#[lang = "owned_box"]
+pub struct BadBox;
+
+fn _foo() {
+ let _ = box 5; // { dg-error "lang item must be applied to a struct with
at least 1 generic argument" }
+}
base-commit: 95a37ea1f0e451c769072130e1893706cd2bcdad
--
2.54.0