Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

HIR analysis: Remove unnecessary abstraction over list of clauses #137100

Merged
merged 1 commit into from
Feb 17, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 0 additions & 100 deletions compiler/rustc_hir_analysis/src/bounds.rs

This file was deleted.

9 changes: 4 additions & 5 deletions compiler/rustc_hir_analysis/src/collect/item_bounds.rs
Original file line number Diff line number Diff line change
@@ -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)
})
}

35 changes: 17 additions & 18 deletions compiler/rustc_hir_analysis/src/collect/predicates_of.rs
Original file line number Diff line number Diff line change
@@ -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,15 +177,15 @@ 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,
&mut bounds,
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,15 +263,15 @@ 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,
&mut bounds,
bound_vars,
PredicateFilter::All,
);
predicates.extend(bounds.clauses());
predicates.extend(bounds);
}

hir::WherePredicateKind::RegionPredicate(region_pred) => {
@@ -627,15 +626,15 @@ 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 =
icx.probe_ty_param_bounds_in_generics(generics, item.owner_id.def_id, filter);

// 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 {
37 changes: 17 additions & 20 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs
Original file line number Diff line number Diff line change
@@ -8,15 +8,14 @@ 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};
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(_) => {}
Original file line number Diff line number Diff line change
@@ -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());
123 changes: 68 additions & 55 deletions compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
Original file line number Diff line number Diff line change
@@ -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.
}
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,
);
// 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::Always(_) | hir::BoundConstness::Never => {}
},
}
}

let mut dup_constraints = FxIndexMap::default();
@@ -2382,19 +2399,15 @@ 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(),
&mut bounds,
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
1 change: 0 additions & 1 deletion compiler/rustc_hir_analysis/src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/generic_args.rs
Original file line number Diff line number Diff line change
@@ -495,7 +495,7 @@ impl<'tcx> GenericArgs<'tcx> {
self.iter().filter_map(|k| k.as_const())
}

/// Returns generic arguments that are not lifetimes or host effect params.
/// Returns generic arguments that are not lifetimes.
#[inline]
pub fn non_erasable_generics(
&'tcx self,
Loading