aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile-expr.cc29
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h4
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.cc14
-rw-r--r--gcc/testsuite/rust/execute/torture/index1.rs28
4 files changed, 75 insertions, 0 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc
index dfe5231..bf47661 100644
--- a/gcc/rust/backend/rust-compile-expr.cc
+++ b/gcc/rust/backend/rust-compile-expr.cc
@@ -1490,6 +1490,35 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
+ // this might be an core::ops::index lang item situation
+ TyTy::FnType *fntype;
+ bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
+ expr.get_mappings ().get_hirid (), &fntype);
+ if (is_op_overload)
+ {
+ auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
+ tree operator_overload_call
+ = resolve_operator_overload (lang_item_type, expr, array_reference,
+ index, expr.get_array_expr (),
+ expr.get_index_expr ());
+
+ // lookup the expected type for this expression
+ TyTy::BaseType *tyty = nullptr;
+ bool ok
+ = ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
+ &tyty);
+ rust_assert (ok);
+ tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
+
+ // rust deref always returns a reference from this overload then we can
+ // actually do the indirection
+ translated
+ = ctx->get_backend ()->indirect_expression (expected_type,
+ operator_overload_call,
+ true, expr.get_locus ());
+ return;
+ }
+
// lets check if the array is a reference type then we can add an
// indirection if required
TyTy::BaseType *array_expr_ty = nullptr;
diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h
index 6ec8d52..b77545a 100644
--- a/gcc/rust/hir/tree/rust-hir-expr.h
+++ b/gcc/rust/hir/tree/rust-hir-expr.h
@@ -4050,6 +4050,10 @@ public:
: node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
{}
+ OperatorExprMeta (HIR::ArrayIndexExpr &expr)
+ : node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
+ {}
+
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
Location get_locus () const { return locus; }
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.cc b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
index 7ae2b57..539a3fe 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-expr.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-expr.cc
@@ -255,6 +255,20 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
return;
// is this a case of core::ops::index?
+ auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
+ bool operator_overloaded
+ = resolve_operator_overload (lang_item_type, expr, array_expr_ty,
+ index_expr_ty);
+ if (operator_overloaded)
+ {
+ // index and index mut always return a reference to the element
+ TyTy::BaseType *resolved = infered;
+ rust_assert (resolved->get_kind () == TyTy::TypeKind::REF);
+ TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (resolved);
+
+ infered = ref->get_base ()->clone ();
+ return;
+ }
if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
{
diff --git a/gcc/testsuite/rust/execute/torture/index1.rs b/gcc/testsuite/rust/execute/torture/index1.rs
new file mode 100644
index 0000000..4682978
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/index1.rs
@@ -0,0 +1,28 @@
+// { dg-additional-options "-w" }
+#[lang = "index"]
+trait Index<Idx> {
+ type Output;
+
+ fn index(&self, index: Idx) -> &Self::Output;
+}
+
+struct Foo(i32, i32);
+impl Index<isize> for Foo {
+ type Output = i32;
+
+ fn index(&self, index: isize) -> &i32 {
+ if index == 0 {
+ &self.0
+ } else {
+ &self.1
+ }
+ }
+}
+
+fn main() -> i32 {
+ let a = Foo(1, 2);
+ let b = a[0];
+ let c = a[1];
+
+ c - b - 1
+}