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

commit r17-4341-gbf37e8d84699096e9d184f14adfbf6ecf372577a
Author: Philip Herron <[email protected]>
Date:   Mon Sep 7 22:08:32 2026 +0100

    gccrs: Stop method selection when we hit generic params
    
    Generics like this need to match directly via their associated type bound
    predicates which will already be checked. Otherwise the unify machinery for
    types_compatable will wrongly match by injecting infer_vars.
    
    Fixes Rust-GCC/gccrs#4859
    
    gcc/rust/ChangeLog:
    
            * typecheck/rust-hir-dot-operator.cc (MethodResolver::select): stop 
on ParamTypes
    
    gcc/testsuite/ChangeLog:
    
            * rust/compile/issue-4859.rs: New test.
    
    Signed-off-by: Philip Herron <[email protected]>

Diff:
---
 gcc/rust/typecheck/rust-hir-dot-operator.cc |  5 +++++
 gcc/testsuite/rust/compile/issue-4859.rs    | 35 +++++++++++++++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/gcc/rust/typecheck/rust-hir-dot-operator.cc 
b/gcc/rust/typecheck/rust-hir-dot-operator.cc
index 8fd7f1d0093d..06d9aa88ecb5 100644
--- a/gcc/rust/typecheck/rust-hir-dot-operator.cc
+++ b/gcc/rust/typecheck/rust-hir-dot-operator.cc
@@ -482,6 +482,11 @@ MethodResolver::select (TyTy::BaseType &receiver)
   if (try_select_predicate_candidates (receiver))
     return true;
 
+  // A receiver that is still a bare unresolved generic type parameter can only
+  // ever satisfy a method through its own trait bounds
+  if (receiver.destructure ()->get_kind () == TyTy::TypeKind::PARAM)
+    return false;
+
   // Assemble candidates
   std::vector<impl_item_candidate> inherent_impl_fns;
   if (specified_trait == nullptr)
diff --git a/gcc/testsuite/rust/compile/issue-4859.rs 
b/gcc/testsuite/rust/compile/issue-4859.rs
new file mode 100644
index 000000000000..0be1db8e915a
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-4859.rs
@@ -0,0 +1,35 @@
+#![feature(no_core, lang_items)]
+#![no_core]
+#[lang = "sized"]
+pub trait Sized {}
+#[lang = "deref"]
+pub trait Deref {
+    type Target: ?Sized;
+    fn deref(&self) -> &Self::Target;
+}
+pub struct VaList {
+    pub inner: i32,
+}
+impl Deref for VaList {
+    type Target = i32;
+    fn deref(&self) -> &i32 {
+        &self.inner
+    }
+}
+pub struct Pin<P> {
+    pub pointer: P,
+}
+impl<P: Deref> Pin<P> {
+    pub const unsafe fn new_unchecked(pointer: P) -> Pin<P> {
+        Pin { pointer }
+    }
+    pub fn as_ref(&self) -> Pin<&P::Target> {
+        unsafe { Pin::new_unchecked(&*self.pointer) }
+    }
+}
+impl<T: ?Sized> Deref for &T {
+    type Target = T;
+    fn deref(&self) -> &T {
+        *self
+    }
+}

Reply via email to