Skip to content

Commit 22c6bca

Browse files
committed
Add support for index lang item overloads
This reuses our code to resolve operator overloads to call into the index lang item for the array-index-expression this serves as a basis for supporting slices. Fixes #975
1 parent d8351d9 commit 22c6bca

File tree

4 files changed

+75
-0
lines changed

4 files changed

+75
-0
lines changed

gcc/rust/backend/rust-compile-expr.cc

+29
Original file line numberDiff line numberDiff line change
@@ -1490,6 +1490,35 @@ CompileExpr::visit (HIR::ArrayIndexExpr &expr)
14901490
tree array_reference = CompileExpr::Compile (expr.get_array_expr (), ctx);
14911491
tree index = CompileExpr::Compile (expr.get_index_expr (), ctx);
14921492

1493+
// this might be an core::ops::index lang item situation
1494+
TyTy::FnType *fntype;
1495+
bool is_op_overload = ctx->get_tyctx ()->lookup_operator_overload (
1496+
expr.get_mappings ().get_hirid (), &fntype);
1497+
if (is_op_overload)
1498+
{
1499+
auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
1500+
tree operator_overload_call
1501+
= resolve_operator_overload (lang_item_type, expr, array_reference,
1502+
index, expr.get_array_expr (),
1503+
expr.get_index_expr ());
1504+
1505+
// lookup the expected type for this expression
1506+
TyTy::BaseType *tyty = nullptr;
1507+
bool ok
1508+
= ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (),
1509+
&tyty);
1510+
rust_assert (ok);
1511+
tree expected_type = TyTyResolveCompile::compile (ctx, tyty);
1512+
1513+
// rust deref always returns a reference from this overload then we can
1514+
// actually do the indirection
1515+
translated
1516+
= ctx->get_backend ()->indirect_expression (expected_type,
1517+
operator_overload_call,
1518+
true, expr.get_locus ());
1519+
return;
1520+
}
1521+
14931522
// lets check if the array is a reference type then we can add an
14941523
// indirection if required
14951524
TyTy::BaseType *array_expr_ty = nullptr;

gcc/rust/hir/tree/rust-hir-expr.h

+4
Original file line numberDiff line numberDiff line change
@@ -4050,6 +4050,10 @@ class OperatorExprMeta
40504050
: node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
40514051
{}
40524052

4053+
OperatorExprMeta (HIR::ArrayIndexExpr &expr)
4054+
: node_mappings (expr.get_mappings ()), locus (expr.get_locus ())
4055+
{}
4056+
40534057
const Analysis::NodeMapping &get_mappings () const { return node_mappings; }
40544058

40554059
Location get_locus () const { return locus; }

gcc/rust/typecheck/rust-hir-type-check-expr.cc

+14
Original file line numberDiff line numberDiff line change
@@ -255,6 +255,20 @@ TypeCheckExpr::visit (HIR::ArrayIndexExpr &expr)
255255
return;
256256

257257
// is this a case of core::ops::index?
258+
auto lang_item_type = Analysis::RustLangItem::ItemType::INDEX;
259+
bool operator_overloaded
260+
= resolve_operator_overload (lang_item_type, expr, array_expr_ty,
261+
index_expr_ty);
262+
if (operator_overloaded)
263+
{
264+
// index and index mut always return a reference to the element
265+
TyTy::BaseType *resolved = infered;
266+
rust_assert (resolved->get_kind () == TyTy::TypeKind::REF);
267+
TyTy::ReferenceType *ref = static_cast<TyTy::ReferenceType *> (resolved);
268+
269+
infered = ref->get_base ()->clone ();
270+
return;
271+
}
258272

259273
if (array_expr_ty->get_kind () == TyTy::TypeKind::REF)
260274
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
// { dg-additional-options "-w" }
2+
#[lang = "index"]
3+
trait Index<Idx> {
4+
type Output;
5+
6+
fn index(&self, index: Idx) -> &Self::Output;
7+
}
8+
9+
struct Foo(i32, i32);
10+
impl Index<isize> for Foo {
11+
type Output = i32;
12+
13+
fn index(&self, index: isize) -> &i32 {
14+
if index == 0 {
15+
&self.0
16+
} else {
17+
&self.1
18+
}
19+
}
20+
}
21+
22+
fn main() -> i32 {
23+
let a = Foo(1, 2);
24+
let b = a[0];
25+
let c = a[1];
26+
27+
c - b - 1
28+
}

0 commit comments

Comments
 (0)