Skip to content

Commit 8c91ed5

Browse files
committed
gccrs: support generic super traits recursively
In order to handle generic super traits on any trait bound we need to ensure we track the TypeBoundPredicate as part of the TraitReference instead of just the raw TraitReferences because these will have any applied generics enplace. Then for any TypeBoundPredicate it takes a copy of the super traits because this is the usage of a TraitBound and we can apply generics which then need to be recursively applied up the chain of super predicates. The main tweak is around TypeBoundPredicate::lookup_associated_item because we need to associate the predicate with the item we are looking up so the caller can respect the generics correctly as well. Fixes #3502 gcc/rust/ChangeLog: * typecheck/rust-hir-path-probe.cc: update call * typecheck/rust-hir-trait-reference.cc (TraitReference::lookup_trait_item): track predicate (TraitReference::is_equal): likewise (TraitReference::is_object_safe): likewise (TraitReference::satisfies_bound): likewise * typecheck/rust-hir-trait-reference.h: likewise * typecheck/rust-hir-trait-resolve.cc (TraitResolver::resolve_trait): likewise * typecheck/rust-tyty-bounds.cc (TypeBoundPredicate::TypeBoundPredicate): track super traits (TypeBoundPredicate::operator=): likewise (TypeBoundPredicate::apply_generic_arguments): ensure we apply to super predicates (TypeBoundPredicateItem::operator=): take copy of parent predicate (TypeBoundPredicateItem::error): pass error instead of nullptr (TypeBoundPredicateItem::is_error): update to no longer check for nullptr (TypeBoundPredicateItem::get_parent): updated (TypeBoundPredicateItem::get_tyty_for_receiver): likewise (TypeBoundPredicate::get_associated_type_items): likewise * typecheck/rust-tyty-bounds.h (class TypeBoundPredicateItem): move * typecheck/rust-tyty-subst.cc: flag to handle placeholder Self on traits * typecheck/rust-tyty-subst.h (class TypeBoundPredicateItem): likewise * typecheck/rust-tyty.h (class TypeBoundPredicateItem): refactored gcc/testsuite/ChangeLog: * rust/execute/torture/issue-3502.rs: New test. Signed-off-by: Philip Herron <[email protected]>
1 parent b4895da commit 8c91ed5

File tree

10 files changed

+166
-60
lines changed

10 files changed

+166
-60
lines changed

