HIR analysis: Remove unnecessary abstraction over list of clauses
This commit is contained in:
parent
d8810e3e2d
commit
84bdc5de6e
8 changed files with 114 additions and 206 deletions
|
@ -1,100 +0,0 @@
|
|||
//! Bounds are restrictions applied to some types after they've been lowered from the HIR to the
|
||||
//! [`rustc_middle::ty`] form.
|
||||
|
||||
use rustc_hir::LangItem;
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, Upcast};
|
||||
use rustc_span::Span;
|
||||
|
||||
/// Collects together a list of type bounds. These lists of bounds occur in many places
|
||||
/// in Rust's syntax:
|
||||
///
|
||||
/// ```text
|
||||
/// trait Foo: Bar + Baz { }
|
||||
/// ^^^^^^^^^ supertrait list bounding the `Self` type parameter
|
||||
///
|
||||
/// fn foo<T: Bar + Baz>() { }
|
||||
/// ^^^^^^^^^ bounding the type parameter `T`
|
||||
///
|
||||
/// impl dyn Bar + Baz
|
||||
/// ^^^^^^^^^ bounding the type-erased dynamic type
|
||||
/// ```
|
||||
///
|
||||
/// Our representation is a bit mixed here -- in some cases, we
|
||||
/// include the self type (e.g., `trait_bounds`) but in others we do not
|
||||
#[derive(Default, PartialEq, Eq, Clone, Debug)]
|
||||
pub(crate) struct Bounds<'tcx> {
|
||||
clauses: Vec<(ty::Clause<'tcx>, Span)>,
|
||||
}
|
||||
|
||||
impl<'tcx> Bounds<'tcx> {
|
||||
pub(crate) fn push_region_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
region: ty::PolyTypeOutlivesPredicate<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.clauses
|
||||
.push((region.map_bound(|p| ty::ClauseKind::TypeOutlives(p)).upcast(tcx), span));
|
||||
}
|
||||
|
||||
pub(crate) fn push_trait_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
span: Span,
|
||||
polarity: ty::PredicatePolarity,
|
||||
) {
|
||||
let clause = (
|
||||
bound_trait_ref
|
||||
.map_bound(|trait_ref| {
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
||||
})
|
||||
.upcast(tcx),
|
||||
span,
|
||||
);
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||
if tcx.is_lang_item(bound_trait_ref.def_id(), LangItem::Sized) {
|
||||
self.clauses.insert(0, clause);
|
||||
} else {
|
||||
self.clauses.push(clause);
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn push_projection_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
projection: ty::PolyProjectionPredicate<'tcx>,
|
||||
span: Span,
|
||||
) {
|
||||
self.clauses.push((
|
||||
projection.map_bound(|proj| ty::ClauseKind::Projection(proj)).upcast(tcx),
|
||||
span,
|
||||
));
|
||||
}
|
||||
|
||||
pub(crate) fn push_sized(&mut self, tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) {
|
||||
let sized_def_id = tcx.require_lang_item(LangItem::Sized, Some(span));
|
||||
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [ty]);
|
||||
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
|
||||
self.clauses.insert(0, (trait_ref.upcast(tcx), span));
|
||||
}
|
||||
|
||||
/// Push a `const` or `~const` bound as a `HostEffect` predicate.
|
||||
pub(crate) fn push_const_bound(
|
||||
&mut self,
|
||||
tcx: TyCtxt<'tcx>,
|
||||
bound_trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
constness: ty::BoundConstness,
|
||||
span: Span,
|
||||
) {
|
||||
if tcx.is_const_trait(bound_trait_ref.def_id()) {
|
||||
self.clauses.push((bound_trait_ref.to_host_effect_clause(tcx, constness), span));
|
||||
} else {
|
||||
tcx.dcx().span_delayed_bug(span, "tried to lower {host:?} bound for non-const trait");
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn clauses(&self) -> impl Iterator<Item = (ty::Clause<'tcx>, Span)> + '_ {
|
||||
self.clauses.iter().cloned()
|
||||
}
|
||||
}
|
|
@ -13,7 +13,6 @@ use tracing::{debug, instrument};
|
|||
|
||||
use super::ItemCtxt;
|
||||
use super::predicates_of::assert_only_contains_predicates_from;
|
||||
use crate::bounds::Bounds;
|
||||
use crate::hir_ty_lowering::{HirTyLowerer, PredicateFilter};
|
||||
|
||||
/// For associated types we include both bounds written on the type
|
||||
|
@ -38,7 +37,7 @@ fn associated_type_bounds<'tcx>(
|
|||
);
|
||||
|
||||
let icx = ItemCtxt::new(tcx, assoc_item_def_id);
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
|
||||
// Associated types are implicitly sized unless a `?Sized` bound is found
|
||||
match filter {
|
||||
|
@ -68,7 +67,7 @@ fn associated_type_bounds<'tcx>(
|
|||
)
|
||||
});
|
||||
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.clauses().chain(bounds_from_parent));
|
||||
let all_bounds = tcx.arena.alloc_from_iter(bounds.into_iter().chain(bounds_from_parent));
|
||||
debug!(
|
||||
"associated_type_bounds({}) = {:?}",
|
||||
tcx.def_path_str(assoc_item_def_id.to_def_id()),
|
||||
|
@ -327,7 +326,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
) -> &'tcx [(ty::Clause<'tcx>, Span)] {
|
||||
ty::print::with_reduced_queries!({
|
||||
let icx = ItemCtxt::new(tcx, opaque_def_id);
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(item_ty, hir_bounds, &mut bounds, ty::List::empty(), filter);
|
||||
// Opaque types are implicitly sized unless a `?Sized` bound is found
|
||||
match filter {
|
||||
|
@ -343,7 +342,7 @@ fn opaque_type_bounds<'tcx>(
|
|||
}
|
||||
debug!(?bounds);
|
||||
|
||||
tcx.arena.alloc_from_iter(bounds.clauses())
|
||||
tcx.arena.alloc_slice(&bounds)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,6 @@ use rustc_span::{DUMMY_SP, Ident, Span};
|
|||
use tracing::{debug, instrument, trace};
|
||||
|
||||
use super::item_bounds::explicit_item_bounds_with_filter;
|
||||
use crate::bounds::Bounds;
|
||||
use crate::collect::ItemCtxt;
|
||||
use crate::constrained_generic_params as cgp;
|
||||
use crate::delegation::inherit_predicates_for_delegation_item;
|
||||
|
@ -178,7 +177,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
// on a trait we must also consider the bounds that follow the trait's name,
|
||||
// like `trait Foo: A + B + C`.
|
||||
if let Some(self_bounds) = is_trait {
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(
|
||||
tcx.types.self_param,
|
||||
self_bounds,
|
||||
|
@ -186,7 +185,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
ty::List::empty(),
|
||||
PredicateFilter::All,
|
||||
);
|
||||
predicates.extend(bounds.clauses());
|
||||
predicates.extend(bounds);
|
||||
}
|
||||
|
||||
// In default impls, we can assume that the self type implements
|
||||
|
@ -209,7 +208,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
GenericParamKind::Lifetime { .. } => (),
|
||||
GenericParamKind::Type { .. } => {
|
||||
let param_ty = icx.lowerer().lower_ty_param(param.hir_id);
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
// Params are implicitly sized unless a `?Sized` bound is found
|
||||
icx.lowerer().add_sized_bound(
|
||||
&mut bounds,
|
||||
|
@ -219,7 +218,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
param.span,
|
||||
);
|
||||
trace!(?bounds);
|
||||
predicates.extend(bounds.clauses());
|
||||
predicates.extend(bounds);
|
||||
trace!(?predicates);
|
||||
}
|
||||
hir::GenericParamKind::Const { .. } => {
|
||||
|
@ -264,7 +263,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
}
|
||||
}
|
||||
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(
|
||||
ty,
|
||||
bound_pred.bounds,
|
||||
|
@ -272,7 +271,7 @@ fn gather_explicit_predicates_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Gen
|
|||
bound_vars,
|
||||
PredicateFilter::All,
|
||||
);
|
||||
predicates.extend(bounds.clauses());
|
||||
predicates.extend(bounds);
|
||||
}
|
||||
|
||||
hir::WherePredicateKind::RegionPredicate(region_pred) => {
|
||||
|
@ -627,7 +626,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
|
|||
let icx = ItemCtxt::new(tcx, trait_def_id);
|
||||
|
||||
let self_param_ty = tcx.types.self_param;
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
icx.lowerer().lower_bounds(self_param_ty, superbounds, &mut bounds, ty::List::empty(), filter);
|
||||
|
||||
let where_bounds_that_match =
|
||||
|
@ -635,7 +634,7 @@ pub(super) fn implied_predicates_with_filter<'tcx>(
|
|||
|
||||
// Combine the two lists to form the complete set of superbounds:
|
||||
let implied_bounds =
|
||||
&*tcx.arena.alloc_from_iter(bounds.clauses().chain(where_bounds_that_match));
|
||||
&*tcx.arena.alloc_from_iter(bounds.into_iter().chain(where_bounds_that_match));
|
||||
debug!(?implied_bounds);
|
||||
|
||||
// Now require that immediate supertraits are lowered, which will, in
|
||||
|
@ -904,7 +903,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
|||
param_def_id: LocalDefId,
|
||||
filter: PredicateFilter,
|
||||
) -> Vec<(ty::Clause<'tcx>, Span)> {
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
|
||||
for predicate in hir_generics.predicates {
|
||||
let hir_id = predicate.hir_id;
|
||||
|
@ -938,7 +937,7 @@ impl<'tcx> ItemCtxt<'tcx> {
|
|||
);
|
||||
}
|
||||
|
||||
bounds.clauses().collect()
|
||||
bounds
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1007,7 +1006,7 @@ pub(super) fn const_conditions<'tcx>(
|
|||
};
|
||||
|
||||
let icx = ItemCtxt::new(tcx, def_id);
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
|
||||
for pred in generics.predicates {
|
||||
match pred.kind {
|
||||
|
@ -1027,12 +1026,12 @@ pub(super) fn const_conditions<'tcx>(
|
|||
}
|
||||
|
||||
if let Some((def_id, supertraits)) = trait_def_id_and_supertraits {
|
||||
bounds.push_const_bound(
|
||||
tcx,
|
||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id())),
|
||||
ty::BoundConstness::Maybe,
|
||||
// We've checked above that the trait is conditionally const.
|
||||
bounds.push((
|
||||
ty::Binder::dummy(ty::TraitRef::identity(tcx, def_id.to_def_id()))
|
||||
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
||||
DUMMY_SP,
|
||||
);
|
||||
));
|
||||
|
||||
icx.lowerer().lower_bounds(
|
||||
tcx.types.self_param,
|
||||
|
@ -1045,7 +1044,7 @@ pub(super) fn const_conditions<'tcx>(
|
|||
|
||||
ty::ConstConditions {
|
||||
parent: has_parent.then(|| tcx.local_parent(def_id).to_def_id()),
|
||||
predicates: tcx.arena.alloc_from_iter(bounds.clauses().map(|(clause, span)| {
|
||||
predicates: tcx.arena.alloc_from_iter(bounds.into_iter().map(|(clause, span)| {
|
||||
(
|
||||
clause.kind().map_bound(|clause| match clause {
|
||||
ty::ClauseKind::HostEffect(ty::HostEffectPredicate {
|
||||
|
|
|
@ -8,7 +8,7 @@ use rustc_hir::HirId;
|
|||
use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{DefId, LocalDefId};
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt};
|
||||
use rustc_middle::ty::{self as ty, IsSuggestable, Ty, TyCtxt, Upcast};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym};
|
||||
use rustc_trait_selection::traits;
|
||||
use rustc_type_ir::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
|
||||
|
@ -16,7 +16,6 @@ use smallvec::SmallVec;
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use super::errors::GenericsArgsErrExtend;
|
||||
use crate::bounds::Bounds;
|
||||
use crate::errors;
|
||||
use crate::hir_ty_lowering::{
|
||||
AssocItemQSelf, FeedConstTy, HirTyLowerer, PredicateFilter, RegionInferReason,
|
||||
|
@ -28,7 +27,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
/// Doesn't add the bound if the HIR bounds contain any of `Sized`, `?Sized` or `!Sized`.
|
||||
pub(crate) fn add_sized_bound(
|
||||
&self,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
self_ty: Ty<'tcx>,
|
||||
hir_bounds: &'tcx [hir::GenericBound<'tcx>],
|
||||
self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>,
|
||||
|
@ -113,10 +112,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
if seen_sized_unbound || seen_negative_sized_bound || seen_positive_sized_bound {
|
||||
// There was in fact a `?Sized`, `!Sized` or explicit `Sized` bound;
|
||||
// we don't need to do anything.
|
||||
} else if sized_def_id.is_some() {
|
||||
} else if let Some(sized_def_id) = sized_def_id {
|
||||
// There was no `?Sized`, `!Sized` or explicit `Sized` bound;
|
||||
// add `Sized` if it's available.
|
||||
bounds.push_sized(tcx, self_ty, span);
|
||||
let trait_ref = ty::TraitRef::new(tcx, sized_def_id, [self_ty]);
|
||||
// Preferable to put this obligation first, since we report better errors for sized ambiguity.
|
||||
bounds.insert(0, (trait_ref.upcast(tcx), span));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -146,7 +147,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
&self,
|
||||
param_ty: Ty<'tcx>,
|
||||
hir_bounds: I,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
bound_vars: &'tcx ty::List<ty::BoundVariableKind>,
|
||||
predicate_filter: PredicateFilter,
|
||||
) where
|
||||
|
@ -189,14 +190,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
|
||||
let region = self.lower_lifetime(lifetime, RegionInferReason::OutlivesBound);
|
||||
bounds.push_region_bound(
|
||||
self.tcx(),
|
||||
ty::Binder::bind_with_vars(
|
||||
ty::OutlivesPredicate(param_ty, region),
|
||||
bound_vars,
|
||||
),
|
||||
lifetime.ident.span,
|
||||
let bound = ty::Binder::bind_with_vars(
|
||||
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(param_ty, region)),
|
||||
bound_vars,
|
||||
);
|
||||
bounds.push((bound.upcast(self.tcx()), lifetime.ident.span));
|
||||
}
|
||||
hir::GenericBound::Use(..) => {
|
||||
// We don't actually lower `use` into the type layer.
|
||||
|
@ -219,7 +217,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
hir_ref_id: hir::HirId,
|
||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||
constraint: &hir::AssocItemConstraint<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
duplicates: &mut FxIndexMap<DefId, Span>,
|
||||
path_span: Span,
|
||||
predicate_filter: PredicateFilter,
|
||||
|
@ -389,14 +387,13 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
PredicateFilter::All
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
bounds.push_projection_bound(
|
||||
tcx,
|
||||
projection_term.map_bound(|projection_term| ty::ProjectionPredicate {
|
||||
let bound = projection_term.map_bound(|projection_term| {
|
||||
ty::ClauseKind::Projection(ty::ProjectionPredicate {
|
||||
projection_term,
|
||||
term,
|
||||
}),
|
||||
constraint.span,
|
||||
);
|
||||
})
|
||||
});
|
||||
bounds.push((bound.upcast(tcx), constraint.span));
|
||||
}
|
||||
// SelfTraitThatDefines is only interested in trait predicates.
|
||||
PredicateFilter::SelfTraitThatDefines(_) => {}
|
||||
|
|
|
@ -17,7 +17,6 @@ use smallvec::{SmallVec, smallvec};
|
|||
use tracing::{debug, instrument};
|
||||
|
||||
use super::HirTyLowerer;
|
||||
use crate::bounds::Bounds;
|
||||
use crate::hir_ty_lowering::{
|
||||
GenericArgCountMismatch, GenericArgCountResult, PredicateFilter, RegionInferReason,
|
||||
};
|
||||
|
@ -36,7 +35,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
let tcx = self.tcx();
|
||||
let dummy_self = tcx.types.trait_object_dummy_self;
|
||||
|
||||
let mut user_written_bounds = Bounds::default();
|
||||
let mut user_written_bounds = Vec::new();
|
||||
let mut potential_assoc_types = Vec::new();
|
||||
for trait_bound in hir_bounds.iter() {
|
||||
if let hir::BoundPolarity::Maybe(_) = trait_bound.modifiers.polarity {
|
||||
|
@ -60,15 +59,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
|
||||
let (trait_bounds, mut projection_bounds) =
|
||||
traits::expand_trait_aliases(tcx, user_written_bounds.clauses());
|
||||
traits::expand_trait_aliases(tcx, user_written_bounds.iter().copied());
|
||||
let (regular_traits, mut auto_traits): (Vec<_>, Vec<_>) = trait_bounds
|
||||
.into_iter()
|
||||
.partition(|(trait_ref, _)| !tcx.trait_is_auto(trait_ref.def_id()));
|
||||
|
||||
// We don't support empty trait objects.
|
||||
if regular_traits.is_empty() && auto_traits.is_empty() {
|
||||
let guar =
|
||||
self.report_trait_object_with_no_traits_error(span, user_written_bounds.clauses());
|
||||
let guar = self.report_trait_object_with_no_traits_error(
|
||||
span,
|
||||
user_written_bounds.iter().copied(),
|
||||
);
|
||||
return Ty::new_error(tcx, guar);
|
||||
}
|
||||
// We don't support >1 principal
|
||||
|
@ -84,7 +85,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Check that there are no gross dyn-compatibility violations;
|
||||
// most importantly, that the supertraits don't contain `Self`,
|
||||
// to avoid ICEs.
|
||||
for (clause, span) in user_written_bounds.clauses() {
|
||||
for (clause, span) in user_written_bounds {
|
||||
if let Some(trait_pred) = clause.as_trait_clause() {
|
||||
let violations =
|
||||
hir_ty_lowering_dyn_compatibility_violations(tcx, trait_pred.def_id());
|
||||
|
|
|
@ -49,9 +49,9 @@ use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw};
|
|||
use rustc_trait_selection::infer::InferCtxtExt;
|
||||
use rustc_trait_selection::traits::wf::object_region_bounds;
|
||||
use rustc_trait_selection::traits::{self, ObligationCtxt};
|
||||
use rustc_type_ir::Upcast;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::bounds::Bounds;
|
||||
use crate::check::check_abi_fn_ptr;
|
||||
use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, InvalidBaseType};
|
||||
use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint};
|
||||
|
@ -691,7 +691,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
constness: hir::BoundConstness,
|
||||
polarity: hir::BoundPolarity,
|
||||
self_ty: Ty<'tcx>,
|
||||
bounds: &mut Bounds<'tcx>,
|
||||
bounds: &mut Vec<(ty::Clause<'tcx>, Span)>,
|
||||
predicate_filter: PredicateFilter,
|
||||
) -> GenericArgCountResult {
|
||||
let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
|
||||
|
@ -720,6 +720,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
bound_vars,
|
||||
);
|
||||
|
||||
debug!(?poly_trait_ref);
|
||||
|
||||
let polarity = match polarity {
|
||||
rustc_ast::BoundPolarity::Positive => ty::PredicatePolarity::Positive,
|
||||
rustc_ast::BoundPolarity::Negative(_) => ty::PredicatePolarity::Negative,
|
||||
|
@ -741,6 +743,26 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
}
|
||||
};
|
||||
|
||||
// We deal with const conditions later.
|
||||
match predicate_filter {
|
||||
PredicateFilter::All
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfTraitThatDefines(..)
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
let bound = poly_trait_ref.map_bound(|trait_ref| {
|
||||
ty::ClauseKind::Trait(ty::TraitPredicate { trait_ref, polarity })
|
||||
});
|
||||
let bound = (bound.upcast(tcx), span);
|
||||
// FIXME(-Znext-solver): We can likely remove this hack once the new trait solver lands.
|
||||
if tcx.is_lang_item(trait_def_id, rustc_hir::LangItem::Sized) {
|
||||
bounds.insert(0, bound);
|
||||
} else {
|
||||
bounds.push(bound);
|
||||
}
|
||||
}
|
||||
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {}
|
||||
}
|
||||
|
||||
if let hir::BoundConstness::Always(span) | hir::BoundConstness::Maybe(span) = constness
|
||||
&& !self.tcx().is_const_trait(trait_def_id)
|
||||
{
|
||||
|
@ -765,58 +787,53 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
suggestion_pre,
|
||||
suggestion,
|
||||
});
|
||||
}
|
||||
|
||||
match predicate_filter {
|
||||
// This is only concerned with trait predicates.
|
||||
PredicateFilter::SelfTraitThatDefines(..) => {
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||
}
|
||||
PredicateFilter::All
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
debug!(?poly_trait_ref);
|
||||
bounds.push_trait_bound(tcx, poly_trait_ref, span, polarity);
|
||||
|
||||
match constness {
|
||||
hir::BoundConstness::Always(span) => {
|
||||
if polarity == ty::PredicatePolarity::Positive {
|
||||
bounds.push_const_bound(
|
||||
tcx,
|
||||
poly_trait_ref,
|
||||
ty::BoundConstness::Const,
|
||||
span,
|
||||
);
|
||||
} else {
|
||||
match predicate_filter {
|
||||
// This is only concerned with trait predicates.
|
||||
PredicateFilter::SelfTraitThatDefines(..) => {}
|
||||
PredicateFilter::All
|
||||
| PredicateFilter::SelfOnly
|
||||
| PredicateFilter::SelfAndAssociatedTypeBounds => {
|
||||
match constness {
|
||||
hir::BoundConstness::Always(span) => {
|
||||
if polarity == ty::PredicatePolarity::Positive {
|
||||
bounds.push((
|
||||
poly_trait_ref
|
||||
.to_host_effect_clause(tcx, ty::BoundConstness::Const),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
hir::BoundConstness::Maybe(_) => {
|
||||
// We don't emit a const bound here, since that would mean that we
|
||||
// unconditionally need to prove a `HostEffect` predicate, even when
|
||||
// the predicates are being instantiated in a non-const context. This
|
||||
// is instead handled in the `const_conditions` query.
|
||||
}
|
||||
hir::BoundConstness::Never => {}
|
||||
}
|
||||
hir::BoundConstness::Maybe(_) => {
|
||||
// We don't emit a const bound here, since that would mean that we
|
||||
// unconditionally need to prove a `HostEffect` predicate, even when
|
||||
// the predicates are being instantiated in a non-const context. This
|
||||
// is instead handled in the `const_conditions` query.
|
||||
}
|
||||
// On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
|
||||
// `~const` bounds. All other predicates are handled in their respective queries.
|
||||
//
|
||||
// Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
|
||||
// here because we only call this on self bounds, and deal with the recursive case
|
||||
// in `lower_assoc_item_constraint`.
|
||||
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => {
|
||||
match constness {
|
||||
hir::BoundConstness::Maybe(span) => {
|
||||
if polarity == ty::PredicatePolarity::Positive {
|
||||
bounds.push((
|
||||
poly_trait_ref
|
||||
.to_host_effect_clause(tcx, ty::BoundConstness::Maybe),
|
||||
span,
|
||||
));
|
||||
}
|
||||
}
|
||||
hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
|
||||
}
|
||||
hir::BoundConstness::Never => {}
|
||||
}
|
||||
}
|
||||
// On the flip side, when filtering `ConstIfConst` bounds, we only need to convert
|
||||
// `~const` bounds. All other predicates are handled in their respective queries.
|
||||
//
|
||||
// Note that like `PredicateFilter::SelfOnly`, we don't need to do any filtering
|
||||
// here because we only call this on self bounds, and deal with the recursive case
|
||||
// in `lower_assoc_item_constraint`.
|
||||
PredicateFilter::ConstIfConst | PredicateFilter::SelfConstIfConst => match constness {
|
||||
hir::BoundConstness::Maybe(span) => {
|
||||
if polarity == ty::PredicatePolarity::Positive {
|
||||
bounds.push_const_bound(
|
||||
tcx,
|
||||
poly_trait_ref,
|
||||
ty::BoundConstness::Maybe,
|
||||
span,
|
||||
);
|
||||
}
|
||||
}
|
||||
hir::BoundConstness::Always(_) | hir::BoundConstness::Never => {}
|
||||
},
|
||||
}
|
||||
|
||||
let mut dup_constraints = FxIndexMap::default();
|
||||
|
@ -2382,7 +2399,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
// Impl trait in bindings lower as an infer var with additional
|
||||
// set of type bounds.
|
||||
let self_ty = self.ty_infer(None, hir_ty.span);
|
||||
let mut bounds = Bounds::default();
|
||||
let mut bounds = Vec::new();
|
||||
self.lower_bounds(
|
||||
self_ty,
|
||||
hir_bounds.iter(),
|
||||
|
@ -2390,11 +2407,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
|
|||
ty::List::empty(),
|
||||
PredicateFilter::All,
|
||||
);
|
||||
self.register_trait_ascription_bounds(
|
||||
bounds.clauses().collect(),
|
||||
hir_ty.hir_id,
|
||||
hir_ty.span,
|
||||
);
|
||||
self.register_trait_ascription_bounds(bounds, hir_ty.hir_id, hir_ty.span);
|
||||
self_ty
|
||||
}
|
||||
// If we encounter a type relative path with RTN generics, then it must have
|
||||
|
|
|
@ -80,7 +80,6 @@ This API is completely unstable and subject to change.
|
|||
pub mod check;
|
||||
|
||||
pub mod autoderef;
|
||||
mod bounds;
|
||||
mod check_unused;
|
||||
mod coherence;
|
||||
mod collect;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue