pass PredicateFilter to compute_bounds
This commit is contained in:
parent
858a861fff
commit
de0e7d32fd
4 changed files with 53 additions and 74 deletions
|
@ -9,12 +9,12 @@ use rustc_span::symbol::Ident;
|
||||||
use rustc_span::{ErrorGuaranteed, Span};
|
use rustc_span::{ErrorGuaranteed, Span};
|
||||||
use rustc_trait_selection::traits;
|
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::bounds::Bounds;
|
||||||
use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
|
use crate::errors::{MultipleRelaxedDefaultBounds, ValueOfAssociatedStructAlreadySpecified};
|
||||||
|
|
||||||
use super::OnlySelfBounds;
|
|
||||||
|
|
||||||
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||||
/// Sets `implicitly_sized` to true on `Bounds` if necessary
|
/// Sets `implicitly_sized` to true on `Bounds` if necessary
|
||||||
pub(crate) fn add_implicitly_sized(
|
pub(crate) fn add_implicitly_sized(
|
||||||
|
@ -176,12 +176,36 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||||
&self,
|
&self,
|
||||||
param_ty: Ty<'tcx>,
|
param_ty: Ty<'tcx>,
|
||||||
ast_bounds: &[hir::GenericBound<'_>],
|
ast_bounds: &[hir::GenericBound<'_>],
|
||||||
only_self_bounds: OnlySelfBounds,
|
filter: PredicateFilter,
|
||||||
) -> Bounds<'tcx> {
|
) -> Bounds<'tcx> {
|
||||||
let mut bounds = Bounds::default();
|
let mut bounds = Bounds::default();
|
||||||
|
|
||||||
|
let only_self_bounds = match filter {
|
||||||
|
PredicateFilter::All | PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||||
|
OnlySelfBounds(false)
|
||||||
|
}
|
||||||
|
PredicateFilter::SelfOnly | PredicateFilter::SelfThatDefines(_) => OnlySelfBounds(true),
|
||||||
|
};
|
||||||
|
|
||||||
self.add_bounds(
|
self.add_bounds(
|
||||||
param_ty,
|
param_ty,
|
||||||
ast_bounds.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,
|
&mut bounds,
|
||||||
ty::List::empty(),
|
ty::List::empty(),
|
||||||
only_self_bounds,
|
only_self_bounds,
|
||||||
|
@ -191,38 +215,6 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
|
||||||
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 mut bounds = Bounds::default();
|
|
||||||
self.add_bounds(
|
|
||||||
param_ty,
|
|
||||||
result.iter(),
|
|
||||||
&mut bounds,
|
|
||||||
ty::List::empty(),
|
|
||||||
OnlySelfBounds(true),
|
|
||||||
);
|
|
||||||
debug!(?bounds);
|
|
||||||
|
|
||||||
bounds
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
|
/// Given an HIR binding like `Item = Foo` or `Item: Foo`, pushes the corresponding predicates
|
||||||
/// onto `bounds`.
|
/// onto `bounds`.
|
||||||
///
|
///
|
||||||
|
|
|
@ -58,6 +58,24 @@ pub struct PathSeg(pub DefId, pub usize);
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
pub struct OnlySelfBounds(pub bool);
|
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<A: B>`, this would expand to `Self: Tr`
|
||||||
|
/// and `<Self as Tr>::A: B`.
|
||||||
|
SelfAndAssociatedTypeBounds,
|
||||||
|
}
|
||||||
|
|
||||||
pub trait AstConv<'tcx> {
|
pub trait AstConv<'tcx> {
|
||||||
fn tcx(&self) -> TyCtxt<'tcx>;
|
fn tcx(&self) -> TyCtxt<'tcx>;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
use super::ItemCtxt;
|
use super::ItemCtxt;
|
||||||
use crate::astconv::{AstConv, OnlySelfBounds};
|
use crate::astconv::{AstConv, PredicateFilter};
|
||||||
use rustc_hir as hir;
|
use rustc_hir as hir;
|
||||||
use rustc_infer::traits::util;
|
use rustc_infer::traits::util;
|
||||||
use rustc_middle::ty::subst::InternalSubsts;
|
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 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
|
// Associated types are implicitly sized unless a `?Sized` bound is found
|
||||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
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)] {
|
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||||
ty::print::with_no_queries!({
|
ty::print::with_no_queries!({
|
||||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
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
|
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||||
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
icx.astconv().add_implicitly_sized(&mut bounds, item_ty, ast_bounds, None, span);
|
||||||
debug!(?bounds);
|
debug!(?bounds);
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::astconv::{AstConv, OnlySelfBounds};
|
use crate::astconv::{AstConv, OnlySelfBounds, PredicateFilter};
|
||||||
use crate::bounds::Bounds;
|
use crate::bounds::Bounds;
|
||||||
use crate::collect::ItemCtxt;
|
use crate::collect::ItemCtxt;
|
||||||
use crate::constrained_generic_params as cgp;
|
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 {
|
if let Some(self_bounds) = is_trait {
|
||||||
predicates.extend(
|
predicates.extend(
|
||||||
icx.astconv()
|
icx.astconv()
|
||||||
.compute_bounds(tcx.types.self_param, self_bounds, OnlySelfBounds(false))
|
.compute_bounds(tcx.types.self_param, self_bounds, PredicateFilter::All)
|
||||||
.clauses(),
|
.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<A: B>`, this would expand to `Self: Tr`
|
|
||||||
/// and `<Self as Tr>::A: B`.
|
|
||||||
SelfAndAssociatedTypeBounds,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Ensures that the super-predicates of the trait with a `DefId`
|
/// Ensures that the super-predicates of the trait with a `DefId`
|
||||||
/// of `trait_def_id` are converted and stored. This also ensures that
|
/// of `trait_def_id` are converted and stored. This also ensures that
|
||||||
/// the transitive super-predicates are converted.
|
/// 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 icx = ItemCtxt::new(tcx, trait_def_id);
|
||||||
|
|
||||||
let self_param_ty = tcx.types.self_param;
|
let self_param_ty = tcx.types.self_param;
|
||||||
let superbounds = match filter {
|
let superbounds = icx.astconv().compute_bounds(self_param_ty, bounds, 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 where_bounds_that_match = icx.type_parameter_bounds_in_generics(
|
let where_bounds_that_match = icx.type_parameter_bounds_in_generics(
|
||||||
generics,
|
generics,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue