https://gcc.gnu.org/g:c5ae11b632a081650be2dbaa6f1a9f30233aef04

commit c5ae11b632a081650be2dbaa6f1a9f30233aef04
Author: Philip Herron <herron.phi...@googlemail.com>
Date:   Fri Nov 1 14:07:54 2024 +0000

    gccrs: add test case to show method resolution is working
    
    The issue here was that the impl block for Cell<T> defines that T must have
    the bound of Copy implemented. But simultaneously if you do an deref
    you get direct access to the unsafe cell which also defines a get method
    so these are two valid ways of accessing the method in question but
    when Copy is implementet the simplest case is prefered so it does resolve
    to Cell<T>::get.
    
    Fixes #3033
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/nr2/exclude: nr can't handle this
            * rust/compile/issue-3033.rs: New test.
    
    Signed-off-by: Philip Herron <herron.phi...@googlemail.com>

Diff:
---
 gcc/testsuite/rust/compile/issue-3033.rs | 144 +++++++++++++++++++++++++++++++
 gcc/testsuite/rust/compile/nr2/exclude   |   1 +
 2 files changed, 145 insertions(+)

diff --git a/gcc/testsuite/rust/compile/issue-3033.rs 
b/gcc/testsuite/rust/compile/issue-3033.rs
new file mode 100644
index 000000000000..9085b7616c0d
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-3033.rs
@@ -0,0 +1,144 @@
+#![feature(negative_impls)]
+
+#[lang = "copy"]
+trait Copy {}
+
+mod copy_impls {
+    use super::Copy;
+
+    macro_rules! impl_copy {
+        ($($t:ty)*) => {
+            $(
+                impl Copy for $t {}
+            )*
+        }
+    }
+
+    impl_copy! {
+        usize u8 u16 u32 u64 // u128
+        isize i8 i16 i32 i64 // i128
+        f32 f64
+        bool char
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[repr(transparent)]
+#[repr(no_niche)] // rust-lang/rust#68303.
+pub struct UnsafeCell<T: ?Sized> {
+    value: T,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl<T: ?Sized> UnsafeCell<T> {
+    /// Gets a mutable pointer to the wrapped value.
+    ///
+    /// This can be cast to a pointer of any kind.
+    /// Ensure that the access is unique (no active references, mutable or not)
+    /// when casting to `&mut T`, and ensure that there are no mutations
+    /// or mutable aliases going on when casting to `&T`
+    ///
+    /// # Examples
+    ///
+    ///
+    /// use std::cell::UnsafeCell;
+    ///
+    /// let uc = UnsafeCell::new(5);
+    ///
+    /// let five = uc.get();
+    ///
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    // #[rustc_const_stable(feature = "const_unsafecell_get", since = 
"1.32.0")]
+    pub const fn get(&self) -> *mut T {
+        // We can just cast the pointer from `UnsafeCell<T>` to `T` because of
+        // #[repr(transparent)]. This exploits libstd's special status, there 
is
+        // no guarantee for user code that this will work in future versions 
of the compiler!
+        self as *const UnsafeCell<T> as *const T as *mut T
+    }
+}
+
+#[stable(feature = "rust1", since = "1.0.0")]
+#[repr(transparent)]
+pub struct Cell<T: ?Sized> {
+    value: UnsafeCell<T>,
+    // { dg-warning "field is never read" "" { target *-*-* } .-1 }
+}
+
+impl<T: Copy> Cell<T> {
+    /// Returns a copy of the contained value.
+    ///
+    /// # Examples
+    ///
+    ///
+    /// use std::cell::Cell;
+    ///
+    /// let c = Cell::new(5);
+    ///
+    /// let five = c.get();
+    ///
+    #[inline]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    pub fn get(&self) -> T {
+        // SAFETY: This can cause data races if called from a separate thread,
+        // but `Cell` is `!Sync` so this won't happen.
+        unsafe { *self.value.get() }
+    }
+}
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "deref"]
+pub trait Deref {
+    /// The resulting type after dereferencing.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    // #[rustc_diagnostic_item = "deref_target"]
+    type Target: ?Sized;
+
+    /// Dereferences the value.
+    #[must_use]
+    #[stable(feature = "rust1", since = "1.0.0")]
+    // #[rustc_diagnostic_item = "deref_method"]
+    fn deref(&self) -> &Self::Target;
+}
+
+impl<T: ?Sized> Deref for &T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+// this is added because of #3030
+extern "C" {
+    fn never() -> !;
+}
+
+impl<T: ?Sized> !DerefMut for &T {
+    fn deref_mut(&mut self) -> &mut T {
+        unsafe { never() }
+    }
+}
+
+impl<T: ?Sized> Deref for &mut T {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        *self
+    }
+}
+
+#[lang = "deref_mut"]
+pub trait DerefMut: Deref {
+    /// Mutably dereferences the value.
+    #[stable(feature = "rust1", since = "1.0.0")]
+    fn deref_mut(&mut self) -> &mut Self::Target;
+}
+
+#[inline]
+pub fn new<'b>(borrow: &'b Cell<i32>) {
+    let b = borrow.get();
+    // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
diff --git a/gcc/testsuite/rust/compile/nr2/exclude 
b/gcc/testsuite/rust/compile/nr2/exclude
index b4799edd4f5b..ceada8bc51a6 100644
--- a/gcc/testsuite/rust/compile/nr2/exclude
+++ b/gcc/testsuite/rust/compile/nr2/exclude
@@ -220,4 +220,5 @@ issue-3032-2.rs
 # https://github.com/Rust-GCC/gccrs/issues/3189
 if_let_expr_simple.rs
 iflet.rs
+issue-3033.rs
 # please don't delete the trailing newline

Reply via email to