https://gcc.gnu.org/g:ff51c40ed910394c622d971e0cd97d26b3a55d14
commit r17-4337-gff51c40ed910394c622d971e0cd97d26b3a55d14 Author: Philip Herron <[email protected]> Date: Sun Sep 6 22:00:56 2026 +0100 gccrs: Handle generic args to traits in paths Fixes Rust-GCC/gccrs#4853 gcc/rust/ChangeLog: * typecheck/rust-substitution-mapper.cc (SubstMapper::valid_type): check for dyn object (SubstMapper::visit): substitution on it * typecheck/rust-substitution-mapper.h: add impl gcc/testsuite/ChangeLog: * rust/compile/issue-4853.rs: New test. Signed-off-by: Philip Herron <[email protected]> Diff: --- gcc/rust/typecheck/rust-substitution-mapper.cc | 24 ++++++++++++++++++++++++ gcc/rust/typecheck/rust-substitution-mapper.h | 2 +- gcc/testsuite/rust/compile/issue-4853.rs | 25 +++++++++++++++++++++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/gcc/rust/typecheck/rust-substitution-mapper.cc b/gcc/rust/typecheck/rust-substitution-mapper.cc index 579c88c4dae7..e08356c2b653 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.cc +++ b/gcc/rust/typecheck/rust-substitution-mapper.cc @@ -63,6 +63,14 @@ SubstMapper::valid_type (TyTy::BaseType *base) bool is_placeholder = base->is<TyTy::PlaceholderType> (); bool is_projection = base->is<TyTy::ProjectionType> (); + // see gcc/testsuite/rust/compile/issue-4853.rs + if (auto *dyn = base->try_as<TyTy::DynamicObjectType> ()) + { + auto &bounds = dyn->get_specified_bounds (); + if (bounds.size () == 1) + return bounds.at (0).requires_generic_args (); + } + return is_fn || is_adt || is_placeholder || is_projection; } @@ -120,6 +128,22 @@ SubstMapper::visit (TyTy::ADTType &type) resolved = concrete; } +void +SubstMapper::visit (TyTy::DynamicObjectType &type) +{ + rust_assert (have_generic_args ()); + rust_assert (type.get_specified_bounds ().size () == 1); + rust_assert (type.get_specified_bounds ().at (0).requires_generic_args ()); + + TyTy::TypeBoundPredicate predicate = type.get_specified_bounds ().at (0); + predicate.apply_generic_arguments (generics, false, false); + if (predicate.is_error ()) + return; + + resolved = new TyTy::DynamicObjectType (type.get_ref (), type.get_ident (), + {predicate}); +} + void SubstMapper::visit (TyTy::PlaceholderType &type) { diff --git a/gcc/rust/typecheck/rust-substitution-mapper.h b/gcc/rust/typecheck/rust-substitution-mapper.h index 73632ddf2b5d..fefab0c578a0 100644 --- a/gcc/rust/typecheck/rust-substitution-mapper.h +++ b/gcc/rust/typecheck/rust-substitution-mapper.h @@ -43,6 +43,7 @@ public: void visit (TyTy::ADTType &type) override; void visit (TyTy::PlaceholderType &type) override; void visit (TyTy::ProjectionType &type) override; + void visit (TyTy::DynamicObjectType &type) override; // nothing to do for these void visit (TyTy::InferType &) override { rust_unreachable (); } @@ -67,7 +68,6 @@ public: void visit (TyTy::ConstErrorType &) override { rust_unreachable (); } void visit (TyTy::StrType &) override { rust_unreachable (); } void visit (TyTy::NeverType &) override { rust_unreachable (); } - void visit (TyTy::DynamicObjectType &) override { rust_unreachable (); } void visit (TyTy::ClosureType &) override { rust_unreachable (); } void visit (TyTy::OpaqueType &) override { rust_unreachable (); } diff --git a/gcc/testsuite/rust/compile/issue-4853.rs b/gcc/testsuite/rust/compile/issue-4853.rs new file mode 100644 index 000000000000..45de755edda7 --- /dev/null +++ b/gcc/testsuite/rust/compile/issue-4853.rs @@ -0,0 +1,25 @@ +// { dg-additional-options "-frust-edition=2018" } +#![feature(lang_items, no_core)] +#![no_core] + +#[lang = "sized"] +trait Sized {} + +trait FloatToInt<Int>: Sized { + unsafe fn to_int_unchecked(self) -> Int; +} + +impl FloatToInt<u32> for f32 { + unsafe fn to_int_unchecked(self) -> u32 { + 0 + } +} + +impl f32 { + pub unsafe fn to_int_unchecked<Int>(self) -> Int + where + Self: FloatToInt<Int>, + { + unsafe { FloatToInt::<Int>::to_int_unchecked(self) } + } +}
