diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:50 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:19:50 +0000 |
commit | 2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35 (patch) | |
tree | d325add32978dbdc1db975a438b3a77d571b1ab8 /compiler/rustc_infer/src/traits | |
parent | Releasing progress-linux version 1.68.2+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.tar.xz rustc-2e00214b3efbdfeefaa0fe9e8b8fd519de7adc35.zip |
Merging upstream version 1.69.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_infer/src/traits')
-rw-r--r-- | compiler/rustc_infer/src/traits/engine.rs | 24 | ||||
-rw-r--r-- | compiler/rustc_infer/src/traits/mod.rs | 3 | ||||
-rw-r--r-- | compiler/rustc_infer/src/traits/structural_impls.rs | 17 | ||||
-rw-r--r-- | compiler/rustc_infer/src/traits/util.rs | 87 |
4 files changed, 81 insertions, 50 deletions
diff --git a/compiler/rustc_infer/src/traits/engine.rs b/compiler/rustc_infer/src/traits/engine.rs index d3519f4b3..f75344f20 100644 --- a/compiler/rustc_infer/src/traits/engine.rs +++ b/compiler/rustc_infer/src/traits/engine.rs @@ -1,6 +1,5 @@ use crate::infer::InferCtxt; use crate::traits::Obligation; -use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; use rustc_middle::ty::{self, ToPredicate, Ty}; @@ -37,13 +36,19 @@ pub trait TraitEngine<'tcx>: 'tcx { obligation: PredicateObligation<'tcx>, ); - fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>; - fn select_where_possible(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>; + fn collect_remaining_errors(&mut self) -> Vec<FulfillmentError<'tcx>>; + fn pending_obligations(&self) -> Vec<PredicateObligation<'tcx>>; - fn relationships(&mut self) -> &mut FxHashMap<ty::TyVid, ty::FoundRelationships>; + /// Among all pending obligations, collect those are stalled on a inference variable which has + /// changed since the last call to `select_where_possible`. Those obligations are marked as + /// successful and returned. + fn drain_unstalled_obligations( + &mut self, + infcx: &InferCtxt<'tcx>, + ) -> Vec<PredicateObligation<'tcx>>; } pub trait TraitEngineExt<'tcx> { @@ -52,6 +57,8 @@ pub trait TraitEngineExt<'tcx> { infcx: &InferCtxt<'tcx>, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>, ); + + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>>; } impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { @@ -64,4 +71,13 @@ impl<'tcx, T: ?Sized + TraitEngine<'tcx>> TraitEngineExt<'tcx> for T { self.register_predicate_obligation(infcx, obligation); } } + + fn select_all_or_error(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<FulfillmentError<'tcx>> { + let errors = self.select_where_possible(infcx); + if !errors.is_empty() { + return errors; + } + + self.collect_remaining_errors() + } } diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs index 026713b6a..3a8289966 100644 --- a/compiler/rustc_infer/src/traits/mod.rs +++ b/compiler/rustc_infer/src/traits/mod.rs @@ -8,6 +8,7 @@ mod project; mod structural_impls; pub mod util; +use hir::def_id::LocalDefId; use rustc_hir as hir; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, Const, ToPredicate, Ty, TyCtxt}; @@ -146,7 +147,7 @@ impl<'tcx, O> Obligation<'tcx, O> { pub fn misc( tcx: TyCtxt<'tcx>, span: Span, - body_id: hir::HirId, + body_id: LocalDefId, param_env: ty::ParamEnv<'tcx>, trait_ref: impl ToPredicate<'tcx, O>, ) -> Obligation<'tcx, O> { diff --git a/compiler/rustc_infer/src/traits/structural_impls.rs b/compiler/rustc_infer/src/traits/structural_impls.rs index 1c6ab6a08..3a5273b03 100644 --- a/compiler/rustc_infer/src/traits/structural_impls.rs +++ b/compiler/rustc_infer/src/traits/structural_impls.rs @@ -1,8 +1,8 @@ use crate::traits; use crate::traits::project::Normalized; -use rustc_middle::ty; use rustc_middle::ty::fold::{FallibleTypeFolder, TypeFoldable}; use rustc_middle::ty::visit::{TypeVisitable, TypeVisitor}; +use rustc_middle::ty::{self, TyCtxt}; use std::fmt; use std::ops::ControlFlow; @@ -61,8 +61,13 @@ impl<'tcx> fmt::Debug for traits::MismatchedProjectionTypes<'tcx> { /////////////////////////////////////////////////////////////////////////// // TypeFoldable implementations. -impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx, O> { - fn try_fold_with<F: FallibleTypeFolder<'tcx>>(self, folder: &mut F) -> Result<Self, F::Error> { +impl<'tcx, O: TypeFoldable<TyCtxt<'tcx>>> TypeFoldable<TyCtxt<'tcx>> + for traits::Obligation<'tcx, O> +{ + fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>( + self, + folder: &mut F, + ) -> Result<Self, F::Error> { Ok(traits::Obligation { cause: self.cause, recursion_depth: self.recursion_depth, @@ -72,8 +77,10 @@ impl<'tcx, O: TypeFoldable<'tcx>> TypeFoldable<'tcx> for traits::Obligation<'tcx } } -impl<'tcx, O: TypeVisitable<'tcx>> TypeVisitable<'tcx> for traits::Obligation<'tcx, O> { - fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { +impl<'tcx, O: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> + for traits::Obligation<'tcx, O> +{ + fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> { self.predicate.visit_with(visitor)?; self.param_env.visit_with(visitor) } diff --git a/compiler/rustc_infer/src/traits/util.rs b/compiler/rustc_infer/src/traits/util.rs index cd5bde2a7..c07ff5165 100644 --- a/compiler/rustc_infer/src/traits/util.rs +++ b/compiler/rustc_infer/src/traits/util.rs @@ -116,11 +116,11 @@ pub fn elaborate_predicates_with_span<'tcx>( pub fn elaborate_obligations<'tcx>( tcx: TyCtxt<'tcx>, - mut obligations: Vec<PredicateObligation<'tcx>>, + obligations: Vec<PredicateObligation<'tcx>>, ) -> Elaborator<'tcx> { - let mut visited = PredicateSet::new(tcx); - obligations.retain(|obligation| visited.insert(obligation.predicate)); - Elaborator { stack: obligations, visited } + let mut elaborator = Elaborator { stack: Vec::new(), visited: PredicateSet::new(tcx) }; + elaborator.extend_deduped(obligations); + elaborator } fn predicate_obligation<'tcx>( @@ -132,6 +132,15 @@ fn predicate_obligation<'tcx>( } impl<'tcx> Elaborator<'tcx> { + fn extend_deduped(&mut self, obligations: impl IntoIterator<Item = PredicateObligation<'tcx>>) { + // 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))); + } + pub fn filter_to_traits(self) -> FilterToTraits<Self> { FilterToTraits::new(self) } @@ -145,40 +154,34 @@ impl<'tcx> Elaborator<'tcx> { // Get predicates declared on the trait. let predicates = tcx.super_predicates_of(data.def_id()); - let obligations = predicates.predicates.iter().map(|&(mut pred, span)| { - // when parent predicate is non-const, elaborate it to non-const predicates. - 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_def_id: data.def_id(), - span, - }, - )) - }, - ); - predicate_obligation( - pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), - obligation.param_env, - cause, - ) - }); + let obligations = + predicates.predicates.iter().enumerate().map(|(index, &(mut pred, span))| { + // when parent predicate is non-const, elaborate it to non-const predicates. + 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( + pred.subst_supertrait(tcx, &bound_predicate.rebind(data.trait_ref)), + obligation.param_env, + cause, + ) + }); debug!(?data, ?obligations, "super_predicates"); - - // 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; - let obligations = obligations.filter(|o| visited.insert(o.predicate)); - - self.stack.extend(obligations); + self.extend_deduped(obligations); } ty::PredicateKind::WellFormed(..) => { // Currently, we do not elaborate WF predicates, @@ -235,10 +238,9 @@ impl<'tcx> Elaborator<'tcx> { return; } - let visited = &mut self.visited; let mut components = smallvec![]; push_outlives_components(tcx, ty_max, &mut components); - self.stack.extend( + self.extend_deduped( components .into_iter() .filter_map(|component| match component { @@ -278,7 +280,6 @@ impl<'tcx> Elaborator<'tcx> { .map(|predicate_kind| { bound_predicate.rebind(predicate_kind).to_predicate(tcx) }) - .filter(|&predicate| visited.insert(predicate)) .map(|predicate| { predicate_obligation( predicate, @@ -292,6 +293,12 @@ impl<'tcx> Elaborator<'tcx> { // Nothing to elaborate } ty::PredicateKind::Ambiguous => {} + ty::PredicateKind::AliasEq(..) => { + // No + } + ty::PredicateKind::Clause(ty::Clause::ConstArgHasType(..)) => { + // Nothing to elaborate + } } } } |