From 758bedc10454b1d101613f4b363fe54c7a405b00 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Apr 2023 23:11:19 +0000 Subject: [PATCH 1/2] Make elaborator generic --- .../src/check/compare_impl_item.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- .../src/collect/item_bounds.rs | 2 +- .../src/impl_wf_check/min_specialization.rs | 12 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- .../rustc_hir_typeck/src/method/confirm.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- compiler/rustc_infer/src/traits/util.rs | 209 ++++++++++-------- compiler/rustc_lint/src/unused.rs | 33 ++- .../rustc_mir_transform/src/const_prop.rs | 5 +- .../src/const_prop_lint.rs | 5 +- .../src/solve/assembly.rs | 4 +- .../src/traits/auto_trait.rs | 8 +- .../src/traits/coherence.rs | 2 +- .../src/traits/error_reporting/ambiguity.rs | 4 +- .../src/traits/error_reporting/mod.rs | 2 +- .../rustc_trait_selection/src/traits/mod.rs | 7 +- .../src/traits/object_safety.rs | 4 +- .../rustc_trait_selection/src/traits/wf.rs | 4 +- .../src/needless_pass_by_value.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 21 files changed, 163 insertions(+), 155 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 2d509a114ad..f6c2004c4a6 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2034,7 +2034,7 @@ pub(super) fn check_type_bounds<'tcx>( ObligationCause::new(impl_ty_span, impl_ty_def_id, code) }; - let obligations = tcx + let obligations: Vec<_> = tcx .bound_explicit_item_bounds(trait_ty.def_id) .subst_iter_copied(tcx, rebased_substs) .map(|(concrete_ty_bound, span)| { @@ -2044,7 +2044,7 @@ pub(super) fn check_type_bounds<'tcx>( .collect(); debug!("check_type_bounds: item_bounds={:?}", obligations); - for mut obligation in util::elaborate_obligations(tcx, obligations) { + for mut obligation in util::elaborate(tcx, obligations) { let normalized_predicate = ocx.normalize(&normalize_cause, normalize_param_env, obligation.predicate); debug!("compare_projection_bounds: normalized predicate = {:?}", normalized_predicate); diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 24cc58ee344..c03621fcfb2 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1908,7 +1908,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { let predicates_with_span = tcx.predicates_of(self.body_def_id).predicates.iter().copied(); // Check elaborated bounds. - let implied_obligations = traits::elaborate_predicates_with_span(tcx, predicates_with_span); + let implied_obligations = traits::elaborate(tcx, predicates_with_span); for (pred, obligation_span) in implied_obligations { // We lower empty bounds like `Vec:` as diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs index d2e45c28658..2e56d24638c 100644 --- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs +++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs @@ -130,7 +130,7 @@ pub(super) fn item_bounds( tcx: TyCtxt<'_>, def_id: DefId, ) -> ty::EarlyBinder<&'_ ty::List>> { - let bounds = tcx.mk_predicates_from_iter(util::elaborate_predicates( + let bounds = tcx.mk_predicates_from_iter(util::elaborate( tcx, tcx.explicit_item_bounds(def_id).iter().map(|&(bound, _span)| bound), )); diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index b5bae5788f6..35785e81ff4 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -318,15 +318,14 @@ fn check_predicates<'tcx>( span: Span, ) { let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs); - let impl1_predicates: Vec<_> = - traits::elaborate_predicates_with_span(tcx, instantiated.into_iter()).collect(); + let impl1_predicates: Vec<_> = traits::elaborate(tcx, instantiated.into_iter()).collect(); let mut impl2_predicates = if impl2_node.is_from_trait() { // Always applicable traits have to be always applicable without any // assumptions. Vec::new() } else { - traits::elaborate_predicates( + traits::elaborate( tcx, tcx.predicates_of(impl2_node.def_id()) .instantiate(tcx, impl2_substs) @@ -371,11 +370,10 @@ fn check_predicates<'tcx>( .unwrap(); assert!(!obligations.needs_infer()); - impl2_predicates.extend( - traits::elaborate_obligations(tcx, obligations).map(|obligation| obligation.predicate), - ) + impl2_predicates + .extend(traits::elaborate(tcx, obligations).map(|obligation| obligation.predicate)) } - impl2_predicates.extend(traits::elaborate_predicates(tcx, always_applicable_traits)); + impl2_predicates.extend(traits::elaborate(tcx, always_applicable_traits)); for (predicate, span) in impl1_predicates { if !impl2_predicates.iter().any(|pred2| trait_predicates_eq(tcx, predicate, *pred2, span)) { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 47a8b080166..15eec42d786 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -204,7 +204,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut expected_sig = None; let mut expected_kind = None; - for (pred, span) in traits::elaborate_predicates_with_span( + for (pred, span) in traits::elaborate( self.tcx, // Reverse the obligations here, since `elaborate_*` uses a stack, // and we want to keep inference generally in the same order of diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index 2762e778591..9155a3d8daa 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -574,7 +574,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { ) -> Option { let sized_def_id = self.tcx.lang_items().sized_trait()?; - traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied()) + traits::elaborate(self.tcx, predicates.predicates.iter().copied()) // We don't care about regions here. .filter_map(|pred| match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index dab709e17f0..0092bd2c6e6 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -1555,8 +1555,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; let parent_o = o.clone(); - let implied_obligations = - traits::elaborate_obligations(self.tcx, vec![o]); + let implied_obligations = traits::elaborate(self.tcx, vec![o]); for o in implied_obligations { let parent = if o == parent_o { None diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index f3797499866..c5095a76f42 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -1,7 +1,7 @@ use smallvec::smallvec; use crate::infer::outlives::components::{push_outlives_components, Component}; -use crate::traits::{self, Obligation, ObligationCause, PredicateObligation}; +use crate::traits::{self, Obligation, PredicateObligation}; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_middle::ty::{self, ToPredicate, TyCtxt}; use rustc_span::symbol::Ident; @@ -66,99 +66,143 @@ impl<'tcx> Extend> for PredicateSet<'tcx> { /// if we know that `T: Ord`, the elaborator would deduce that `T: PartialOrd` /// holds as well. Similarly, if we have `trait Foo: 'static`, and we know that /// `T: Foo`, then we know that `T: 'static`. -pub struct Elaborator<'tcx> { - stack: Vec>, +pub struct Elaborator<'tcx, O> { + stack: Vec, visited: PredicateSet<'tcx>, } +/// Describes how to elaborate an obligation into a sub-obligation. +/// +/// For [`Obligation`], a sub-obligation is combined with the current obligation's +/// param-env and cause code. For [`ty::Predicate`], none of this is needed, since +/// there is no param-env or cause code to copy over. +pub trait Elaboratable<'tcx> { + fn predicate(&self) -> ty::Predicate<'tcx>; + + // Makes a new `Self` but with a different predicate. + fn child(&self, predicate: ty::Predicate<'tcx>) -> Self; + + // Makes a new `Self` but with a different predicate and a different cause + // code (if `Self` has one). + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + span: Span, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + index: usize, + ) -> Self; +} + +impl<'tcx> Elaboratable<'tcx> for PredicateObligation<'tcx> { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.predicate + } + + fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + Obligation { + cause: self.cause.clone(), + param_env: self.param_env, + recursion_depth: 0, + predicate, + } + } + + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + span: Span, + parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + index: usize, + ) -> Self { + let cause = self.cause.clone().derived_cause(parent_trait_pred, |derived| { + traits::ImplDerivedObligation(Box::new(traits::ImplDerivedObligationCause { + derived, + impl_or_alias_def_id: parent_trait_pred.def_id(), + impl_def_predicate_index: Some(index), + span, + })) + }); + Obligation { cause, param_env: self.param_env, recursion_depth: 0, predicate } + } +} + +impl<'tcx> Elaboratable<'tcx> for ty::Predicate<'tcx> { + fn predicate(&self) -> ty::Predicate<'tcx> { + *self + } + + fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + predicate + } + + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + predicate + } +} + +impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { + fn predicate(&self) -> ty::Predicate<'tcx> { + self.0 + } + + fn child(&self, predicate: ty::Predicate<'tcx>) -> Self { + (predicate, self.1) + } + + fn child_with_derived_cause( + &self, + predicate: ty::Predicate<'tcx>, + _span: Span, + _parent_trait_pred: ty::PolyTraitPredicate<'tcx>, + _index: usize, + ) -> Self { + (predicate, self.1) + } +} + pub fn elaborate_trait_ref<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, -) -> impl Iterator> { - elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx))) +) -> Elaborator<'tcx, ty::Predicate<'tcx>> { + elaborate(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx))) } pub fn elaborate_trait_refs<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator>, -) -> impl Iterator> { - let predicates = trait_refs.map(move |trait_ref| trait_ref.without_const().to_predicate(tcx)); - elaborate_predicates(tcx, predicates) +) -> Elaborator<'tcx, ty::Predicate<'tcx>> { + elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx))) } -pub fn elaborate_predicates<'tcx>( +pub fn elaborate<'tcx, O: Elaboratable<'tcx>>( tcx: TyCtxt<'tcx>, - predicates: impl Iterator>, -) -> impl Iterator> { - elaborate_obligations( - tcx, - predicates - .map(|predicate| { - Obligation::new( - tcx, - // We'll dump the cause/param-env later - ObligationCause::dummy(), - ty::ParamEnv::empty(), - predicate, - ) - }) - .collect(), - ) - .map(|obl| obl.predicate) -} - -pub fn elaborate_predicates_with_span<'tcx>( - tcx: TyCtxt<'tcx>, - predicates: impl Iterator, Span)>, -) -> impl Iterator, Span)> { - elaborate_obligations( - tcx, - predicates - .map(|(predicate, span)| { - Obligation::new( - tcx, - // We'll dump the cause/param-env later - ObligationCause::dummy_with_span(span), - ty::ParamEnv::empty(), - predicate, - ) - }) - .collect(), - ) - .map(|obl| (obl.predicate, obl.cause.span)) -} - -pub fn elaborate_obligations<'tcx>( - tcx: TyCtxt<'tcx>, - obligations: Vec>, -) -> Elaborator<'tcx> { + obligations: impl IntoIterator, +) -> Elaborator<'tcx, O> { let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) }; elaborator.extend_deduped(obligations); elaborator } -fn predicate_obligation<'tcx>( - predicate: ty::Predicate<'tcx>, - param_env: ty::ParamEnv<'tcx>, - cause: ObligationCause<'tcx>, -) -> PredicateObligation<'tcx> { - Obligation { cause, param_env, recursion_depth: 0, predicate } -} - -impl<'tcx> Elaborator<'tcx> { - fn extend_deduped(&mut self, obligations: impl IntoIterator>) { +impl<'tcx, O: Elaboratable<'tcx>> Elaborator<'tcx, O> { + fn extend_deduped(&mut self, obligations: impl IntoIterator) { // Only keep those bounds that we haven't already seen. // This is necessary to prevent infinite recursion in some // cases. One common case is when people define // `trait Sized: Sized { }` rather than `trait Sized { }`. // let visited = &mut self.visited; - self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate))); + self.stack.extend(obligations.into_iter().filter(|o| self.visited.insert(o.predicate()))); } - fn elaborate(&mut self, obligation: &PredicateObligation<'tcx>) { + fn elaborate(&mut self, elaboratable: &O) { let tcx = self.visited.tcx; - let bound_predicate = obligation.predicate.kind(); + let bound_predicate = elaboratable.predicate().kind(); match bound_predicate.skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(data)) => { // Get predicates declared on the trait. @@ -170,24 +214,11 @@ impl<'tcx> Elaborator<'tcx> { if data.constness == ty::BoundConstness::NotConst { pred = pred.without_const(tcx); } - - let cause = obligation.cause.clone().derived_cause( - bound_predicate.rebind(data), - |derived| { - traits::ImplDerivedObligation(Box::new( - traits::ImplDerivedObligationCause { - derived, - impl_or_alias_def_id: data.def_id(), - impl_def_predicate_index: Some(index), - span, - }, - )) - }, - ); - predicate_obligation( + elaboratable.child_with_derived_cause( pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), - obligation.param_env, - cause, + span, + bound_predicate.rebind(data), + index, ) }); debug!(?data, ?obligations, "super_predicates"); @@ -290,13 +321,7 @@ impl<'tcx> Elaborator<'tcx> { .map(|predicate_kind| { bound_predicate.rebind(predicate_kind).to_predicate(tcx) }) - .map(|predicate| { - predicate_obligation( - predicate, - obligation.param_env, - obligation.cause.clone(), - ) - }), + .map(|predicate| elaboratable.child(predicate)), ); } ty::PredicateKind::TypeWellFormedFromEnv(..) => { @@ -313,8 +338,8 @@ impl<'tcx> Elaborator<'tcx> { } } -impl<'tcx> Iterator for Elaborator<'tcx> { - type Item = PredicateObligation<'tcx>; +impl<'tcx, O: Elaboratable<'tcx>> Iterator for Elaborator<'tcx, O> { + type Item = O; fn size_hint(&self) -> (usize, Option) { (self.stack.len(), None) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ad328006051..35c461f5ace 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -12,7 +12,7 @@ use rustc_errors::{pluralize, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_infer::traits::util::elaborate_predicates_with_span; +use rustc_infer::traits::util::elaborate; use rustc_middle::ty::adjustment; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::Symbol; @@ -254,24 +254,21 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { } ty::Adt(def, _) => is_def_must_use(cx, def.did(), span), ty::Alias(ty::Opaque, ty::AliasTy { def_id: def, .. }) => { - elaborate_predicates_with_span( - cx.tcx, - cx.tcx.explicit_item_bounds(def).iter().cloned(), - ) - .find_map(|(pred, _span)| { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::PredicateKind::Clause(ty::Clause::Trait( - ref poly_trait_predicate, - )) = pred.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; + elaborate(cx.tcx, cx.tcx.explicit_item_bounds(def).iter().cloned()) + .find_map(|(pred, _span)| { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::PredicateKind::Clause(ty::Clause::Trait( + ref poly_trait_predicate, + )) = pred.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; - is_def_must_use(cx, def_id, span) - } else { - None - } - }) - .map(|inner| MustUsePath::Opaque(Box::new(inner))) + is_def_must_use(cx, def_id, span) + } else { + None + } + }) + .map(|inner| MustUsePath::Opaque(Box::new(inner))) } ty::Dynamic(binders, _, _) => binders.iter().find_map(|predicate| { if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs index ac55948e61b..839d5422ad1 100644 --- a/compiler/rustc_mir_transform/src/const_prop.rs +++ b/compiler/rustc_mir_transform/src/const_prop.rs @@ -115,10 +115,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp { .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - if traits::impossible_predicates( - tcx, - traits::elaborate_predicates(tcx, predicates).collect(), - ) { + if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id); return; } diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs index 942ccd5a9d1..85e229b694c 100644 --- a/compiler/rustc_mir_transform/src/const_prop_lint.rs +++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs @@ -91,10 +91,7 @@ impl<'tcx> MirLint<'tcx> for ConstProp { .predicates .iter() .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); - if traits::impossible_predicates( - tcx, - traits::elaborate_predicates(tcx, predicates).collect(), - ) { + if traits::impossible_predicates(tcx, traits::elaborate(tcx, predicates).collect()) { trace!("ConstProp skipped for {:?}: found unsatisfiable predicates", def_id); return; } diff --git a/compiler/rustc_trait_selection/src/solve/assembly.rs b/compiler/rustc_trait_selection/src/solve/assembly.rs index f8a54f73a33..6476da7ba48 100644 --- a/compiler/rustc_trait_selection/src/solve/assembly.rs +++ b/compiler/rustc_trait_selection/src/solve/assembly.rs @@ -9,7 +9,7 @@ use itertools::Itertools; use rustc_data_structures::fx::FxIndexSet; use rustc_hir::def_id::DefId; use rustc_infer::traits::query::NoSolution; -use rustc_infer::traits::util::elaborate_predicates; +use rustc_infer::traits::util::elaborate; use rustc_middle::traits::solve::{CanonicalResponse, Certainty, Goal, MaybeCause, QueryResult}; use rustc_middle::ty::fast_reject::TreatProjections; use rustc_middle::ty::TypeFoldable; @@ -498,7 +498,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { let tcx = self.tcx(); let own_bounds: FxIndexSet<_> = bounds.iter().map(|bound| bound.with_self_ty(tcx, self_ty)).collect(); - for assumption in elaborate_predicates(tcx, own_bounds.iter().copied()) { + for assumption in elaborate(tcx, own_bounds.iter().copied()) { // FIXME: Predicates are fully elaborated in the object type's existential bounds // list. We want to only consider these pre-elaborated projections, and not other // projection predicates that we reach by elaborating the principal trait ref, diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 878c502655c..a53d414be9e 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -234,7 +234,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { /// constructed once for a given type. As part of the construction process, the `ParamEnv` will /// have any supertrait bounds normalized -- e.g., if we have a type `struct Foo`, the /// `ParamEnv` will contain `T: Copy` and `T: Clone`, since `Copy: Clone`. When we construct our - /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate_predicates`, or + /// own `ParamEnv`, we need to do this ourselves, through `traits::elaborate`, or /// else `SelectionContext` will choke on the missing predicates. However, this should never /// show up in the final synthesized generics: we don't want our generated docs page to contain /// something like `T: Copy + Clone`, as that's redundant. Therefore, we keep track of a @@ -346,10 +346,8 @@ impl<'tcx> AutoTraitFinder<'tcx> { _ => panic!("Unexpected error for '{:?}': {:?}", ty, result), }; - let normalized_preds = elaborate_predicates( - tcx, - computed_preds.clone().chain(user_computed_preds.iter().cloned()), - ); + let normalized_preds = + elaborate(tcx, computed_preds.clone().chain(user_computed_preds.iter().cloned())); new_env = ty::ParamEnv::new( tcx.mk_predicates_from_iter(normalized_preds), param_env.reveal(), diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index d360158fdf8..53d4f95e9e3 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -368,7 +368,7 @@ fn negative_impl_exists<'tcx>( } // Try to prove a negative obligation exists for super predicates - for pred in util::elaborate_predicates(infcx.tcx, iter::once(o.predicate)) { + for pred in util::elaborate(infcx.tcx, iter::once(o.predicate)) { if resolve_negative_obligation(infcx.fork(), &o.with(infcx.tcx, pred), body_def_id) { return true; } diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs index 672b3365ff4..0475f24d87c 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/ambiguity.rs @@ -1,6 +1,6 @@ use rustc_hir::def_id::DefId; use rustc_infer::infer::{InferCtxt, LateBoundRegionConversionTime}; -use rustc_infer::traits::util::elaborate_predicates_with_span; +use rustc_infer::traits::util::elaborate; use rustc_infer::traits::{Obligation, ObligationCause, TraitObligation}; use rustc_middle::ty; use rustc_span::{Span, DUMMY_SP}; @@ -82,7 +82,7 @@ pub fn recompute_applicable_impls<'tcx>( let predicates = tcx.predicates_of(obligation.cause.body_id.to_def_id()).instantiate_identity(tcx); - for (pred, span) in elaborate_predicates_with_span(tcx, predicates.into_iter()) { + for (pred, span) in elaborate(tcx, predicates.into_iter()) { let kind = pred.kind(); if let ty::PredicateKind::Clause(ty::Clause::Trait(trait_pred)) = kind.skip_binder() && param_env_candidate_may_apply(kind.rebind(trait_pred)) diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs index c19798213b7..6ebf056f0e8 100644 --- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs @@ -1624,7 +1624,7 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> { } }; - for pred in super::elaborate_predicates(self.tcx, std::iter::once(cond)) { + for pred in super::elaborate(self.tcx, std::iter::once(cond)) { let bound_predicate = pred.kind(); if let ty::PredicateKind::Clause(ty::Clause::Trait(implication)) = bound_predicate.skip_binder() diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 8d831dca6e3..1094a77fe14 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -58,10 +58,7 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError} pub use self::structural_match::{ search_for_adt_const_param_violation, search_for_structural_match_violation, }; -pub use self::util::{ - elaborate_obligations, elaborate_predicates, elaborate_predicates_with_span, - elaborate_trait_ref, elaborate_trait_refs, -}; +pub use self::util::{elaborate, elaborate_trait_ref, elaborate_trait_refs}; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; pub use self::util::{ @@ -267,7 +264,7 @@ pub fn normalize_param_env_or_error<'tcx>( // and errors will get reported then; so outside of type inference we // can be sure that no errors should occur. let mut predicates: Vec<_> = - util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()).collect(); + util::elaborate(tcx, unnormalized_env.caller_bounds().into_iter()).collect(); debug!("normalize_param_env_or_error: elaborated-predicates={:?}", predicates); diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index dbf6b78572a..9953d048f75 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -8,7 +8,7 @@ //! - not reference the erased type `Self` except for in this receiver; //! - not have generic type parameters. -use super::{elaborate_predicates, elaborate_trait_ref}; +use super::{elaborate, elaborate_trait_ref}; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; @@ -379,7 +379,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool { // Search for a predicate like `Self : Sized` amongst the trait bounds. let predicates = tcx.predicates_of(def_id); let predicates = predicates.instantiate_identity(tcx).predicates; - elaborate_predicates(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() { + elaborate(tcx, predicates.into_iter()).any(|pred| match pred.kind().skip_binder() { ty::PredicateKind::Clause(ty::Clause::Trait(ref trait_pred)) => { trait_pred.def_id() == sized_def_id && trait_pred.self_ty().is_param(0) } diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 156674e33c3..3d026506a5a 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -364,7 +364,7 @@ impl<'tcx> WfPredicates<'tcx> { }; if let Elaborate::All = elaborate { - let implied_obligations = traits::util::elaborate_obligations(tcx, obligations); + let implied_obligations = traits::util::elaborate(tcx, obligations); let implied_obligations = implied_obligations.map(extend); self.out.extend(implied_obligations); } else { @@ -920,7 +920,7 @@ pub(crate) fn required_region_bounds<'tcx>( ) -> Vec> { assert!(!erased_self_ty.has_escaping_bound_vars()); - traits::elaborate_predicates(tcx, predicates) + traits::elaborate(tcx, predicates) .filter_map(|pred| { debug!(?pred); match pred.kind().skip_binder() { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 327e090d38b..0bb1775aae9 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -122,7 +122,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { let sized_trait = need!(cx.tcx.lang_items().sized_trait()); - let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter()) + let preds = traits::elaborate(cx.tcx, cx.param_env.caller_bounds().iter()) .filter(|p| !p.is_global()) .filter_map(|pred| { // Note that we do not want to deal with qualified predicates here. diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 619aa9f4bf6..9051cf51658 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2104,7 +2104,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool { .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None }); traits::impossible_predicates( cx.tcx, - traits::elaborate_predicates(cx.tcx, predicates) + traits::elaborate(cx.tcx, predicates) .collect::>(), ) } From 2cd0729d635a47bc585c683b36cd72cf884eb258 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Thu, 6 Apr 2023 23:24:03 +0000 Subject: [PATCH 2/2] Get rid of elaborate_trait_ref{s} too --- .../rustc_hir_analysis/src/astconv/mod.rs | 6 ++--- compiler/rustc_infer/src/traits/util.rs | 24 ++++++------------- .../rustc_trait_selection/src/traits/mod.rs | 2 +- .../src/traits/object_safety.rs | 5 ++-- 4 files changed, 14 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs index e25b07d9392..6727173cd88 100644 --- a/compiler/rustc_hir_analysis/src/astconv/mod.rs +++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs @@ -33,9 +33,9 @@ use rustc_middle::infer::unify_key::{ConstVariableOrigin, ConstVariableOriginKin use rustc_middle::middle::stability::AllowUnstable; use rustc_middle::ty::fold::FnMutDelegate; use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, SubstsRef}; -use rustc_middle::ty::DynKind; use rustc_middle::ty::GenericParamDefKind; use rustc_middle::ty::{self, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{DynKind, ToPredicate}; use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS}; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::edition::Edition; @@ -1526,8 +1526,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { for (base_trait_ref, span, constness) in regular_traits_refs_spans { assert_eq!(constness, ty::BoundConstness::NotConst); - - for pred in traits::elaborate_trait_ref(tcx, base_trait_ref) { + let base_pred: ty::Predicate<'tcx> = base_trait_ref.to_predicate(tcx); + for pred in traits::elaborate(tcx, [base_pred]) { debug!("conv_object_ty_poly_trait_ref: observing object predicate `{:?}`", pred); let bound_predicate = pred.kind(); diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index c5095a76f42..c7f7ed14940 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -166,20 +166,6 @@ impl<'tcx> Elaboratable<'tcx> for (ty::Predicate<'tcx>, Span) { } } -pub fn elaborate_trait_ref<'tcx>( - tcx: TyCtxt<'tcx>, - trait_ref: ty::PolyTraitRef<'tcx>, -) -> Elaborator<'tcx, ty::Predicate<'tcx>> { - elaborate(tcx, std::iter::once(trait_ref.without_const().to_predicate(tcx))) -} - -pub fn elaborate_trait_refs<'tcx>( - tcx: TyCtxt<'tcx>, - trait_refs: impl Iterator>, -) -> Elaborator<'tcx, ty::Predicate<'tcx>> { - elaborate(tcx, trait_refs.map(|trait_ref| trait_ref.to_predicate(tcx))) -} - pub fn elaborate<'tcx, O: Elaboratable<'tcx>>( tcx: TyCtxt<'tcx>, obligations: impl IntoIterator, @@ -364,17 +350,21 @@ pub fn supertraits<'tcx>( tcx: TyCtxt<'tcx>, trait_ref: ty::PolyTraitRef<'tcx>, ) -> impl Iterator> { - FilterToTraits::new(elaborate_trait_ref(tcx, trait_ref)) + let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx); + FilterToTraits::new(elaborate(tcx, [pred])) } pub fn transitive_bounds<'tcx>( tcx: TyCtxt<'tcx>, trait_refs: impl Iterator>, ) -> impl Iterator> { - FilterToTraits::new(elaborate_trait_refs(tcx, trait_refs)) + FilterToTraits::new(elaborate( + tcx, + trait_refs.map(|trait_ref| -> ty::Predicate<'tcx> { trait_ref.to_predicate(tcx) }), + )) } -/// A specialized variant of `elaborate_trait_refs` that only elaborates trait references that may +/// A specialized variant of `elaborate` that only elaborates trait references that may /// define the given associated type `assoc_name`. It uses the /// `super_predicates_that_define_assoc_type` query to avoid enumerating super-predicates that /// aren't related to `assoc_item`. This is used when resolving types like `Self::Item` or diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 1094a77fe14..8a203dec86b 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -58,7 +58,7 @@ pub use self::specialize::{specialization_graph, translate_substs, OverlapError} pub use self::structural_match::{ search_for_adt_const_param_violation, search_for_structural_match_violation, }; -pub use self::util::{elaborate, elaborate_trait_ref, elaborate_trait_refs}; +pub use self::util::elaborate; pub use self::util::{expand_trait_aliases, TraitAliasExpander}; pub use self::util::{get_vtable_index_of_object_method, impl_item_is_final, upcast_choices}; pub use self::util::{ diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs index 9953d048f75..b8ad1925e4e 100644 --- a/compiler/rustc_trait_selection/src/traits/object_safety.rs +++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs @@ -8,7 +8,7 @@ //! - not reference the erased type `Self` except for in this receiver; //! - not have generic type parameters. -use super::{elaborate, elaborate_trait_ref}; +use super::elaborate; use crate::infer::TyCtxtInferExt; use crate::traits::query::evaluate_obligation::InferCtxtExt; @@ -666,7 +666,8 @@ fn object_ty_for_trait<'tcx>( }); debug!(?trait_predicate); - let mut elaborated_predicates: Vec<_> = elaborate_trait_ref(tcx, trait_ref) + let pred: ty::Predicate<'tcx> = trait_ref.to_predicate(tcx); + let mut elaborated_predicates: Vec<_> = elaborate(tcx, [pred]) .filter_map(|pred| { debug!(?pred); let pred = pred.to_opt_poly_projection_pred()?;