gcc/rust/typecheck/rust-hir-path-probe.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -346,7 +346,7 @@ PathProbeType::process_associated_trait_for_candidates (
346346

347347
const TyTy::TypeBoundPredicate p (*trait_ref, BoundPolarity::RegularBound,
348348
UNDEF_LOCATION);
349-
TyTy::TypeBoundPredicateItem item (&p, trait_item_ref);
349+
TyTy::TypeBoundPredicateItem item (p, trait_item_ref);
350350

351351
TyTy::BaseType *trait_item_tyty = item.get_raw_item ()->get_tyty ();
352352
if (receiver->get_kind () != TyTy::DYNAMIC)

gcc/rust/typecheck/rust-hir-trait-reference.cc

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ TraitItemReference::get_error () const
106106

107107
TraitReference::TraitReference (
108108
const HIR::Trait *hir_trait_ref, std::vector<TraitItemReference> item_refs,
109-
std::vector<const TraitReference *> super_traits,
109+
std::vector<TyTy::TypeBoundPredicate> super_traits,
110110
std::vector<TyTy::SubstitutionParamMapping> substs)
111111
: hir_trait_ref (hir_trait_ref), item_refs (item_refs),
112112
super_traits (super_traits)
@@ -263,7 +263,8 @@ TraitReference::lookup_hir_trait_item (const HIR::TraitItem &item,
263263

264264
bool
265265
TraitReference::lookup_trait_item (const std::string &ident,
266-
const TraitItemReference **ref) const
266+
const TraitItemReference **ref,
267+
bool lookup_supers) const
267268
{
268269
for (auto &item : item_refs)
269270
{
@@ -274,10 +275,13 @@ TraitReference::lookup_trait_item (const std::string &ident,
274275
}
275276
}
276277

278+
if (!lookup_supers)
279+
return false;
280+
277281
// lookup super traits
278282
for (const auto &super_trait : super_traits)
279283
{
280-
bool found = super_trait->lookup_trait_item (ident, ref);
284+
bool found = super_trait.get ()->lookup_trait_item (ident, ref);
281285
if (found)
282286
return true;
283287
}
@@ -302,7 +306,7 @@ TraitReference::lookup_trait_item (const std::string &ident,
302306
for (const auto &super_trait : super_traits)
303307
{
304308
const TraitItemReference *res
305-
= super_trait->lookup_trait_item (ident, type);
309+
= super_trait.get ()->lookup_trait_item (ident, type);
306310
if (!res->is_error ())
307311
return res;
308312
}
@@ -330,7 +334,7 @@ TraitReference::get_trait_items_and_supers (
330334
result.push_back (&item);
331335

332336
for (const auto &super_trait : super_traits)
333-
super_trait->get_trait_items_and_supers (result);
337+
super_trait.get ()->get_trait_items_and_supers (result);
334338
}
335339

336340
void
@@ -374,7 +378,7 @@ TraitReference::is_equal (const TraitReference &other) const
374378
return this_id == other_id;
375379
}
376380

377-
const std::vector<const TraitReference *>
381+
std::vector<TyTy::TypeBoundPredicate>
378382
TraitReference::get_super_traits () const
379383
{
380384
return super_traits;
@@ -385,10 +389,10 @@ TraitReference::is_object_safe (bool emit_error, location_t locus) const
385389
{
386390
// https: // doc.rust-lang.org/reference/items/traits.html#object-safety
387391
std::vector<const TraitReference *> non_object_super_traits;
388-
for (auto &item : super_traits)
392+
for (auto &super_trait : super_traits)
389393
{
390-
if (!item->is_object_safe (false, UNDEF_LOCATION))
391-
non_object_super_traits.push_back (item);
394+
if (!super_trait.get ()->is_object_safe (false, UNDEF_LOCATION))
395+
non_object_super_traits.push_back (super_trait.get ());
392396
}
393397

394398
std::vector<const Resolver::TraitItemReference *> non_object_safe_items;
@@ -434,7 +438,7 @@ TraitReference::satisfies_bound (const TraitReference &reference) const
434438

435439
for (const auto &super_trait : super_traits)
436440
{
437-
if (super_trait->satisfies_bound (reference))
441+
if (super_trait.get ()->satisfies_bound (reference))
438442
return true;
439443
}
440444

gcc/rust/typecheck/rust-hir-trait-reference.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ class TraitReference
144144
public:
145145
TraitReference (const HIR::Trait *hir_trait_ref,
146146
std::vector<TraitItemReference> item_refs,
147-
std::vector<const TraitReference *> super_traits,
147+
std::vector<TyTy::TypeBoundPredicate> super_traits,
148148
std::vector<TyTy::SubstitutionParamMapping> substs);
149149

150150
TraitReference (TraitReference const &other);
@@ -196,7 +196,8 @@ class TraitReference
196196
const TraitItemReference **ref) const;
197197

198198
bool lookup_trait_item (const std::string &ident,
199-
const TraitItemReference **ref) const;
199+
const TraitItemReference **ref,
200+
bool lookup_supers = true) const;
200201

201202
const TraitItemReference *
202203
lookup_trait_item (const std::string &ident,
@@ -217,7 +218,7 @@ class TraitReference
217218

218219
bool is_equal (const TraitReference &other) const;
219220

220-
const std::vector<const TraitReference *> get_super_traits () const;
221+
std::vector<TyTy::TypeBoundPredicate> get_super_traits () const;
221222

222223
bool is_object_safe (bool emit_error, location_t locus) const;
223224

@@ -230,7 +231,7 @@ class TraitReference
230231
private:
231232
const HIR::Trait *hir_trait_ref;
232233
std::vector<TraitItemReference> item_refs;
233-
std::vector<const TraitReference *> super_traits;
234+
std::vector<TyTy::TypeBoundPredicate> super_traits;
234235
std::vector<TyTy::SubstitutionParamMapping> trait_substs;
235236
};
236237

gcc/rust/typecheck/rust-hir-trait-resolve.cc

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
266266
specified_bounds.push_back (self_hrtb);
267267

268268
// look for any
269-
std::vector<const TraitReference *> super_traits;
269+
std::vector<TyTy::TypeBoundPredicate> super_traits;
270270
if (trait_reference->has_type_param_bounds ())
271271
{
272272
for (auto &bound : trait_reference->get_type_param_bounds ())
@@ -284,7 +284,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
284284
return &TraitReference::error_node ();
285285

286286
specified_bounds.push_back (predicate);
287-
super_traits.push_back (predicate.get ());
287+
super_traits.push_back (predicate);
288288
}
289289
}
290290
}
@@ -305,8 +305,7 @@ TraitResolver::resolve_trait (HIR::Trait *trait_reference)
305305
item_refs.push_back (std::move (trait_item_ref));
306306
}
307307

