diff options
author | Philip Herron <herron.philip@googlemail.com> | 2023-06-13 19:14:27 +0100 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2023-06-14 08:26:31 +0000 |
commit | c84e7d9db2d33b7684b0a6b4b3ab9d5540adac27 (patch) | |
tree | 9ed80010d9c2beb09c200f1ef5104532780ed00c | |
parent | c021eef8aa73cc0a3a4e992018cab414a17db4c8 (diff) | |
download | gcc-c84e7d9db2d33b7684b0a6b4b3ab9d5540adac27.zip gcc-c84e7d9db2d33b7684b0a6b4b3ab9d5540adac27.tar.gz gcc-c84e7d9db2d33b7684b0a6b4b3ab9d5540adac27.tar.bz2 |
gccrs: fortify resolve_method_address to match the types
Fixes #2019
gcc/rust/ChangeLog:
* backend/rust-compile-base.cc (HIRCompileBase::resolve_method_address):
match the fntype to the candidate
gcc/testsuite/ChangeLog:
* rust/compile/issue-2019-2.rs: New test.
* rust/compile/issue-2019-3.rs: New test.
Signed-off-by: Philip Herron <herron.philip@googlemail.com>
-rw-r--r-- | gcc/rust/backend/rust-compile-base.cc | 49 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/issue-2019-2.rs | 30 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/issue-2019-3.rs | 59 |
3 files changed, 132 insertions, 6 deletions
diff --git a/gcc/rust/backend/rust-compile-base.cc b/gcc/rust/backend/rust-compile-base.cc index caa10ed..988c675 100644 --- a/gcc/rust/backend/rust-compile-base.cc +++ b/gcc/rust/backend/rust-compile-base.cc @@ -770,6 +770,10 @@ HIRCompileBase::resolve_method_address (TyTy::FnType *fntype, TyTy::BaseType *receiver, Location expr_locus) { + rust_debug_loc (expr_locus, "resolve_method_address for %s and receiver %s", + fntype->debug_str ().c_str (), + receiver->debug_str ().c_str ()); + DefId id = fntype->get_id (); rust_assert (id != UNKNOWN_DEFID); @@ -823,13 +827,46 @@ HIRCompileBase::resolve_method_address (TyTy::FnType *fntype, ctx, fntype, true, expr_locus); } - // 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 + const Resolver::PathProbeCandidate *selectedCandidate = nullptr; + rust_debug_loc (expr_locus, "resolved to %lu candidates", candidates.size ()); + + // filter for the possible case of non fn type items + std::set<Resolver::PathProbeCandidate> filteredFunctionCandidates; + for (auto &candidate : candidates) + { + bool is_fntype = candidate.ty->get_kind () == TyTy::TypeKind::FNDEF; + if (!is_fntype) + continue; + + filteredFunctionCandidates.insert (candidate); + } + + // look for the exact fntype + for (auto &candidate : filteredFunctionCandidates) + { + bool compatable + = Resolver::types_compatable (TyTy::TyWithLocation (candidate.ty), + TyTy::TyWithLocation (fntype), expr_locus, + false); + + rust_debug_loc (candidate.locus, "candidate: %s vs %s compatable=%s", + candidate.ty->debug_str ().c_str (), + fntype->debug_str ().c_str (), + compatable ? "true" : "false"); + + if (compatable) + { + selectedCandidate = &candidate; + break; + } + } + + // FIXME eventually this should just return error mark node when we support + // going through all the passes + rust_assert (selectedCandidate != nullptr); - rust_assert (candidates.size () == 1); - auto &candidate = *candidates.begin (); + // lets compile it + const Resolver::PathProbeCandidate &candidate = *selectedCandidate; rust_assert (candidate.is_impl_candidate ()); rust_assert (candidate.ty->get_kind () == TyTy::TypeKind::FNDEF); TyTy::FnType *candidate_call = static_cast<TyTy::FnType *> (candidate.ty); diff --git a/gcc/testsuite/rust/compile/issue-2019-2.rs b/gcc/testsuite/rust/compile/issue-2019-2.rs new file mode 100644 index 0000000..37c8e30 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2019-2.rs @@ -0,0 +1,30 @@ +#[lang = "add"] +pub trait Add<RHS = Self> { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +impl Add for u32 { + type Output = u32; + + fn add(self, other: u32) -> u32 { + self + other + } +} + +impl<'a> Add<u32> for &'a u32 { + type Output = <u32 as Add<u32>>::Output; + + fn add(self, other: u32) -> <u32 as Add<u32>>::Output { + Add::add(*self, other) + } +} + +impl<'a> Add<&'a u32> for u32 { + type Output = <u32 as Add<u32>>::Output; + + fn add(self, other: &'a u32) -> <u32 as Add<u32>>::Output { + Add::add(self, *other) + } +} diff --git a/gcc/testsuite/rust/compile/issue-2019-3.rs b/gcc/testsuite/rust/compile/issue-2019-3.rs new file mode 100644 index 0000000..6789038 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-2019-3.rs @@ -0,0 +1,59 @@ +macro_rules! forward_ref_binop { + (impl $imp:ident, $method:ident for $t:ty, $u:ty) => { + forward_ref_binop!(impl $imp, $method for $t, $u, + #[stable(feature = "rust1", since = "1.0.0")]); + }; + (impl $imp:ident, $method:ident for $t:ty, $u:ty, #[$attr:meta]) => { + #[$attr] + impl<'a> $imp<$u> for &'a $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, other) + } + } + + #[$attr] + impl<'a> $imp<&'a $u> for $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(self, *other) + } + } + + #[$attr] + impl<'a, 'b> $imp<&'a $u> for &'b $t { + type Output = <$t as $imp<$u>>::Output; + + #[inline] + fn $method(self, other: &'a $u) -> <$t as $imp<$u>>::Output { + $imp::$method(*self, *other) + } + } + } +} + +#[lang = "add"] +pub trait Add<RHS = Self> { + type Output; + + fn add(self, rhs: RHS) -> Self::Output; +} + +macro_rules! add_impl { + ($($t:ty)*) => ($( + #[stable(feature = "rust1", since = "1.0.0")] + impl Add for $t { + type Output = $t; + + fn add(self, other: $t) -> $t { self + other } + } + + forward_ref_binop! { impl Add, add for $t, $t } + )*) +} + +add_impl! { usize u8 u16 u32 u64 /*u128*/ isize i8 i16 i32 i64 /*i128*/ f32 f64 } |