diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2021-09-15 15:29:42 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-09-15 15:29:42 +0000 |
commit | 887598b92f28d69141b0091d09998672c07e131c (patch) | |
tree | 82d424164ca7e906c477de1cf3bb2c359a837df6 /gcc | |
parent | af472f5931920b821d2e483749563c902424096c (diff) | |
parent | 04549bf8c34cdb3ea435d8542f2cac6d46bcd30f (diff) | |
download | gcc-887598b92f28d69141b0091d09998672c07e131c.zip gcc-887598b92f28d69141b0091d09998672c07e131c.tar.gz gcc-887598b92f28d69141b0091d09998672c07e131c.tar.bz2 |
Merge #679
679: Fix bug when calling method from generic reciever type-bound r=philberty a=philberty
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
Co-authored-by: Philip Herron <philip.herron@embecosm.com>
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 +} |