diff options
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 28 | ||||
-rw-r--r-- | gcc/testsuite/rust/execute/torture/trait4.rs | 36 |
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 +} |