308-
TraitReference trait_object (trait_reference, item_refs,
309-
std::move (super_traits),
308+
TraitReference trait_object (trait_reference, item_refs, super_traits,
310309
std::move (substitutions));
311310
context->insert_trait_reference (
312311
trait_reference->get_mappings ().get_defid (), std::move (trait_object));

gcc/rust/typecheck/rust-tyty-bounds.cc

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -345,7 +345,8 @@ TypeBoundPredicate::TypeBoundPredicate (
345345
location_t locus)
346346
: SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
347347
reference (trait_reference.get_mappings ().get_defid ()), locus (locus),
348-
error_flag (false), polarity (polarity)
348+
error_flag (false), polarity (polarity),
349+
super_traits (trait_reference.get_super_traits ())
349350
{
350351
rust_assert (!trait_reference.get_trait_substs ().empty ());
351352

@@ -385,7 +386,8 @@ TypeBoundPredicate::TypeBoundPredicate (mark_is_error)
385386
TypeBoundPredicate::TypeBoundPredicate (const TypeBoundPredicate &other)
386387
: SubstitutionRef ({}, SubstitutionArgumentMappings::empty (), {}),
387388
reference (other.reference), locus (other.locus),
388-
error_flag (other.error_flag), polarity (other.polarity)
389+
error_flag (other.error_flag), polarity (other.polarity),
390+
super_traits (other.super_traits)
389391
{
390392
substitutions.clear ();
391393
for (const auto &p : other.get_substs ())
@@ -455,6 +457,7 @@ TypeBoundPredicate::operator= (const TypeBoundPredicate &other)
455457
= SubstitutionArgumentMappings (copied_arg_mappings, {},
456458
other.used_arguments.get_regions (),
457459
other.used_arguments.get_locus ());
460+
super_traits = other.super_traits;
458461

459462
return *this;
460463
}
@@ -521,11 +524,19 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
521524
}
522525

523526
// now actually perform a substitution
524-
used_arguments = get_mappings_from_generic_args (
527+
auto args = get_mappings_from_generic_args (
525528
*generic_args,
526529
Resolver::TypeCheckContext::get ()->regions_from_generic_args (
527530
*generic_args));
528531

532+
apply_argument_mappings (args);
533+
}
534+
535+
void
536+
TypeBoundPredicate::apply_argument_mappings (
537+
SubstitutionArgumentMappings &arguments)
538+
{
539+
used_arguments = arguments;
529540
error_flag |= used_arguments.is_error ();
530541
auto &subst_mappings = used_arguments;
531542
for (auto &sub : get_substs ())
@@ -549,6 +560,14 @@ TypeBoundPredicate::apply_generic_arguments (HIR::GenericArgs *generic_args,
549560
const auto item_ref = item.get_raw_item ();
550561
item_ref->associated_type_set (type);
551562
}
563+
564+
for (auto &super_trait : super_traits)
565+
{
566+
auto adjusted
567+
= super_trait.adjust_mappings_for_this (used_arguments,
568+
true /*trait mode*/);
569+
super_trait.apply_argument_mappings (adjusted);
570+
}
552571
}
553572

554573
bool
@@ -564,34 +583,56 @@ TypeBoundPredicate::lookup_associated_item (const std::string &search) const
564583
{
565584
auto trait_ref = get ();
566585
const Resolver::TraitItemReference *trait_item_ref = nullptr;
567-
if (!trait_ref->lookup_trait_item (search, &trait_item_ref))
568-
return TypeBoundPredicateItem::error ();
586+
if (trait_ref->lookup_trait_item (search, &trait_item_ref,
587+
false /*lookup supers*/))
588+
return TypeBoundPredicateItem (*this, trait_item_ref);
589+
590+
for (auto &super_trait : super_traits)
591+
{
592+
auto lookup = super_trait.lookup_associated_item (search);
593+
if (!lookup.is_error ())
594+
return lookup;
595+
}
569596

570-
return TypeBoundPredicateItem (this, trait_item_ref);
597+
return TypeBoundPredicateItem::error ();
571598
}
572599

573600
TypeBoundPredicateItem::TypeBoundPredicateItem (
574-
const TypeBoundPredicate *parent,
601+
const TypeBoundPredicate parent,
575602
const Resolver::TraitItemReference *trait_item_ref)
576603
: parent (parent), trait_item_ref (trait_item_ref)
577604
{}
578605

606+
TypeBoundPredicateItem::TypeBoundPredicateItem (
607+
const TypeBoundPredicateItem &other)
608+
: parent (other.parent), trait_item_ref (other.trait_item_ref)
609+
{}
610+
611+
TypeBoundPredicateItem &
612+
TypeBoundPredicateItem::operator= (const TypeBoundPredicateItem &other)
613+
{
614+
parent = other.parent;
615+
trait_item_ref = other.trait_item_ref;
616+
617+
return *this;
618+
}
619+
579620
TypeBoundPredicateItem
580621
TypeBoundPredicateItem::error ()
581622
{
582-
return TypeBoundPredicateItem (nullptr, nullptr);
623+
return TypeBoundPredicateItem (TypeBoundPredicate::error (), nullptr);
583624
}
584625

585626
bool
586627
TypeBoundPredicateItem::is_error () const
587628
{
588-
return parent == nullptr || trait_item_ref == nullptr;
629+
return parent.is_error () || trait_item_ref == nullptr;
589630
}
590631

591632
const TypeBoundPredicate *
592633
TypeBoundPredicateItem::get_parent () const
593634
{
594-
return parent;
635+
return &parent;
595636
}
596637

597638
TypeBoundPredicateItem
@@ -605,7 +646,7 @@ BaseType *
605646
TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
606647
{
607648
TyTy::BaseType *trait_item_tyty = get_raw_item ()->get_tyty ();
608-
if (parent->get_substitution_arguments ().is_empty ())
649+
if (parent.get_substitution_arguments ().is_empty ())
609650
return trait_item_tyty;
610651

611652
const Resolver::TraitItemReference *tref = get_raw_item ();
@@ -614,7 +655,7 @@ TypeBoundPredicateItem::get_tyty_for_receiver (const TyTy::BaseType *receiver)
614655
return trait_item_tyty;
615656

616657
// set up the self mapping
617-
SubstitutionArgumentMappings gargs = parent->get_substitution_arguments ();
658+
SubstitutionArgumentMappings gargs = parent.get_substitution_arguments ();
618659
rust_assert (!gargs.is_empty ());
619660

620661
// setup the adjusted mappings
@@ -746,7 +787,7 @@ TypeBoundPredicate::get_associated_type_items ()
746787
== Resolver::TraitItemReference::TraitItemType::TYPE;
747788
if (is_associated_type)
748789
{
749-
TypeBoundPredicateItem item (this, &trait_item);
790+
TypeBoundPredicateItem item (*this, &trait_item);
750791
items.push_back (std::move (item));
751792
}
752793
}

gcc/rust/typecheck/rust-tyty-bounds.h

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -34,31 +34,6 @@ namespace TyTy {
3434

3535
class BaseType;
3636
class TypeBoundPredicate;
37-
class TypeBoundPredicateItem
38-
{
39-
public:
40-
TypeBoundPredicateItem (const TypeBoundPredicate *parent,
41-
const Resolver::TraitItemReference *trait_item_ref);
42-
43-
static TypeBoundPredicateItem error ();
44-
45-
bool is_error () const;
46-
47-
BaseType *get_tyty_for_receiver (const TyTy::BaseType *receiver);
48-
49-
const Resolver::TraitItemReference *get_raw_item () const;
50-
51-
bool needs_implementation () const;
52-
53-
const TypeBoundPredicate *get_parent () const;
54-
55-
location_t get_locus () const;
56-
57-
private:
58-
const TypeBoundPredicate *parent;
59-
const Resolver::TraitItemReference *trait_item_ref;
60-
};
61-
6237
class TypeBoundsMappings
6338
{
6439
protected:

gcc/rust/typecheck/rust-tyty-subst.cc

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -788,7 +788,7 @@ SubstitutionRef::infer_substitions (location_t locus)
788788

789789
SubstitutionArgumentMappings
790790
SubstitutionRef::adjust_mappings_for_this (
791-
SubstitutionArgumentMappings &mappings)
791+
SubstitutionArgumentMappings &mappings, bool trait_mode)
792792
{
793793
std::vector<SubstitutionArg> resolved_mappings;
794794
for (size_t i = 0; i < substitutions.size (); i++)
@@ -816,7 +816,7 @@ SubstitutionRef::adjust_mappings_for_this (
816816
}
817817

818818
bool ok = !arg.is_error ();
819-
if (ok)
819+
if (ok || (trait_mode && i == 0))
820820
{
821821
SubstitutionArg adjusted (&subst, arg.get_tyty ());
822822
resolved_mappings.push_back (std::move (adjusted));

gcc/rust/typecheck/rust-tyty-subst.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -253,6 +253,7 @@ class SubstitutionArgumentMappings
253253
bool error_flag;
254254
};
255255

256+
class TypeBoundPredicateItem;
256257
class SubstitutionRef
257258
{
258259
public:
@@ -319,7 +320,8 @@ class SubstitutionRef
319320
// we have bindings for X Y Z and need to propagate the binding Y,Z into Foo
320321
// Which binds to A,B
321322
SubstitutionArgumentMappings
322-
adjust_mappings_for_this (SubstitutionArgumentMappings &mappings);
323+
adjust_mappings_for_this (SubstitutionArgumentMappings &mappings,
324+
bool trait_mode = false);
323325

324326
// Are the mappings here actually bound to this type. For example imagine the
325327
// case:

0 commit comments

Comments
 (0)