about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2020-06-23 18:18:06 +0100
committerMatthew Jasper <mjjasper1@gmail.com>2020-10-06 11:18:45 +0100
commita7ead3bd539e75cb2e881238406a203023f1acd3 (patch)
tree753253596f7c0cf064dd04fc039bc53004b56f57
parent0eb87ed55fa76e11777254c77ff7f11c74aa2bfa (diff)
downloadrust-a7ead3bd539e75cb2e881238406a203023f1acd3.tar.gz
rust-a7ead3bd539e75cb2e881238406a203023f1acd3.zip
Move item_bounds to typeck::collect
-rw-r--r--compiler/rustc_ty/src/ty.rs125
-rw-r--r--compiler/rustc_typeck/src/collect.rs2
-rw-r--r--compiler/rustc_typeck/src/collect/item_bounds.rs126
3 files changed, 129 insertions, 124 deletions
diff --git a/compiler/rustc_ty/src/ty.rs b/compiler/rustc_ty/src/ty.rs
index 2be466bf773..1f21d9488a4 100644
--- a/compiler/rustc_ty/src/ty.rs
+++ b/compiler/rustc_ty/src/ty.rs
@@ -1,11 +1,9 @@
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::svh::Svh;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LOCAL_CRATE};
-use rustc_infer::traits::util;
 use rustc_middle::hir::map as hir_map;
-use rustc_middle::ty::subst::{InternalSubsts, Subst};
+use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{
     self, Binder, Predicate, PredicateAtom, PredicateKind, ToPredicate, Ty, TyCtxt, WithConstness,
 };
@@ -492,126 +490,6 @@ fn asyncness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::IsAsync {
     fn_like.asyncness()
 }
 
