diff options
| author | Santiago Pastorino <spastorino@gmail.com> | 2020-11-19 18:37:26 -0300 |
|---|---|---|
| committer | Santiago Pastorino <spastorino@gmail.com> | 2020-11-27 11:23:48 -0300 |
| commit | 5b6f206d23b003b89a0883d2c0e5461330ab1068 (patch) | |
| tree | a2be8648683e9240cbbebed6d3a6bfd01368a681 | |
| parent | 4a97c52630f9d8c5df3c229b1c2c0fb0fa3f3ca2 (diff) | |
| download | rust-5b6f206d23b003b89a0883d2c0e5461330ab1068.tar.gz rust-5b6f206d23b003b89a0883d2c0e5461330ab1068.zip | |
Fix super_traits_of to consider where bounds
| -rw-r--r-- | compiler/rustc_typeck/src/collect.rs | 30 | ||||
| -rw-r--r-- | src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs | 21 |
2 files changed, 47 insertions, 4 deletions
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs index 8b457c7ceec..6a33bc88685 100644 --- a/compiler/rustc_typeck/src/collect.rs +++ b/compiler/rustc_typeck/src/collect.rs @@ -1133,10 +1133,12 @@ pub fn super_traits_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> impl Iterator<It _ => bug!("super_trait_of {} is not an item", trait_hir_id), }; - let supertraits = match item.kind { - hir::ItemKind::Trait(.., ref supertraits, _) => supertraits, - hir::ItemKind::TraitAlias(_, ref supertraits) => supertraits, - _ => span_bug!(item.span, "super_trait_of invoked on non-trait"), + let (generics, supertraits) = match item.kind { + hir::ItemKind::Trait(.., ref generics, ref supertraits, _) => { + (generics, supertraits) + } + hir::ItemKind::TraitAlias(ref generics, ref supertraits) => (generics, supertraits), + _ => span_bug!(item.span, "super_predicates invoked on non-trait"), }; for supertrait in supertraits.iter() { @@ -1145,6 +1147,26 @@ pub fn super_traits_of(tcx: TyCtxt<'_>, trait_def_id: DefId) -> impl Iterator<It stack.push(trait_did); } } + + let icx = ItemCtxt::new(tcx, trait_did); + // Convert any explicit superbounds in the where-clause, + // e.g., `trait Foo where Self: Bar`. + // In the case of trait aliases, however, we include all bounds in the where-clause, + // so e.g., `trait Foo = where u32: PartialEq<Self>` would include `u32: PartialEq<Self>` + // as one of its "superpredicates". + let is_trait_alias = tcx.is_trait_alias(trait_did); + let self_param_ty = tcx.types.self_param; + for (predicate, _) in icx.type_parameter_bounds_in_generics( + generics, + item.hir_id, + self_param_ty, + OnlySelfBounds(!is_trait_alias), + None, + ) { + if let ty::PredicateAtom::Trait(data, _) = predicate.skip_binders() { + stack.push(data.def_id()); + } + } } else { let generic_predicates = tcx.super_predicates_of(trait_did); for (predicate, _) in generic_predicates.predicates { diff --git a/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs new file mode 100644 index 00000000000..3eb50ab5547 --- /dev/null +++ b/src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs @@ -0,0 +1,21 @@ +// check-pass + +trait Foo { + type Item; +} + +trait Bar +where + Self: Foo, +{ +} + +#[allow(dead_code)] +fn foo<M>(_m: M) +where + M: Bar, + M::Item: Send, +{ +} + +fn main() {} |
