diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.cc | 37 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 21 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 33 | ||||
-rw-r--r-- | gcc/rust/util/rust-hir-map.h | 8 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/operator_overload_10.rs | 79 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/operator_overload_7.rs | 44 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/operator_overload_8.rs | 61 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/operator_overload_9.rs | 61 |
8 files changed, 321 insertions, 23 deletions
diff --git a/gcc/rust/backend/rust-compile-expr.cc b/gcc/rust/backend/rust-compile-expr.cc index fb01d8d..6051f50 100644 --- a/gcc/rust/backend/rust-compile-expr.cc +++ b/gcc/rust/backend/rust-compile-expr.cc @@ -117,6 +117,43 @@ CompileExpr::visit (HIR::NegationExpr &expr) = ctx->get_backend ()->negation_expression (op, negated_expr, location); } +void +CompileExpr::visit (HIR::DereferenceExpr &expr) +{ + TyTy::BaseType *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), + &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this TupleExpr"); + return; + } + + tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); + + // this might be an operator overload situation lets check + 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::DEREF; + tree operator_overload_call + = resolve_operator_overload (lang_item_type, expr, main_expr, nullptr, + expr.get_expr ().get (), nullptr); + + // rust deref always returns a reference from this overload then we can + // actually do the indirection + main_expr = operator_overload_call; + } + + tree expected_type = TyTyResolveCompile::compile (ctx, tyty); + bool known_valid = true; + translated + = ctx->get_backend ()->indirect_expression (expected_type, main_expr, + known_valid, expr.get_locus ()); +} + tree CompileExpr::compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, TyTy::BaseType *receiver, diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 46d501a..1e8e1f6 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -979,26 +979,7 @@ public: = ctx->get_backend ()->address_expression (main_expr, expr.get_locus ()); } - void visit (HIR::DereferenceExpr &expr) override - { - tree main_expr = CompileExpr::Compile (expr.get_expr ().get (), ctx); - - TyTy::BaseType *tyty = nullptr; - if (!ctx->get_tyctx ()->lookup_type (expr.get_mappings ().get_hirid (), - &tyty)) - { - rust_fatal_error (expr.get_locus (), - "did not resolve type for this TupleExpr"); - return; - } - - tree expected_type = TyTyResolveCompile::compile (ctx, tyty); - bool known_valid = true; - translated - = ctx->get_backend ()->indirect_expression (expected_type, main_expr, - known_valid, - expr.get_locus ()); - } + void visit (HIR::DereferenceExpr &expr) override; protected: tree compile_dyn_dispatch_call (const TyTy::DynamicObjectType *dyn, diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 5d6017c..1015cc2 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -1219,6 +1219,18 @@ public: TyTy::BaseType *resolved_base = TypeCheckExpr::Resolve (expr.get_expr ().get (), false); + auto lang_item_type = Analysis::RustLangItem::ItemType::DEREF; + bool operator_overloaded + = resolve_operator_overload (lang_item_type, expr, resolved_base, + nullptr); + if (operator_overloaded) + { + // operator overloaded deref always refurns a reference type lets assert + // this + rust_assert (infered->get_kind () == TyTy::TypeKind::REF); + resolved_base = infered; + } + bool is_valid_type = resolved_base->get_kind () == TyTy::TypeKind::REF || resolved_base->get_kind () == TyTy::TypeKind::POINTER; @@ -1281,9 +1293,24 @@ protected: bool probe_impls = !receiver_is_generic; bool ignore_mandatory_trait_items = !receiver_is_generic; - auto candidates = PathProbeType::Probe ( - root, HIR::PathIdentSegment (associated_item_name), probe_impls, - probe_bounds, ignore_mandatory_trait_items, respective_lang_item_id); + auto probe_type = probe_impls ? lhs : root; + auto candidates + = PathProbeType::Probe (probe_type, + HIR::PathIdentSegment (associated_item_name), + probe_impls, probe_bounds, + ignore_mandatory_trait_items); + if (candidates.empty ()) + { + if (probe_impls) + { + candidates = PathProbeType::Probe ( + root, HIR::PathIdentSegment (associated_item_name), probe_impls, + probe_bounds, ignore_mandatory_trait_items); + } + + if (candidates.empty ()) + return false; + } // autoderef to find the relevant method std::vector<Adjustment> adjustments; diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 4f8c389..77a4caf 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -51,6 +51,8 @@ public: DIV_ASSIGN, REM_ASSIGN, + DEREF, + UNKNOWN, }; @@ -104,6 +106,10 @@ public: { return ItemType::REM_ASSIGN; } + else if (item.compare ("deref") == 0) + { + return ItemType::DEREF; + } return ItemType::UNKNOWN; } @@ -136,6 +142,8 @@ public: return "div_assign"; case REM_ASSIGN: return "rem_assign"; + case DEREF: + return "deref"; case UNKNOWN: break; diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_10.rs b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs new file mode 100644 index 0000000..23ae778 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_10.rs @@ -0,0 +1,79 @@ +/* { dg-output "foo_deref\n123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "deref"] +pub trait Deref { + type Target; + + fn deref(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 } +} + +impl<T> Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "imm_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +impl<T> Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "mut_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +struct Foo<T>(T); +impl<T> Deref for Foo<T> { + type Target = T; + + fn deref(&self) -> &Self::Target { + unsafe { + let a = "foo_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + &self.0 + } +} + +fn main() -> i32 { + let foo: Foo<i32> = Foo(123); + let bar: i32 = *foo; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, bar); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_7.rs b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs new file mode 100644 index 0000000..6ff3a87 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_7.rs @@ -0,0 +1,44 @@ +/* { dg-output "imm_deref\n123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "deref"] +pub trait Deref { + type Target; + + fn deref(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 } +} + +impl<T> Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + unsafe { + let a = "imm_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +fn main() -> i32 { + let foo: &i32 = &123; + let res: i32 = *foo; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_8.rs b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs new file mode 100644 index 0000000..d853d71 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_8.rs @@ -0,0 +1,61 @@ +/* { dg-output "imm_deref\n123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "deref"] +pub trait Deref { + type Target; + + fn deref(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 } +} + +impl<T> Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + unsafe { + let a = "imm_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +impl<T> Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "mut_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +fn main() -> i32 { + let foo: &i32 = &123; + let res: i32 = *foo; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res); + } + + 0 +} diff --git a/gcc/testsuite/rust/execute/torture/operator_overload_9.rs b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs new file mode 100644 index 0000000..5c770e7 --- /dev/null +++ b/gcc/testsuite/rust/execute/torture/operator_overload_9.rs @@ -0,0 +1,61 @@ +/* { dg-output "mut_deref\n123\n" } */ +extern "C" { + fn printf(s: *const i8, ...); +} + +#[lang = "deref"] +pub trait Deref { + type Target; + + fn deref(&self) -> &Self::Target; + // { dg-warning "unused name .self." "" { target *-*-* } .-1 } + // { dg-warning "unused name .Deref::deref." "" { target *-*-* } .-2 } +} + +impl<T> Deref for &T { + type Target = T; + + fn deref(&self) -> &T { + // { dg-warning "unused name" "" { target *-*-* } .-1 } + unsafe { + let a = "imm_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +impl<T> Deref for &mut T { + type Target = T; + + fn deref(&self) -> &T { + unsafe { + let a = "mut_deref\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c); + } + + *self + } +} + +fn main() -> i32 { + let foo = &mut 123; + let res: i32 = *foo; + + unsafe { + let a = "%i\n\0"; + let b = a as *const str; + let c = b as *const i8; + + printf(c, res); + } + + 0 +} |