]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
gccrs: fortify resolve_method_address to match the types
authorPhilip Herron <herron.philip@googlemail.com>
Tue, 13 Jun 2023 18:14:27 +0000 (19:14 +0100)
committerArthur Cohen <arthur.cohen@embecosm.com>
Tue, 16 Jan 2024 17:46:27 +0000 (18:46 +0100)
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>
gcc/rust/backend/rust-compile-base.cc
gcc/testsuite/rust/compile/issue-2019-2.rs [new file with mode: 0644]
gcc/testsuite/rust/compile/issue-2019-3.rs [new file with mode: 0644]

index f034b8c7b0a40b9869ffd2ffbc1942e306fcb671..4a95530f1488a9eb21c61d345598e8cdbbdd693c 100644 (file)
@@ -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 (file)
index 0000000..37c8e30
--- /dev/null
@@ -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 (file)
index 0000000..6789038
--- /dev/null
@@ -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 }