diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs index d29601e9008c3..89677141f3862 100644 --- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs +++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs @@ -9,12 +9,12 @@ use rustc_span::symbol::Ident; use rustc_span::{ErrorGuaranteed, Span}; use rustc_trait_selection::traits; -use crate::astconv::{AstConv, ConvertedBinding, ConvertedBindingKind}; +use crate::astconv::{ + AstConv, ConvertedBinding, ConvertedBindingKind, OnlySelfBounds, PredicateFilter, +}; use crate::bounds::Bounds; use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified}; -use super::OnlySelfBounds; - impl<'tcx> dyn AstConv<'tcx> + '_ { /// Sets `implicitly_sized` to true on `Bounds` if necessary pub(crate) fn add_implicitly_sized( @@ -176,47 +176,39 @@ impl<'tcx> dyn AstConv<'tcx> + '_ { &self, param_ty: Ty<'tcx>, ast_bounds: &[hir::GenericBound<'_>], - only_self_bounds: OnlySelfBounds, + filter: PredicateFilter, ) -> Bounds<'tcx> { let mut bounds = Bounds::default(); - self.add_bounds( - param_ty, - ast_bounds.iter(), - &mut bounds, - ty::List::empty(), - only_self_bounds, - ); - debug!(?bounds); - bounds - } - - /// Convert the bounds in `ast_bounds` that refer to traits which define an associated type - /// named `assoc_name` into ty::Bounds. Ignore the rest. - pub(crate) fn compute_bounds_that_match_assoc_item( - &self, - param_ty: Ty<'tcx>, - ast_bounds: &[hir::GenericBound<'_>], - assoc_name: Ident, - ) -> Bounds<'tcx> { - let mut result = Vec::new(); - - for ast_bound in ast_bounds { - if let Some(trait_ref) = ast_bound.trait_ref() - && let Some(trait_did) = trait_ref.trait_def_id() - && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) - { - result.push(ast_bound.clone()); + let only_self_bounds = match filter { + PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { + OnlySelfBounds(false) } - } + PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true), + }; - let mut bounds = Bounds::default(); self.add_bounds( param_ty, - result.iter(), + ast_bounds.iter().filter(|bound| { + match filter { + PredicateFilter::All + | PredicateFilter::SelfOnly + | PredicateFilter::SelfAndAssociatedTypeBounds => true, + PredicateFilter::SelfThatDefines(assoc_name) => { + if let Some(trait_ref) = bound.trait_ref() + && let Some(trait_did) = trait_ref.trait_def_id() + && self.tcx().trait_may_define_assoc_item(trait_did, assoc_name) + { + true + } else { + false + } + } + } + }), &mut bounds, ty::List::empty(), - OnlySelfBounds(true), + only_self_bounds, ); debug!(?bounds); diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index 6a59aa36ec7d4..5032378923b79 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -58,6 +58,24 @@ pub struct PathSeg(pub DefId, pub usize); #[derive(Copy, Clone, Debug)] pub struct OnlySelfBounds(pub bool); +#[derive(Copy, Clone, Debug)] +pub enum PredicateFilter { + /// All predicates may be implied by the trait. + All, + + /// Only traits that reference `Self: ..` are implied by the trait. + SelfOnly, + + /// Only traits that reference `Self: ..` and define an associated type + /// with the given ident are implied by the trait. + SelfThatDefines(Ident), + + /// Only traits that reference `Self: ..` and their associated type bounds. + /// For example, given `Self: Tr`, this would expand to `Self: Tr` + /// and `::A: B`. + SelfAndAssociatedTypeBounds, +} + pub trait AstConv<'tcx> { fn tcx(&self) -> TyCtxt<'tcx>; diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index 44c393bfe82fd..8b3f98493c12b 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -1,5 +1,5 @@ use super::ItemCtxt; -use crate::astconv::{AstConv, OnlySelfBounds}; +use crate::astconv::{AstConv, PredicateFilter}; use rustc_hir as hir; use rustc_infer::traits::util; use rustc_middle::ty::subst::InternalSubsts; @@ -26,7 +26,7 @@ fn associated_type_bounds<'tcx>( ); let icx = ItemCtxt::new(tcx, assoc_item_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All); // Associated types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); @@ -68,7 +68,7 @@ fn opaque_type_bounds<'tcx>( ) -> &'tcx [(ty::Clause<'tcx>, Span)] { ty::print::with_no_queries!({ let icx = ItemCtxt::new(tcx, opaque_def_id); - let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, OnlySelfBounds(false)); + let mut bounds = icx.astconv().compute_bounds(item_ty, ast_bounds, PredicateFilter::All); // Opaque types are implicitly sized unless a `?Sized` bound is found icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span); debug!(?bounds); diff --git a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs index 5605901fbcb4d..d9b2aacab9d66 100644 --- a/compiler/rustc_hir_analysis/src/collect/predicates_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/predicates_of.rs @@ -1,4 +1,4 @@ -use crate::astconv::{AstConv, OnlySelfBounds}; +use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter}; use crate::bounds::Bounds; use crate::collect::ItemCtxt; use crate::constrained_generic_params as cgp; @@ -125,7 +125,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen if let Some(self_bounds) = is_trait { predicates.extend( icx.astconv() - .compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false)) + .compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All) .clauses(), ); } @@ -530,24 +530,6 @@ pub(super) fn explicit_predicates_of<'tcx>( } } -#[derive(Copy, Clone, Debug)] -pub enum PredicateFilter { - /// All predicates may be implied by the trait. - All, - - /// Only traits that reference `Self: ..` are implied by the trait. - SelfOnly, - - /// Only traits that reference `Self: ..` and define an associated type - /// with the given ident are implied by the trait. - SelfThatDefines(Ident), - - /// Only traits that reference `Self: ..` and their associated type bounds. - /// For example, given `Self: Tr`, this would expand to `Self: Tr` - /// and `::A: B`. - SelfAndAssociatedTypeBounds, -} - /// Ensures that the super-predicates of the trait with a `DefId` /// of `trait_def_id` are converted and stored. This also ensures that /// the transitive super-predicates are converted. @@ -610,20 +592,7 @@ pub(super) fn implied_predicates_with_filter( let icx = ItemCtxt::new(tcx, trait_def_id); let self_param_ty = tcx.types.self_param; - let superbounds = match filter { - // Should imply both "real" supertraits, and also associated type bounds - // from the supertraits position. - PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => { - icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(false)) - } - // Should only imply "real" supertraits, i.e. predicates with the self type `Self`. - PredicateFilter::SelfOnly => { - icx.astconv().compute_bounds(self_param_ty, bounds, OnlySelfBounds(true)) - } - PredicateFilter::SelfThatDefines(assoc_name) => { - icx.astconv().compute_bounds_that_match_assoc_item(self_param_ty, bounds, assoc_name) - } - }; + let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, filter); let where_bounds_that_match = icx.type_parameter_bounds_in_generics( generics,