diff options
| author | Matthew Jasper <mjjasper1@gmail.com> | 2020-06-23 18:18:06 +0100 |
|---|---|---|
| committer | Matthew Jasper <mjjasper1@gmail.com> | 2020-10-06 11:18:45 +0100 |
| commit | a7ead3bd539e75cb2e881238406a203023f1acd3 (patch) | |
| tree | 753253596f7c0cf064dd04fc039bc53004b56f57 | |
| parent | 0eb87ed55fa76e11777254c77ff7f11c74aa2bfa (diff) | |
| download | rust-a7ead3bd539e75cb2e881238406a203023f1acd3.tar.gz rust-a7ead3bd539e75cb2e881238406a203023f1acd3.zip | |
Move item_bounds to typeck::collect
| -rw-r--r-- | compiler/rustc_ty/src/ty.rs | 125 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/collect.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_typeck/src/collect/item_bounds.rs | 126 |
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)), + } +} |
