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 + } +}
