From: Philip Herron <[email protected]>
The parser only recognized Foo<Bar = T> for the generic type bindings
syntax. This parses both flavours now into update generic args type.
Fixes Rust-GCC/gccrs#1726
gcc/rust/ChangeLog:
* ast/rust-path.cc (GenericArgsBinding::as_string): new format
* ast/rust-path.h (struct GenericArgsBinding): new kinds for bindings
* hir/rust-ast-lower-base.cc (ASTLoweringBase::lower_binding): new
* hir/tree/rust-hir-path.cc (GenericArgsBinding::GenericArgsBinding):
likewise
(GenericArgsBinding::operator=): likewise
* hir/tree/rust-hir-path.h (class GenericArgsBinding): likewise
* hir/tree/rust-hir.cc (GenericArgsBinding::to_string): likewise
* parse/rust-parse-impl.hxx: peek for both types
* typecheck/rust-type-util.cc (normalize_projection): track constrains
* typecheck/rust-tyty-bounds.cc
(TypeBoundPredicate::TypeBoundPredicate): new ctor
(TypeBoundPredicate::operator=): likewise
* typecheck/rust-tyty-subst.cc
(SubstitutionArgumentMappings::get_constraint_args): new
* typecheck/rust-tyty-subst.h: new
* typecheck/rust-unify.cc (UnifyRules::expect_projection): fix loop
gcc/testsuite/ChangeLog:
* rust/compile/associated-type-bound.rs: New test.
* rust/compile/issue-1726-1.rs: New test.
* rust/compile/issue-1726-2.rs: New test.
Signed-off-by: Philip Herron <[email protected]>
---
This change was merged into the gccrs repository and is posted here for
upstream visibility and potential drive-by review, as requested by GCC
release managers.
Each commit email contains a link to its details on github from where you can
find the Pull-Request and associated discussions.
Commit on github:
https://github.com/Rust-GCC/gccrs/commit/f3d78219fefeb918ca3f11e56e77c3deff119cb8
The commit has been mentioned in the following issue(s):
- Rust-GCC/gccrs#1726: https://github.com/Rust-GCC/gccrs/issues/1726
The commit has been mentioned in the following pull-request(s):
- https://github.com/Rust-GCC/gccrs/pull/4843
gcc/rust/ast/rust-path.cc | 5 +-
gcc/rust/ast/rust-path.h | 20 ++++++--
gcc/rust/hir/rust-ast-lower-base.cc | 13 ++++-
gcc/rust/hir/tree/rust-hir-path.cc | 8 +--
gcc/rust/hir/tree/rust-hir-path.h | 13 ++++-
gcc/rust/hir/tree/rust-hir.cc | 4 +-
gcc/rust/parse/rust-parse-impl.hxx | 18 +++++--
gcc/rust/typecheck/rust-type-util.cc | 18 +++++++
gcc/rust/typecheck/rust-tyty-bounds.cc | 18 +++----
gcc/rust/typecheck/rust-tyty-subst.cc | 49 ++++++++++++------
gcc/rust/typecheck/rust-tyty-subst.h | 15 +++---
gcc/rust/typecheck/rust-unify.cc | 6 +++
.../rust/compile/associated-type-bound.rs | 50 +++++++++++++++++++
gcc/testsuite/rust/compile/issue-1726-1.rs | 17 +++++++
gcc/testsuite/rust/compile/issue-1726-2.rs | 42 ++++++++++++++++
15 files changed, 248 insertions(+), 48 deletions(-)
create mode 100644 gcc/testsuite/rust/compile/associated-type-bound.rs
create mode 100644 gcc/testsuite/rust/compile/issue-1726-1.rs
create mode 100644 gcc/testsuite/rust/compile/issue-1726-2.rs
diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc
index 5260adc8a..e8b885cbc 100644
--- a/gcc/rust/ast/rust-path.cc
+++ b/gcc/rust/ast/rust-path.cc
@@ -108,8 +108,9 @@ GenericArg::disambiguate_to_type () const
std::string
GenericArgsBinding::as_string () const
{
- // TODO: rewrite to work with non-literalisable types
- return identifier.as_string () + " = " + type->as_string ();
+ auto type_string = type->as_string ();
+ auto separator = kind == Kind::Constraint ? " : " : " = ";
+ return identifier.as_string () + separator + type_string;
}
std::string
diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h
index 3ce7ed7ef..ecb156e90 100644
--- a/gcc/rust/ast/rust-path.h
+++ b/gcc/rust/ast/rust-path.h
@@ -71,10 +71,18 @@ public:
// A binding of an identifier to a type used in generic arguments in paths
struct GenericArgsBinding
{
+public:
+ enum class Kind
+ {
+ Equality,
+ Constraint
+ };
+
private:
Identifier identifier;
std::unique_ptr<Type> type;
location_t locus;
+ Kind kind;
public:
// Returns whether binding is in an error state.
@@ -90,7 +98,7 @@ public:
if (type)
new_type = type->reconstruct ();
- return GenericArgsBinding (identifier, std::move (new_type), locus);
+ return GenericArgsBinding (identifier, std::move (new_type), locus, kind);
}
// Creates an error state generic args binding.
@@ -101,13 +109,15 @@ public:
// Pointer type for type in constructor to enable polymorphism
GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
- location_t locus = UNDEF_LOCATION)
- : identifier (std::move (ident)), type (std::move (type_ptr)), locus
(locus)
+ location_t locus = UNDEF_LOCATION,
+ Kind kind = Kind::Equality)
+ : identifier (std::move (ident)), type (std::move (type_ptr)),
+ locus (locus), kind (kind)
{}
// Copy constructor has to deep copy the type as it is a unique pointer
GenericArgsBinding (GenericArgsBinding const &other)
- : identifier (other.identifier), locus (other.locus)
+ : identifier (other.identifier), locus (other.locus), kind (other.kind)
{
// guard to protect from null pointer dereference
if (other.type != nullptr)
@@ -122,6 +132,7 @@ public:
{
identifier = other.identifier;
locus = other.locus;
+ kind = other.kind;
// guard to protect from null pointer dereference
if (other.type != nullptr)
@@ -154,6 +165,7 @@ public:
location_t get_locus () const { return locus; }
Identifier get_identifier () const { return identifier; }
+ Kind get_kind () const { return kind; }
};
/* Class representing a const generic application */
diff --git a/gcc/rust/hir/rust-ast-lower-base.cc
b/gcc/rust/hir/rust-ast-lower-base.cc
index a4ab5d5ed..33b1c2f51 100644
--- a/gcc/rust/hir/rust-ast-lower-base.cc
+++ b/gcc/rust/hir/rust-ast-lower-base.cc
@@ -651,10 +651,19 @@ ASTLoweringBase::lower_path_expr_seg
(AST::PathExprSegment &s)
HIR::GenericArgsBinding
ASTLoweringBase::lower_binding (AST::GenericArgsBinding &binding)
{
- HIR::Type *lowered_type = ASTLoweringType::translate (binding.get_type ());
+ auto impl_trait_allowed
+ = binding.get_kind () == AST::GenericArgsBinding::Kind::Constraint
+ ? ASTLoweringType::ImplTrait::Allow
+ : ASTLoweringType::ImplTrait::Forbid;
+ HIR::Type *lowered_type
+ = ASTLoweringType::translate (binding.get_type (), false,
+ impl_trait_allowed);
+ auto kind = binding.get_kind () == AST::GenericArgsBinding::Kind::Constraint
+ ? HIR::GenericArgsBinding::Kind::Constraint
+ : HIR::GenericArgsBinding::Kind::Equality;
return HIR::GenericArgsBinding (binding.get_identifier (),
std::unique_ptr<HIR::Type> (lowered_type),
- binding.get_locus ());
+ binding.get_locus (), kind);
}
HIR::GenericArgs
diff --git a/gcc/rust/hir/tree/rust-hir-path.cc
b/gcc/rust/hir/tree/rust-hir-path.cc
index b887d0e07..1c1117f93 100644
--- a/gcc/rust/hir/tree/rust-hir-path.cc
+++ b/gcc/rust/hir/tree/rust-hir-path.cc
@@ -25,13 +25,14 @@ namespace HIR {
GenericArgsBinding::GenericArgsBinding (Identifier ident,
std::unique_ptr<Type> type_ptr,
- location_t locus)
- : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus)
+ location_t locus, Kind kind)
+ : identifier (std::move (ident)), type (std::move (type_ptr)), locus (locus),
+ kind (kind)
{}
GenericArgsBinding::GenericArgsBinding (GenericArgsBinding const &other)
: identifier (other.identifier), type (other.type->clone_type ()),
- locus (other.locus)
+ locus (other.locus), kind (other.kind)
{}
GenericArgsBinding &
@@ -40,6 +41,7 @@ GenericArgsBinding::operator= (GenericArgsBinding const
&other)
identifier = other.identifier;
type = other.type->clone_type ();
locus = other.locus;
+ kind = other.kind;
return *this;
}
diff --git a/gcc/rust/hir/tree/rust-hir-path.h
b/gcc/rust/hir/tree/rust-hir-path.h
index c6b3cbfab..b9de6b90b 100644
--- a/gcc/rust/hir/tree/rust-hir-path.h
+++ b/gcc/rust/hir/tree/rust-hir-path.h
@@ -63,10 +63,19 @@ public:
// A binding of an identifier to a type used in generic arguments in paths
class GenericArgsBinding
{
+public:
+ enum class Kind
+ {
+ Equality,
+ Constraint
+ };
+
+private:
Identifier identifier;
std::unique_ptr<Type> type;
location_t locus;
+ Kind kind;
public:
// Returns whether binding is in an error state.
@@ -84,7 +93,8 @@ public:
// Pointer type for type in constructor to enable polymorphism
GenericArgsBinding (Identifier ident, std::unique_ptr<Type> type_ptr,
- location_t locus = UNDEF_LOCATION);
+ location_t locus = UNDEF_LOCATION,
+ Kind kind = Kind::Equality);
// Copy constructor has to deep copy the type as it is a unique pointer
GenericArgsBinding (GenericArgsBinding const &other);
@@ -116,6 +126,7 @@ public:
}
location_t get_locus () const { return locus; }
+ Kind get_kind () const { return kind; }
};
class ConstGenericArg
diff --git a/gcc/rust/hir/tree/rust-hir.cc b/gcc/rust/hir/tree/rust-hir.cc
index 7d611ed5c..00db9fc64 100644
--- a/gcc/rust/hir/tree/rust-hir.cc
+++ b/gcc/rust/hir/tree/rust-hir.cc
@@ -2387,7 +2387,9 @@ GenericArgs::to_string () const
std::string
GenericArgsBinding::to_string () const
{
- return identifier.as_string () + " = " + type->to_string ();
+ auto type_string = type->to_string ();
+ auto separator = kind == Kind::Constraint ? " : " : " = ";
+ return identifier.as_string () + separator + type_string;
}
std::string
diff --git a/gcc/rust/parse/rust-parse-impl.hxx
b/gcc/rust/parse/rust-parse-impl.hxx
index b5f417685..652f128c6 100644
--- a/gcc/rust/parse/rust-parse-impl.hxx
+++ b/gcc/rust/parse/rust-parse-impl.hxx
@@ -5247,7 +5247,8 @@ Parser<ManagedTokenSource>::parse_path_generic_args ()
// ensure not binding being parsed as type accidently
if (t->get_id () == IDENTIFIER
- && lexer.peek_token (1)->get_id () == EQUAL)
+ && (lexer.peek_token (1)->get_id () == EQUAL
+ || lexer.peek_token (1)->get_id () == COLON))
break;
auto arg = parse_generic_arg ();
@@ -5324,12 +5325,21 @@ Parser<ManagedTokenSource>::parse_generic_args_binding
()
lexer.skip_token ();
Identifier ident{ident_tok};
- if (!skip_token (EQUAL))
+ if (lexer.peek_token ()->get_id () == COLON)
{
- // skip after somewhere?
- return AST::GenericArgsBinding::create_error ();
+ lexer.skip_token ();
+ auto bounds_locus = lexer.peek_token ()->get_locus ();
+ auto bounds = parse_type_param_bounds ();
+ auto type = std::unique_ptr<AST::Type> (
+ new AST::ImplTraitType (std::move (bounds), bounds_locus));
+ return AST::GenericArgsBinding (
+ std::move (ident), std::move (type), ident_tok->get_locus (),
+ AST::GenericArgsBinding::Kind::Constraint);
}
+ if (!skip_token (EQUAL))
+ return AST::GenericArgsBinding::create_error ();
+
// parse type (required)
std::unique_ptr<AST::Type> type = parse_type ();
if (type == nullptr)
diff --git a/gcc/rust/typecheck/rust-type-util.cc
b/gcc/rust/typecheck/rust-type-util.cc
index 21559cb2a..005defb50 100644
--- a/gcc/rust/typecheck/rust-type-util.cc
+++ b/gcc/rust/typecheck/rust-type-util.cc
@@ -679,6 +679,24 @@ normalize_projection (TyTy::ProjectionType *proj,
location_t locus,
auto it = binding.find (assoc_name);
if (it != binding.end ())
return it->second;
+
+ const auto &constraints
+ = bound.get_substitution_arguments ().get_constraint_args ();
+ auto constraint = constraints.find (assoc_name);
+ if (constraint != constraints.end ())
+ {
+ TyTy::BaseType *constrained = proj->clone ();
+ constrained->inherit_bounds (*constraint->second);
+
+ // Keep the constrained projection distinct from the canonical
+ // associated-type declaration.
+ auto &mappings = Analysis::Mappings::get ();
+ HirId fresh = mappings.get_next_hir_id ();
+ constrained->set_ref (fresh);
+ constrained->set_ty_ref (fresh);
+ ctx->insert_implicit_type (fresh, constrained);
+ return constrained;
+ }
}
}
diff --git a/gcc/rust/typecheck/rust-tyty-bounds.cc
b/gcc/rust/typecheck/rust-tyty-bounds.cc
index fca42d61a..5a1e02fe8 100644
--- a/gcc/rust/typecheck/rust-tyty-bounds.cc
+++ b/gcc/rust/typecheck/rust-tyty-bounds.cc
@@ -469,11 +469,10 @@ TypeBoundPredicate::TypeBoundPredicate (const
TypeBoundPredicate &other)
copied_arg_mappings.push_back (std::move (c));
}
- used_arguments
- = SubstitutionArgumentMappings (copied_arg_mappings,
- other.used_arguments.get_binding_args (),
- other.used_arguments.get_regions (),
- other.used_arguments.get_locus ());
+ used_arguments = SubstitutionArgumentMappings (
+ copied_arg_mappings, other.used_arguments.get_binding_args (),
+ other.used_arguments.get_regions (), other.used_arguments.get_locus (),
+ nullptr, false, false, other.used_arguments.get_constraint_args ());
}
TypeBoundPredicate &
@@ -511,11 +510,10 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate
&other)
copied_arg_mappings.emplace_back (&substitutions.at (i++), argument);
}
- used_arguments
- = SubstitutionArgumentMappings (copied_arg_mappings,
- other.used_arguments.get_binding_args (),
- other.used_arguments.get_regions (),
- other.used_arguments.get_locus ());
+ used_arguments = SubstitutionArgumentMappings (
+ copied_arg_mappings, other.used_arguments.get_binding_args (),
+ other.used_arguments.get_regions (), other.used_arguments.get_locus (),
+ nullptr, false, false, other.used_arguments.get_constraint_args ());
super_traits = other.super_traits;
return *this;
diff --git a/gcc/rust/typecheck/rust-tyty-subst.cc
b/gcc/rust/typecheck/rust-tyty-subst.cc
index 46e22288c..bed285eee 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.cc
+++ b/gcc/rust/typecheck/rust-tyty-subst.cc
@@ -336,16 +336,18 @@
SubstitutionArgumentMappings::SubstitutionArgumentMappings (
std::vector<SubstitutionArg> mappings,
std::map<std::string, BaseType *> binding_args, RegionParamList regions,
location_t locus, ParamSubstCb param_subst_cb, bool trait_item_flag,
- bool error_flag)
+ bool error_flag, std::map<std::string, BaseType *> constraint_args)
: mappings (std::move (mappings)), binding_args (binding_args),
- regions (regions), locus (locus), param_subst_cb (param_subst_cb),
- trait_item_flag (trait_item_flag), error_flag (error_flag)
+ constraint_args (constraint_args), regions (regions), locus (locus),
+ param_subst_cb (param_subst_cb), trait_item_flag (trait_item_flag),
+ error_flag (error_flag)
{}
SubstitutionArgumentMappings::SubstitutionArgumentMappings (
const SubstitutionArgumentMappings &other)
: mappings (other.mappings), binding_args (other.binding_args),
- regions (other.regions), locus (other.locus), param_subst_cb (nullptr),
+ constraint_args (other.constraint_args), regions (other.regions),
+ locus (other.locus), param_subst_cb (nullptr),
trait_item_flag (other.trait_item_flag), error_flag (other.error_flag)
{}
@@ -355,6 +357,7 @@ SubstitutionArgumentMappings::operator= (
{
mappings = other.mappings;
binding_args = other.binding_args;
+ constraint_args = other.constraint_args;
regions = other.regions;
locus = other.locus;
param_subst_cb = nullptr;
@@ -476,6 +479,12 @@ SubstitutionArgumentMappings::get_binding_args () const
return binding_args;
}
+const std::map<std::string, BaseType *> &
+SubstitutionArgumentMappings::get_constraint_args () const
+{
+ return constraint_args;
+}
+
std::string
SubstitutionArgumentMappings::as_string () const
{
@@ -685,6 +694,7 @@ SubstitutionRef::get_mappings_from_generic_args (
HIR::GenericArgs &args, const std::vector<Region> ®ions)
{
std::map<std::string, BaseType *> binding_arguments;
+ std::map<std::string, BaseType *> constraint_arguments;
if (args.get_binding_args ().size () > 0)
{
if (supports_associated_bindings ())
@@ -721,8 +731,13 @@ SubstitutionRef::get_mappings_from_generic_args (
return SubstitutionArgumentMappings::error ();
}
- binding_arguments[binding.get_identifier ().as_string ()]
- = resolved;
+ if (binding.get_kind ()
+ == HIR::GenericArgsBinding::Kind::Constraint)
+ constraint_arguments[binding.get_identifier ().as_string ()]
+ = resolved;
+ else
+ binding_arguments[binding.get_identifier ().as_string ()]
+ = resolved;
}
}
else
@@ -945,10 +960,15 @@ SubstitutionRef::get_mappings_from_generic_args (
}
}
- return {mappings, binding_arguments,
+ return {mappings,
+ binding_arguments,
RegionParamList::from_subst (used_arguments.get_regions ().size (),
regions),
- args.get_locus ()};
+ args.get_locus (),
+ nullptr,
+ false,
+ false,
+ constraint_arguments};
}
BaseType *
@@ -1036,12 +1056,10 @@ SubstitutionRef::adjust_mappings_for_this (
if (resolved_mappings.empty ())
return SubstitutionArgumentMappings::error ();
- return SubstitutionArgumentMappings (resolved_mappings,
- mappings.get_binding_args (),
- mappings.get_regions (),
- mappings.get_locus (),
- mappings.get_subst_cb (),
- mappings.trait_item_mode ());
+ return SubstitutionArgumentMappings (
+ resolved_mappings, mappings.get_binding_args (), mappings.get_regions (),
+ mappings.get_locus (), mappings.get_subst_cb (),
+ mappings.trait_item_mode (), false, mappings.get_constraint_args ());
}
bool
@@ -1101,7 +1119,8 @@ SubstitutionRef::solve_mappings_from_receiver_for_self (
return SubstitutionArgumentMappings (resolved_mappings,
mappings.get_binding_args (),
mappings.get_regions (),
- mappings.get_locus ());
+ mappings.get_locus (), nullptr, false,
+ false, mappings.get_constraint_args ());
}
bool
diff --git a/gcc/rust/typecheck/rust-tyty-subst.h
b/gcc/rust/typecheck/rust-tyty-subst.h
index 8a71f8907..947488afb 100644
--- a/gcc/rust/typecheck/rust-tyty-subst.h
+++ b/gcc/rust/typecheck/rust-tyty-subst.h
@@ -175,12 +175,12 @@ typedef std::function<void (const ParamType &, const
SubstitutionArg &)>
class SubstitutionArgumentMappings
{
public:
- SubstitutionArgumentMappings (std::vector<SubstitutionArg> mappings,
- std::map<std::string, BaseType *> binding_args,
- RegionParamList regions, location_t locus,
- ParamSubstCb param_subst_cb = nullptr,
- bool trait_item_flag = false,
- bool error_flag = false);
+ SubstitutionArgumentMappings (
+ std::vector<SubstitutionArg> mappings,
+ std::map<std::string, BaseType *> binding_args, RegionParamList regions,
+ location_t locus, ParamSubstCb param_subst_cb = nullptr,
+ bool trait_item_flag = false, bool error_flag = false,
+ std::map<std::string, BaseType *> constraint_args = {});
SubstitutionArgumentMappings (const SubstitutionArgumentMappings &other);
SubstitutionArgumentMappings &
@@ -233,6 +233,8 @@ public:
const std::map<std::string, BaseType *> &get_binding_args () const;
+ const std::map<std::string, BaseType *> &get_constraint_args () const;
+
const RegionParamList &get_regions () const;
RegionParamList &get_mut_regions ();
@@ -247,6 +249,7 @@ public:
private:
std::vector<SubstitutionArg> mappings;
std::map<std::string, BaseType *> binding_args;
+ std::map<std::string, BaseType *> constraint_args;
RegionParamList regions;
location_t locus;
ParamSubstCb param_subst_cb;
diff --git a/gcc/rust/typecheck/rust-unify.cc b/gcc/rust/typecheck/rust-unify.cc
index 32aebff52..e6a863a5b 100644
--- a/gcc/rust/typecheck/rust-unify.cc
+++ b/gcc/rust/typecheck/rust-unify.cc
@@ -1989,6 +1989,12 @@ UnifyRules::expect_projection (TyTy::ProjectionType
*ltype,
{
if (ltype->is_trait_position ())
{
+ // A trait-position projection whose Self is still generic cannot be
+ // normalized against a concrete impl candidate.
+ auto dself = ltype->get_self ()->destructure ();
+ if (dself->is<TyTy::ParamType> ())
+ return ltype;
+
TyTy::BaseType *ln
= normalize_projection (ltype, locus, false, false);
if (ln != nullptr && ln != ltype)
diff --git a/gcc/testsuite/rust/compile/associated-type-bound.rs
b/gcc/testsuite/rust/compile/associated-type-bound.rs
new file mode 100644
index 000000000..43cc57533
--- /dev/null
+++ b/gcc/testsuite/rust/compile/associated-type-bound.rs
@@ -0,0 +1,50 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Iterator {
+ type Item;
+}
+
+pub trait IntoIterator {
+ type IntoIter;
+}
+
+pub struct FlattenCompat<I, U>(I, U);
+
+pub struct Flatten<I: Iterator<Item: IntoIterator>> {
+ pub inner: FlattenCompat<I, <I::Item as IntoIterator>::IntoIter>,
+}
+
+pub trait Foo {
+ type Bar;
+
+ fn foo(&self);
+}
+
+pub trait Copy {}
+
+pub trait Container<T> {
+ type Item;
+}
+
+pub fn c<F: Foo<Bar: Foo>>(value: &F::Bar)
+where
+ F::Bar: Copy,
+{
+ value.foo();
+}
+
+pub fn nested<F: Foo<Bar: Foo>>() {
+ let _: *const <F::Bar as Foo>::Bar;
+}
+
+pub fn multiple_bounds<F: Foo<Bar: Foo + Copy>>() {
+ let _: *const <F::Bar as Foo>::Bar;
+}
+
+pub fn positional_and_bound<T, C: Container<T, Item: Foo>>() {
+ let _: *const <C::Item as Foo>::Bar;
+}
diff --git a/gcc/testsuite/rust/compile/issue-1726-1.rs
b/gcc/testsuite/rust/compile/issue-1726-1.rs
new file mode 100644
index 000000000..0e78fff3c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1726-1.rs
@@ -0,0 +1,17 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Foo {
+ type Bar;
+}
+
+pub trait Copy {}
+
+pub fn c<F: Foo<Bar: Foo>>()
+where
+ F::Bar: Copy,
+{
+}
diff --git a/gcc/testsuite/rust/compile/issue-1726-2.rs
b/gcc/testsuite/rust/compile/issue-1726-2.rs
new file mode 100644
index 000000000..4808b5709
--- /dev/null
+++ b/gcc/testsuite/rust/compile/issue-1726-2.rs
@@ -0,0 +1,42 @@
+#![feature(lang_items, no_core)]
+#![no_core]
+
+#[lang = "sized"]
+pub trait Sized {}
+
+pub trait Foo {
+ type Bar;
+
+ fn foo(&self);
+}
+
+pub trait Copy {}
+
+pub fn c<F: Foo<Bar: Foo>>(value: &F::Bar)
+where
+ F::Bar: Copy,
+{
+ value.foo();
+}
+
+pub struct Outer;
+pub struct Inner;
+
+impl Foo for Outer {
+ type Bar = Inner;
+
+ fn foo(&self) {}
+}
+
+impl Foo for Inner {
+ type Bar = Inner;
+
+ fn foo(&self) {}
+}
+
+impl Copy for Inner {}
+
+pub fn main() {
+ let inner = Inner;
+ c::<Outer>(&inner);
+}
base-commit: 2c764560d7c41f9aef6d69eb25777622d583eea1
--
2.55.0