diff options
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 29 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 4 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.cc | 14 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/index1.rs | 28 |
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 +} |