aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-09-15 16:16:55 +0100
committerPhilip Herron <philip.herron@embecosm.com>2021-09-15 16:27:21 +0100
commit04549bf8c34cdb3ea435d8542f2cac6d46bcd30f (patch)
tree49df4a8cb24256fa97180bcd464a0cd5ba71f0ae /gcc
parent4493f1c927c79e5b0933d26e9597044790c22f12 (diff)
downloadgcc-04549bf8c34cdb3ea435d8542f2cac6d46bcd30f.zip
gcc-04549bf8c34cdb3ea435d8542f2cac6d46bcd30f.tar.gz
gcc-04549bf8c34cdb3ea435d8542f2cac6d46bcd30f.tar.bz2
Fix bug when calling method from generic reciever type-bound
When we have a generic function with a specified type bound, this means the method resolution can only resolve this to the trait item. During code generation we must then monomorphize this and lookup the associated impl block item for this trait (if it exists) and call this function. Fixes #678
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/backend/rust-compile.cc28
-rw-r--r--gcc/testsuite/rust/execute/torture/trait4.rs36
2 files changed, 58 insertions, 6 deletions
diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc
index 5214b1d..f0e26dc 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -22,6 +22,7 @@
#include "rust-compile-struct-field-expr.h"
#include "rust-hir-trait-resolve.h"
#include "rust-hir-path-probe.h"
+#include "rust-hir-dot-operator.h"
namespace Rust {
namespace Compile {
@@ -171,10 +172,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
// item so its up to us to figure out if this path should resolve
// to an trait-impl-block-item or if it can be defaulted to the
// trait-impl-item's definition
+
+ auto root = receiver->get_root ();
std::vector<Resolver::PathProbeCandidate> candidates
= Resolver::PathProbeType::Probe (
- receiver, expr.get_method_name ().get_segment (), true, false,
- true);
+ root, expr.get_method_name ().get_segment (), true, false, true);
if (candidates.size () == 0)
{
@@ -186,6 +188,11 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
rust_assert (ok); // found
rust_assert (trait_item_ref->is_optional ()); // has definition
+ // FIXME Optional means it has a definition and an associated
+ // block which can be a default implementation, if it does not
+ // contain an implementation we should actually return
+ // error_mark_node
+
TyTy::BaseType *self_type = nullptr;
if (!ctx->get_tyctx ()->lookup_type (
expr.get_receiver ()->get_mappings ().get_hirid (),
@@ -209,10 +216,19 @@ CompileExpr::visit (HIR::MethodCallExpr &expr)
}
else
{
- Resolver::PathProbeCandidate &candidate = candidates.at (0);
- rust_assert (candidate.is_impl_candidate ());
-
- HIR::ImplItem *impl_item = candidate.item.impl.impl_item;
+ std::vector<Resolver::Adjustment> adjustments;
+ Resolver::PathProbeCandidate *candidate
+ = Resolver::MethodResolution::Select (candidates, root,
+ adjustments);
+
+ // FIXME this will be a case to return error_mark_node, there is
+ // an error scenario where a Trait Foo has a method Bar, but this
+ // receiver does not implement this trait or has an incompatible
+ // implementation and we should just return error_mark_node
+ rust_assert (candidate != nullptr);
+ rust_assert (candidate->is_impl_candidate ());
+
+ HIR::ImplItem *impl_item = candidate->item.impl.impl_item;
TyTy::BaseType *self_type = nullptr;
if (!ctx->get_tyctx ()->lookup_type (
diff --git a/gcc/testsuite/rust/execute/torture/trait4.rs b/gcc/testsuite/rust/execute/torture/trait4.rs
new file mode 100644
index 0000000..8c9b740
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait4.rs
@@ -0,0 +1,36 @@
+/* { dg-output "123\n" }*/
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+struct Foo(i32);
+trait Bar {
+ fn baz(&self);
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+impl Bar for Foo {
+ fn baz(&self) {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, self.0);
+ }
+ }
+}
+
+fn type_bound<T: Bar>(t: &T) {
+ t.baz();
+}
+
+fn main() -> i32 {
+ let a;
+
+ a = &Foo(123);
+ type_bound(a);
+
+ 0
+}