about summary refs log tree commit diff
diff options
context:
space:
mode:
authorSantiago Pastorino <spastorino@gmail.com>2020-11-19 18:37:26 -0300
committerSantiago Pastorino <spastorino@gmail.com>2020-11-27 11:23:48 -0300
commit5b6f206d23b003b89a0883d2c0e5461330ab1068 (patch)
treea2be8648683e9240cbbebed6d3a6bfd01368a681
parent4a97c52630f9d8c5df3c229b1c2c0fb0fa3f3ca2 (diff)
downloadrust-5b6f206d23b003b89a0883d2c0e5461330ab1068.tar.gz
rust-5b6f206d23b003b89a0883d2c0e5461330ab1068.zip
Fix super_traits_of to consider where bounds
-rw-r--r--compiler/rustc_typeck/src/collect.rs30
-rw-r--r--src/test/ui/associated-type-bounds/associated-item-through-where-clause.rs21
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() {}