aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/typecheck/rust-hir-path-probe.h11
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.cc2
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc50
-rw-r--r--gcc/rust/typecheck/rust-tyty.h6
-rw-r--r--gcc/testsuite/rust/execute/torture/trait6.rs41
-rw-r--r--gcc/testsuite/rust/execute/torture/trait7.rs41
6 files changed, 145 insertions, 6 deletions
diff --git a/gcc/rust/typecheck/rust-hir-path-probe.h b/gcc/rust/typecheck/rust-hir-path-probe.h
index dd51f83..d2b5f5b 100644
--- a/gcc/rust/typecheck/rust-hir-path-probe.h
+++ b/gcc/rust/typecheck/rust-hir-path-probe.h
@@ -276,7 +276,16 @@ protected:
TyTy::BaseType *trait_item_tyty = trait_item_ref->get_tyty ();
- if (impl != nullptr)
+ // we cannot auto setup associated type mappings when our receiver is a
+ // generic type bound
+ const TyTy::BaseType *root = receiver->get_root ();
+ bool receiver_is_type_param
+ = root->get_kind () == TyTy::TypeKind::PARAM;
+ bool receiver_is_dyn = root->get_kind () == TyTy::TypeKind::DYNAMIC;
+ bool receiver_is_generic = receiver_is_type_param || receiver_is_dyn;
+
+ if (impl != nullptr && !receiver_is_generic)
+
{
HirId impl_block_id = impl->get_mappings ().get_hirid ();
AssociatedImplTrait *lookup_associated = nullptr;
diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.cc b/gcc/rust/typecheck/rust-hir-type-check-type.cc
index a479581..ed21d53 100644
--- a/gcc/rust/typecheck/rust-hir-type-check-type.cc
+++ b/gcc/rust/typecheck/rust-hir-type-check-type.cc
@@ -445,7 +445,7 @@ TypeCheckType::resolve_segments (
// lookup the associated-impl-trait
HIR::ImplBlock *impl = candidate.item.trait.impl;
- if (impl != nullptr)
+ if (impl != nullptr && !reciever_is_generic)
{
AssociatedImplTrait *lookup_associated = nullptr;
bool found_impl_trait = context->lookup_associated_trait_impl (
diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc
index f2216f9..1e7c87e 100644
--- a/gcc/rust/typecheck/rust-tyty.cc
+++ b/gcc/rust/typecheck/rust-tyty.cc
@@ -331,9 +331,11 @@ StructFieldType::clone () const
get_field_type ()->clone ());
}
-void
+bool
SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus)
{
+ auto context = Resolver::TypeCheckContext::get ();
+
if (type.get_kind () == TyTy::TypeKind::INFER)
{
type.inherit_bounds (*param);
@@ -341,7 +343,7 @@ SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus)
else
{
if (!param->bounds_compatible (type, locus, true))
- return;
+ return false;
}
if (type.get_kind () == TypeKind::PARAM)
@@ -351,8 +353,52 @@ SubstitutionParamMapping::fill_param_ty (BaseType &type, Location locus)
}
else
{
+ // check the substitution is compatible with bounds
+ if (!param->bounds_compatible (type, locus, true))
+ return false;
+
+ // setup any associated type mappings for the specified bonds and this
+ // type
+ auto candidates = Resolver::TypeBoundsProbe::Probe (&type);
+ for (auto &specified_bound : param->get_specified_bounds ())
+ {
+ const Resolver::TraitReference *specified_bound_ref
+ = specified_bound.get ();
+
+ // since the bounds_compatible check has occurred we should be able to
+ // assert on finding the trait references
+ HirId associated_impl_block_id = UNKNOWN_HIRID;
+ bool found = false;
+ for (auto &bound : candidates)
+ {
+ const Resolver::TraitReference *bound_trait_ref = bound.first;
+ const HIR::ImplBlock *associated_impl = bound.second;
+
+ found = specified_bound_ref->is_equal (*bound_trait_ref);
+ if (found)
+ {
+ rust_assert (associated_impl != nullptr);
+ associated_impl_block_id
+ = associated_impl->get_mappings ().get_hirid ();
+ break;
+ }
+ }
+
+ if (found && associated_impl_block_id != UNKNOWN_HIRID)
+ {
+ Resolver::AssociatedImplTrait *lookup_associated = nullptr;
+ bool found_impl_trait = context->lookup_associated_trait_impl (
+ associated_impl_block_id, &lookup_associated);
+
+ if (found_impl_trait)
+ lookup_associated->setup_associated_types ();
+ }
+ }
+
param->set_ty_ref (type.get_ref ());
}
+
+ return true;
}
void
diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h
index 054e327..f6a2797 100644
--- a/gcc/rust/typecheck/rust-tyty.h
+++ b/gcc/rust/typecheck/rust-tyty.h
@@ -626,7 +626,7 @@ public:
std::string as_string () const { return param->as_string (); }
- void fill_param_ty (BaseType &type, Location locus);
+ bool fill_param_ty (BaseType &type, Location locus);
SubstitutionParamMapping clone () const
{
@@ -1812,7 +1812,9 @@ public:
bool contains_type_parameters () const override
{
- rust_assert (can_resolve ());
+ if (!can_resolve ())
+ return false;
+
return resolve ()->contains_type_parameters ();
}
diff --git a/gcc/testsuite/rust/execute/torture/trait6.rs b/gcc/testsuite/rust/execute/torture/trait6.rs
new file mode 100644
index 0000000..54023d2
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait6.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+ type A;
+
+ fn bar(self) -> Self::A;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+struct S(i32);
+impl Foo for S {
+ type A = i32;
+
+ fn bar(self) -> Self::A {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ self.0
+ }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+ x.bar()
+}
+
+fn main() -> i32 {
+ let a;
+ a = S(123);
+
+ let bar: i32 = test_bar::<S>(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}
diff --git a/gcc/testsuite/rust/execute/torture/trait7.rs b/gcc/testsuite/rust/execute/torture/trait7.rs
new file mode 100644
index 0000000..059ba15
--- /dev/null
+++ b/gcc/testsuite/rust/execute/torture/trait7.rs
@@ -0,0 +1,41 @@
+/* { dg-output "123\n" } */
+extern "C" {
+ fn printf(s: *const i8, ...);
+}
+
+pub trait Foo {
+ type A;
+
+ fn bar(self) -> Self::A;
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+}
+
+struct S(i32);
+impl Foo for S {
+ type A = i32;
+
+ fn bar(self) -> Self::A {
+ // { dg-warning "unused name" "" { target *-*-* } .-1 }
+ self.0
+ }
+}
+
+fn test_bar<T: Foo>(x: T) -> T::A {
+ x.bar()
+}
+
+fn main() -> i32 {
+ let a;
+ a = S(123);
+
+ let bar: i32 = test_bar(a);
+ unsafe {
+ let a = "%i\n\0";
+ let b = a as *const str;
+ let c = b as *const i8;
+
+ printf(c, bar);
+ }
+
+ 0
+}