-/// For associated types we allow bounds written on the associated type
-/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
-/// when desugared as bounds on the trait `where Self::X: Trait`.
-///
-/// Note that this filtering is done with the items identity substs to
-/// simplify checking that these bounds are met in impls. This means that
-/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
-/// `hr-associated-type-bound-1.rs`.
-fn associated_type_bounds(
-    tcx: TyCtxt<'_>,
-    assoc_item_def_id: DefId,
-) -> &'_ ty::List<ty::Predicate<'_>> {
-    let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
-    // We include predicates from the trait as well to handle
-    // `where Self::X: Trait`.
-    let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
-    let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
-
-    let assoc_item_ty = ty::ProjectionTy {
-        item_def_id: assoc_item_def_id,
-        substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
-    };
-
-    let predicates = item_predicates.filter_map(|obligation| {
-        let pred = obligation.predicate;
-        match pred.skip_binders() {
-            ty::PredicateAtom::Trait(tr, _) => {
-                if let ty::Projection(p) = *tr.self_ty().kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::Projection(proj) => {
-                if let ty::Projection(p) = *proj.projection_ty.self_ty().kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::TypeOutlives(outlives) => {
-                if let ty::Projection(p) = *outlives.0.kind() {
-                    if p == assoc_item_ty {
-                        return Some(pred);
-                    }
-                }
-            }
-            _ => {}
-        }
-        None
-    });
-
-    let result = tcx.mk_predicates(predicates);
-    debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result);
-    result
-}
-
-/// Opaque types don't have the same issues as associated types: the only
-/// predicates on an opaque type (excluding those it inherits from its parent
-/// item) should be of the form we're expecting.
-fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
-    let substs = InternalSubsts::identity_for_item(tcx, def_id);
-
-    let bounds = tcx.predicates_of(def_id);
-    let predicates =
-        util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred));
-
-    let filtered_predicates = predicates.filter_map(|obligation| {
-        let pred = obligation.predicate;
-        match pred.skip_binders() {
-            ty::PredicateAtom::Trait(tr, _) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.self_ty().kind() {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::Projection(proj) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) =
-                    *proj.projection_ty.self_ty().kind()
-                {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                }
-            }
-            ty::PredicateAtom::TypeOutlives(outlives) => {
-                if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.0.kind() {
-                    if opaque_def_id == def_id && opaque_substs == substs {
-                        return Some(pred);
-                    }
-                } else {
-                    // These can come from elaborating other predicates
-                    return None;
-                }
-            }
-            // These can come from elaborating other predicates
-            ty::PredicateAtom::RegionOutlives(_) => return None,
-            _ => {}
-        }
-        tcx.sess.delay_span_bug(
-            obligation.cause.span(tcx),
-            &format!("unexpected predicate {:?} on opaque type", pred),
-        );
-        None
-    });
-
-    let result = tcx.mk_predicates(filtered_predicates);
-    debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result);
-    result
-}
-
-fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
-    match tcx.def_kind(def_id) {
-        DefKind::AssocTy => associated_type_bounds(tcx, def_id),
-        DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id),
-        k => bug!("item_bounds called on {}", k.descr(def_id)),
-    }
-}
-
 pub fn provide(providers: &mut ty::query::Providers) {
     *providers = ty::query::Providers {
         asyncness,
@@ -629,7 +507,6 @@ pub fn provide(providers: &mut ty::query::Providers) {
         instance_def_size_estimate,
         issue33140_self_ty,
         impl_defaultness,
-        item_bounds,
         ..*providers
     };
 }
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index 1f4f40fca9b..b4ce3ac74e6 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -50,6 +50,7 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits::error_reporting::suggestions::NextTypeParamName;
 
+mod item_bounds;
 mod type_of;
 
 struct OnlySelfBounds(bool);
@@ -68,6 +69,7 @@ pub fn provide(providers: &mut Providers) {
     *providers = Providers {
         opt_const_param_of: type_of::opt_const_param_of,
         type_of: type_of::type_of,
+        item_bounds: item_bounds::item_bounds,
         generics_of,
         predicates_of,
         predicates_defined_on,
diff --git a/compiler/rustc_typeck/src/collect/item_bounds.rs b/compiler/rustc_typeck/src/collect/item_bounds.rs
new file mode 100644
index 00000000000..c43f830787d
--- /dev/null
+++ b/compiler/rustc_typeck/src/collect/item_bounds.rs
@@ -0,0 +1,126 @@
+use rustc_hir::def::DefKind;
+use rustc_infer::traits::util;
+use rustc_middle::ty::subst::InternalSubsts;
+use rustc_middle::ty::{self, TyCtxt};
+use rustc_span::def_id::DefId;
+
+/// For associated types we allow bounds written on the associated type
+/// (`type X: Trait`) to be used as candidates. We also allow the same bounds
+/// when desugared as bounds on the trait `where Self::X: Trait`.
+///
+/// Note that this filtering is done with the items identity substs to
+/// simplify checking that these bounds are met in impls. This means that
+/// a bound such as `for<'b> <Self as X<'b>>::U: Clone` can't be used, as in
+/// `hr-associated-type-bound-1.rs`.
+fn associated_type_bounds(
+    tcx: TyCtxt<'_>,
+    assoc_item_def_id: DefId,
+) -> &'_ ty::List<ty::Predicate<'_>> {
+    let generic_trait_bounds = tcx.predicates_of(assoc_item_def_id);
+    // We include predicates from the trait as well to handle
+    // `where Self::X: Trait`.
+    let item_bounds = generic_trait_bounds.instantiate_identity(tcx);
+    let item_predicates = util::elaborate_predicates(tcx, item_bounds.predicates.into_iter());
+
+    let assoc_item_ty = ty::ProjectionTy {
+        item_def_id: assoc_item_def_id,
+        substs: InternalSubsts::identity_for_item(tcx, assoc_item_def_id),
+    };
+
+    let predicates = item_predicates.filter_map(|obligation| {
+        let pred = obligation.predicate;
+        match pred.kind() {
+            ty::PredicateKind::Trait(tr, _) => {
+                if let ty::Projection(p) = *tr.skip_binder().self_ty().kind() {
+                    if p == assoc_item_ty {
+                        return Some(pred);
+                    }
+                }
+            }
+            ty::PredicateKind::Projection(proj) => {
+                if let ty::Projection(p) = *proj.skip_binder().projection_ty.self_ty().kind() {
+                    if p == assoc_item_ty {
+                        return Some(pred);
+                    }
+                }
+            }
+            ty::PredicateKind::TypeOutlives(outlives) => {
+                if let ty::Projection(p) = *outlives.skip_binder().0.kind() {
+                    if p == assoc_item_ty {
+                        return Some(pred);
+                    }
+                }
+            }
+            _ => {}
+        }
+        None
+    });
+
+    let result = tcx.mk_predicates(predicates);
+    debug!("associated_type_bounds({}) = {:?}", tcx.def_path_str(assoc_item_def_id), result);
+    result
+}
+
+/// Opaque types don't have the same issues as associated types: the only
+/// predicates on an opaque type (excluding those it inherits from its parent
+/// item) should be of the form we're expecting.
+fn opaque_type_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
+    let substs = InternalSubsts::identity_for_item(tcx, def_id);
+
+    let bounds = tcx.predicates_of(def_id);
+    let predicates =
+        util::elaborate_predicates(tcx, bounds.predicates.iter().map(|&(pred, _)| pred));
+
+    let filtered_predicates = predicates.filter_map(|obligation| {
+        let pred = obligation.predicate;
+        match pred.kind() {
+            ty::PredicateKind::Trait(tr, _) => {
+                if let ty::Opaque(opaque_def_id, opaque_substs) = *tr.skip_binder().self_ty().kind()
+                {
+                    if opaque_def_id == def_id && opaque_substs == substs {
+                        return Some(pred);
+                    }
+                }
+            }
+            ty::PredicateKind::Projection(proj) => {
+                if let ty::Opaque(opaque_def_id, opaque_substs) =
+                    *proj.skip_binder().projection_ty.self_ty().kind()
+                {
+                    if opaque_def_id == def_id && opaque_substs == substs {
+                        return Some(pred);
+                    }
+                }
+            }
+            ty::PredicateKind::TypeOutlives(outlives) => {
+                if let ty::Opaque(opaque_def_id, opaque_substs) = *outlives.skip_binder().0.kind() {
+                    if opaque_def_id == def_id && opaque_substs == substs {
+                        return Some(pred);
+                    }
+                } else {
+                    // These can come from elaborating other predicates
+                    return None;
+                }
+            }
+            // These can come from elaborating other predicates
+            ty::PredicateKind::RegionOutlives(_) => return None,
+            _ => {}
+        }
+        tcx.sess.delay_span_bug(
+            obligation.cause.span(tcx),
+            &format!("unexpected predicate {:?} on opaque type", pred),
+        );
+        None
+    });
+
+    let result = tcx.mk_predicates(filtered_predicates);
+    debug!("opaque_type_bounds({}) = {:?}", tcx.def_path_str(def_id), result);
+    result
+}
+
+pub(super) fn item_bounds(tcx: TyCtxt<'_>, def_id: DefId) -> &'_ ty::List<ty::Predicate<'_>> {
+    match tcx.def_kind(def_id) {
+        DefKind::AssocTy => associated_type_bounds(tcx, def_id),
+        DefKind::OpaqueTy => opaque_type_bounds(tcx, def_id),
+        k => bug!("item_bounds called on {}", k.descr(def_id)),
+    }
+}