1use std::marker::PhantomData;
2use std::ops::ControlFlow;
3
4use rustc_data_structures::obligation_forest::{
5 Error, ForestObligation, ObligationForest, ObligationProcessor, Outcome, ProcessResult,
6};
7use rustc_hir::def_id::LocalDefId;
8use rustc_infer::infer::DefineOpaqueTypes;
9use rustc_infer::traits::{
10 FromSolverError, PolyTraitObligation, PredicateObligations, ProjectionCacheKey, SelectionError,
11 TraitEngine,
12};
13use rustc_middle::bug;
14use rustc_middle::ty::abstract_const::NotConstEvaluatable;
15use rustc_middle::ty::error::{ExpectedFound, TypeError};
16use rustc_middle::ty::{
17 self, Binder, Const, DelayedSet, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
18 TypeVisitableExt, TypeVisitor, TypingMode, may_use_unstable_feature,
19};
20use thin_vec::{ThinVec, thin_vec};
21use tracing::{debug, debug_span, instrument};
22
23use super::effects::{self, HostEffectObligation};
24use super::project::{self, ProjectAndUnifyResult};
25use super::select::SelectionContext;
26use super::{
27 EvaluationResult, FulfillmentError, FulfillmentErrorCode, PredicateObligation,
28 ScrubbedTraitError, const_evaluatable, wf,
29};
30use crate::error_reporting::InferCtxtErrorExt;
31use crate::infer::{InferCtxt, TyOrConstInferVar};
32use crate::traits::normalize::normalize_with_depth_to;
33use crate::traits::project::{PolyProjectionObligation, ProjectionCacheKeyExt as _};
34use crate::traits::query::evaluate_obligation::InferCtxtExt;
35use crate::traits::{EvaluateConstErr, sizedness_fast_path};
36
37pub(crate) type PendingPredicateObligations<'tcx> = ThinVec<PendingPredicateObligation<'tcx>>;
38
39impl<'tcx> ForestObligation for PendingPredicateObligation<'tcx> {
40 type CacheKey = ty::ParamEnvAnd<'tcx, ty::Predicate<'tcx>>;
44
45 fn as_cache_key(&self) -> Self::CacheKey {
46 self.obligation.param_env.and(self.obligation.predicate)
47 }
48}
49
50pub struct FulfillmentContext<'tcx, E: 'tcx> {
61 predicates: ObligationForest<PendingPredicateObligation<'tcx>>,
64
65 usable_in_snapshot: usize,
70
71 _errors: PhantomData<E>,
72}
73
74#[derive(#[automatically_derived]
impl<'tcx> ::core::clone::Clone for PendingPredicateObligation<'tcx> {
#[inline]
fn clone(&self) -> PendingPredicateObligation<'tcx> {
PendingPredicateObligation {
obligation: ::core::clone::Clone::clone(&self.obligation),
stalled_on: ::core::clone::Clone::clone(&self.stalled_on),
}
}
}Clone, #[automatically_derived]
impl<'tcx> ::core::fmt::Debug for PendingPredicateObligation<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"PendingPredicateObligation", "obligation", &self.obligation,
"stalled_on", &&self.stalled_on)
}
}Debug)]
75pub struct PendingPredicateObligation<'tcx> {
76 pub obligation: PredicateObligation<'tcx>,
77 pub stalled_on: Vec<TyOrConstInferVar>,
82}
83
84#[cfg(target_pointer_width = "64")]
86const _: [(); 72] =
[(); ::std::mem::size_of::<PendingPredicateObligation<'_>>()];rustc_data_structures::static_assert_size!(PendingPredicateObligation<'_>, 72);
87
88impl<'tcx, E> FulfillmentContext<'tcx, E>
89where
90 E: FromSolverError<'tcx, OldSolverError<'tcx>>,
91{
92 pub(super) fn new(infcx: &InferCtxt<'tcx>) -> FulfillmentContext<'tcx, E> {
94 if !!infcx.next_trait_solver() {
{
::core::panicking::panic_fmt(format_args!("old trait solver fulfillment context created when infcx is set up for new trait solver"));
}
};assert!(
95 !infcx.next_trait_solver(),
96 "old trait solver fulfillment context created when \
97 infcx is set up for new trait solver"
98 );
99 FulfillmentContext {
100 predicates: ObligationForest::new(),
101 usable_in_snapshot: infcx.num_open_snapshots(),
102 _errors: PhantomData,
103 }
104 }
105
106 fn select(&mut self, selcx: SelectionContext<'_, 'tcx>) -> Vec<E> {
108 let span = {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("select",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(108u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["obligation_forest_size"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() } &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&self.predicates.len())
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
}debug_span!("select", obligation_forest_size = ?self.predicates.len());
109 let _enter = span.enter();
110 let infcx = selcx.infcx;
111
112 let outcome: Outcome<_, _> =
114 self.predicates.process_obligations(&mut FulfillProcessor { selcx });
115
116 let errors: Vec<E> = outcome
120 .errors
121 .into_iter()
122 .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
123 .collect();
124
125 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:125",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(125u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("select({0} predicates remaining, {1} errors) done",
self.predicates.len(), errors.len()) as &dyn Value))])
});
} else { ; }
};debug!(
126 "select({} predicates remaining, {} errors) done",
127 self.predicates.len(),
128 errors.len()
129 );
130
131 errors
132 }
133}
134
135impl<'tcx, E> TraitEngine<'tcx, E> for FulfillmentContext<'tcx, E>
136where
137 E: FromSolverError<'tcx, OldSolverError<'tcx>>,
138{
139 #[inline]
140 fn register_predicate_obligation(
141 &mut self,
142 infcx: &InferCtxt<'tcx>,
143 mut obligation: PredicateObligation<'tcx>,
144 ) {
145 match (&self.usable_in_snapshot, &infcx.num_open_snapshots()) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val, &*right_val,
::core::option::Option::None);
}
}
};assert_eq!(self.usable_in_snapshot, infcx.num_open_snapshots());
146 if true {
if !!obligation.param_env.has_non_region_infer() {
::core::panicking::panic("assertion failed: !obligation.param_env.has_non_region_infer()")
};
};debug_assert!(!obligation.param_env.has_non_region_infer());
149 obligation.predicate = infcx.resolve_vars_if_possible(obligation.predicate);
150
151 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:151",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(151u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message",
"obligation"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("register_predicate_obligation")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&obligation)
as &dyn Value))])
});
} else { ; }
};debug!(?obligation, "register_predicate_obligation");
152
153 self.predicates
154 .register_obligation(PendingPredicateObligation { obligation, stalled_on: ::alloc::vec::Vec::new()vec![] });
155 }
156
157 fn collect_remaining_errors(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
158 self.predicates
159 .to_errors(FulfillmentErrorCode::Ambiguity { overflow: None })
160 .into_iter()
161 .map(|err| E::from_solver_error(infcx, OldSolverError(err)))
162 .collect()
163 }
164
165 fn try_evaluate_obligations(&mut self, infcx: &InferCtxt<'tcx>) -> Vec<E> {
166 let selcx = SelectionContext::new(infcx);
167 self.select(selcx)
168 }
169
170 fn drain_stalled_obligations_for_coroutines(
171 &mut self,
172 infcx: &InferCtxt<'tcx>,
173 ) -> PredicateObligations<'tcx> {
174 let stalled_coroutines = match infcx.typing_mode() {
175 TypingMode::Analysis { defining_opaque_types_and_generators } => {
176 defining_opaque_types_and_generators
177 }
178 TypingMode::Coherence
179 | TypingMode::Borrowck { defining_opaque_types: _ }
180 | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ }
181 | TypingMode::PostAnalysis => return Default::default(),
182 };
183
184 if stalled_coroutines.is_empty() {
185 return Default::default();
186 }
187
188 let mut processor = DrainProcessor {
189 infcx,
190 removed_predicates: PredicateObligations::new(),
191 stalled_coroutines,
192 };
193 let outcome: Outcome<_, _> = self.predicates.process_obligations(&mut processor);
194 if !outcome.errors.is_empty() {
::core::panicking::panic("assertion failed: outcome.errors.is_empty()")
};assert!(outcome.errors.is_empty());
195 return processor.removed_predicates;
196
197 struct DrainProcessor<'a, 'tcx> {
198 infcx: &'a InferCtxt<'tcx>,
199 removed_predicates: PredicateObligations<'tcx>,
200 stalled_coroutines: &'tcx ty::List<LocalDefId>,
201 }
202
203 impl<'tcx> ObligationProcessor for DrainProcessor<'_, 'tcx> {
204 type Obligation = PendingPredicateObligation<'tcx>;
205 type Error = !;
206 type OUT = Outcome<Self::Obligation, Self::Error>;
207
208 fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
209 struct StalledOnCoroutines<'tcx> {
210 pub stalled_coroutines: &'tcx ty::List<LocalDefId>,
211 pub cache: DelayedSet<Ty<'tcx>>,
212 }
213
214 impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for StalledOnCoroutines<'tcx> {
215 type Result = ControlFlow<()>;
216
217 fn visit_ty(&mut self, ty: Ty<'tcx>) -> Self::Result {
218 if !self.cache.insert(ty) {
219 return ControlFlow::Continue(());
220 }
221
222 if let ty::Coroutine(def_id, _) = ty.kind()
223 && def_id
224 .as_local()
225 .is_some_and(|def_id| self.stalled_coroutines.contains(&def_id))
226 {
227 ControlFlow::Break(())
228 } else if ty.has_coroutines() {
229 ty.super_visit_with(self)
230 } else {
231 ControlFlow::Continue(())
232 }
233 }
234 }
235
236 self.infcx
237 .resolve_vars_if_possible(pending_obligation.obligation.predicate)
238 .visit_with(&mut StalledOnCoroutines {
239 stalled_coroutines: self.stalled_coroutines,
240 cache: Default::default(),
241 })
242 .is_break()
243 }
244
245 fn process_obligation(
246 &mut self,
247 pending_obligation: &mut PendingPredicateObligation<'tcx>,
248 ) -> ProcessResult<PendingPredicateObligation<'tcx>, !> {
249 if !self.needs_process_obligation(pending_obligation) {
::core::panicking::panic("assertion failed: self.needs_process_obligation(pending_obligation)")
};assert!(self.needs_process_obligation(pending_obligation));
250 self.removed_predicates.push(pending_obligation.obligation.clone());
251 ProcessResult::Changed(Default::default())
252 }
253
254 fn process_backedge<'c, I>(
255 &mut self,
256 cycle: I,
257 _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
258 ) -> Result<(), !>
259 where
260 I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
261 {
262 self.removed_predicates.extend(cycle.map(|c| c.obligation.clone()));
263 Ok(())
264 }
265 }
266 }
267
268 fn has_pending_obligations(&self) -> bool {
269 self.predicates.has_pending_obligations()
270 }
271
272 fn pending_obligations(&self) -> PredicateObligations<'tcx> {
273 self.predicates.map_pending_obligations(|o| o.obligation.clone())
274 }
275}
276
277struct FulfillProcessor<'a, 'tcx> {
278 selcx: SelectionContext<'a, 'tcx>,
279}
280
281fn mk_pending<'tcx>(
282 parent: &PredicateObligation<'tcx>,
283 os: PredicateObligations<'tcx>,
284) -> PendingPredicateObligations<'tcx> {
285 os.into_iter()
286 .map(|mut o| {
287 o.set_depth_from_parent(parent.recursion_depth);
288 PendingPredicateObligation { obligation: o, stalled_on: ::alloc::vec::Vec::new()vec![] }
289 })
290 .collect()
291}
292
293impl<'a, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'tcx> {
294 type Obligation = PendingPredicateObligation<'tcx>;
295 type Error = FulfillmentErrorCode<'tcx>;
296 type OUT = Outcome<Self::Obligation, Self::Error>;
297
298 #[inline]
308 fn skippable_obligations<'b>(
309 &'b self,
310 it: impl Iterator<Item = &'b Self::Obligation>,
311 ) -> usize {
312 let is_unchanged = self.selcx.infcx.is_ty_infer_var_definitely_unchanged();
313
314 it.take_while(|o| match o.stalled_on.as_slice() {
315 [o] => is_unchanged(*o),
316 _ => false,
317 })
318 .count()
319 }
320
321 #[inline(always)]
327 fn needs_process_obligation(&self, pending_obligation: &Self::Obligation) -> bool {
328 let stalled_on = &pending_obligation.stalled_on;
332 match stalled_on.len() {
333 1 => self.selcx.infcx.ty_or_const_infer_var_changed(stalled_on[0]),
337
338 0 => true,
346
347 _ => (|| {
354 for &infer_var in stalled_on {
355 if self.selcx.infcx.ty_or_const_infer_var_changed(infer_var) {
356 return true;
357 }
358 }
359 false
360 })(),
361 }
362 }
363
364 #[inline(never)]
372 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_obligation",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(372u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&[],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{ meta.fields().value_set(&[]) })
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
ProcessResult<PendingPredicateObligation<'tcx>,
FulfillmentErrorCode<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
pending_obligation.stalled_on.clear();
let obligation = &mut pending_obligation.obligation;
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:381",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(381u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message",
"obligation"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("pre-resolve")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&obligation)
as &dyn Value))])
});
} else { ; }
};
if obligation.predicate.has_non_region_infer() {
obligation.predicate =
self.selcx.infcx.resolve_vars_if_possible(obligation.predicate);
}
let obligation = &pending_obligation.obligation;
let infcx = self.selcx.infcx;
if sizedness_fast_path(infcx.tcx, obligation.predicate,
obligation.param_env) {
return ProcessResult::Changed(::thin_vec::ThinVec::new());
}
if obligation.predicate.has_aliases() {
let mut obligations = PredicateObligations::new();
let predicate =
normalize_with_depth_to(&mut self.selcx,
obligation.param_env, obligation.cause.clone(),
obligation.recursion_depth + 1, obligation.predicate,
&mut obligations);
if predicate != obligation.predicate {
obligations.push(obligation.with(infcx.tcx, predicate));
return ProcessResult::Changed(mk_pending(obligation,
obligations));
}
}
let binder = obligation.predicate.kind();
match binder.no_bound_vars() {
None =>
match binder.skip_binder() {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref))
=> {
let trait_obligation =
obligation.with(infcx.tcx, binder.rebind(trait_ref));
self.process_trait_obligation(obligation, trait_obligation,
&mut pending_obligation.stalled_on)
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(data))
=> {
let project_obligation =
obligation.with(infcx.tcx, binder.rebind(data));
self.process_projection_obligation(obligation,
project_obligation, &mut pending_obligation.stalled_on)
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
| ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
| ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) |
ty::PredicateKind::DynCompatible(_) |
ty::PredicateKind::Subtype(_) | ty::PredicateKind::Coerce(_)
|
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
| ty::PredicateKind::ConstEquate(..) |
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) =>
{
let pred =
ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
let mut obligations =
PredicateObligations::with_capacity(1);
obligations.push(obligation.with(infcx.tcx, pred));
ProcessResult::Changed(mk_pending(obligation, obligations))
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::NormalizesTo(..) => {
::rustc_middle::util::bug::bug_fmt(format_args!("NormalizesTo is only used by the new solver"))
}
ty::PredicateKind::AliasRelate(..) => {
::rustc_middle::util::bug::bug_fmt(format_args!("AliasRelate is only used by the new solver"))
}
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_))
=> {
{
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("unexpected higher ranked `UnstableFeature` goal")));
}
}
},
Some(pred) =>
match pred {
ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
let trait_obligation =
obligation.with(infcx.tcx, Binder::dummy(data));
self.process_trait_obligation(obligation, trait_obligation,
&mut pending_obligation.stalled_on)
}
ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data))
=> {
let host_obligation = obligation.with(infcx.tcx, data);
self.process_host_obligation(obligation, host_obligation,
&mut pending_obligation.stalled_on)
}
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data))
=> {
if infcx.considering_regions {
infcx.register_region_outlives_constraint(data,
&obligation.cause);
}
ProcessResult::Changed(Default::default())
}
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(t_a,
r_b))) => {
if infcx.considering_regions {
infcx.register_type_outlives_constraint(t_a, r_b,
&obligation.cause);
}
ProcessResult::Changed(Default::default())
}
ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data))
=> {
let project_obligation =
obligation.with(infcx.tcx, Binder::dummy(*data));
self.process_projection_obligation(obligation,
project_obligation, &mut pending_obligation.stalled_on)
}
ty::PredicateKind::DynCompatible(trait_def_id) => {
if !self.selcx.tcx().is_dyn_compatible(trait_def_id) {
ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::Unimplemented))
} else { ProcessResult::Changed(Default::default()) }
}
ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
ty::PredicateKind::NormalizesTo(..) => {
::rustc_middle::util::bug::bug_fmt(format_args!("NormalizesTo is only used by the new solver"))
}
ty::PredicateKind::AliasRelate(..) => {
::rustc_middle::util::bug::bug_fmt(format_args!("AliasRelate is only used by the new solver"))
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct,
ty)) => {
let ct = infcx.shallow_resolve_const(ct);
let ct_ty =
match ct.kind() {
ty::ConstKind::Infer(var) => {
let var =
match var {
ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
ty::InferConst::Fresh(_) => {
::rustc_middle::util::bug::bug_fmt(format_args!("encountered fresh const in fulfill"))
}
};
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend([var]);
return ProcessResult::Unchanged;
}
ty::ConstKind::Error(_) => {
return ProcessResult::Changed(PendingPredicateObligations::new());
}
ty::ConstKind::Value(cv) => cv.ty,
ty::ConstKind::Unevaluated(uv) =>
infcx.tcx.type_of(uv.def).instantiate(infcx.tcx,
uv.args).skip_norm_wip(),
ty::ConstKind::Expr(_) => {
return ProcessResult::Changed(mk_pending(obligation,
PredicateObligations::new()));
}
ty::ConstKind::Placeholder(_) => {
::rustc_middle::util::bug::bug_fmt(format_args!("placeholder const {0:?} in old solver",
ct))
}
ty::ConstKind::Bound(_, _) =>
::rustc_middle::util::bug::bug_fmt(format_args!("escaping bound vars in {0:?}",
ct)),
ty::ConstKind::Param(param_ct) => {
param_ct.find_const_ty_from_env(obligation.param_env)
}
};
match infcx.at(&obligation.cause,
obligation.param_env).eq(DefineOpaqueTypes::Yes, ct_ty, ty)
{
Ok(inf_ok) =>
ProcessResult::Changed(mk_pending(obligation,
inf_ok.into_obligations())),
Err(_) =>
ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::ConstArgHasWrongType {
ct,
ct_ty,
expected_ty: ty,
})),
}
}
_ if
!self.selcx.tcx().recursion_limit().value_within_limit(obligation.recursion_depth)
=> {
self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation,
false);
}
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term))
=> {
if term.is_trivially_wf(self.selcx.tcx()) {
return ProcessResult::Changed(::thin_vec::ThinVec::new());
}
match wf::obligations(self.selcx.infcx,
obligation.param_env, obligation.cause.body_id,
obligation.recursion_depth + 1, term, obligation.cause.span)
{
None => {
pending_obligation.stalled_on =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[TyOrConstInferVar::maybe_from_term(term).unwrap()]));
ProcessResult::Unchanged
}
Some(os) =>
ProcessResult::Changed(mk_pending(obligation, os)),
}
}
ty::PredicateKind::Subtype(subtype) => {
match self.selcx.infcx.subtype_predicate(&obligation.cause,
obligation.param_env, Binder::dummy(subtype)) {
Err((a, b)) => {
pending_obligation.stalled_on =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]));
ProcessResult::Unchanged
}
Ok(Ok(ok)) => {
ProcessResult::Changed(mk_pending(obligation,
ok.obligations))
}
Ok(Err(err)) => {
let expected_found =
if subtype.a_is_expected {
ExpectedFound::new(subtype.a, subtype.b)
} else { ExpectedFound::new(subtype.b, subtype.a) };
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found,
err))
}
}
}
ty::PredicateKind::Coerce(coerce) => {
match self.selcx.infcx.coerce_predicate(&obligation.cause,
obligation.param_env, Binder::dummy(coerce)) {
Err((a, b)) => {
pending_obligation.stalled_on =
::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)]));
ProcessResult::Unchanged
}
Ok(Ok(ok)) => {
ProcessResult::Changed(mk_pending(obligation,
ok.obligations))
}
Ok(Err(err)) => {
let expected_found = ExpectedFound::new(coerce.b, coerce.a);
ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found,
err))
}
}
}
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv))
=> {
match const_evaluatable::is_const_evaluatable(self.selcx.infcx,
uv, obligation.param_env, obligation.cause.span) {
Ok(()) => ProcessResult::Changed(Default::default()),
Err(NotConstEvaluatable::MentionsInfer) => {
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend(uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg));
ProcessResult::Unchanged
}
Err(e @ NotConstEvaluatable::MentionsParam | e @
NotConstEvaluatable::Error(_)) =>
ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::NotConstEvaluatable(e))),
}
}
ty::PredicateKind::ConstEquate(c1, c2) => {
let tcx = self.selcx.tcx();
if !tcx.features().generic_const_exprs() {
{
::core::panicking::panic_fmt(format_args!("`ConstEquate` without a feature gate: {0:?} {1:?}",
c1, c2));
}
};
{
let c1 = tcx.expand_abstract_consts(c1);
let c2 = tcx.expand_abstract_consts(c2);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:710",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(710u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("equating consts:\nc1= {0:?}\nc2= {1:?}",
c1, c2) as &dyn Value))])
});
} else { ; }
};
use rustc_hir::def::DefKind;
match (c1.kind(), c2.kind()) {
(ty::ConstKind::Unevaluated(a),
ty::ConstKind::Unevaluated(b)) if
a.def == b.def &&
#[allow(non_exhaustive_omitted_patterns)] match tcx.def_kind(a.def)
{
DefKind::AssocConst { .. } => true,
_ => false,
} => {
if let Ok(new_obligations) =
infcx.at(&obligation.cause,
obligation.param_env).eq(DefineOpaqueTypes::Yes,
ty::AliasTerm::from_unevaluated_const(tcx, a),
ty::AliasTerm::from_unevaluated_const(tcx, b)) {
return ProcessResult::Changed(mk_pending(obligation,
new_obligations.into_obligations()));
}
}
(_, ty::ConstKind::Unevaluated(_)) |
(ty::ConstKind::Unevaluated(_), _) => (),
(_, _) => {
if let Ok(new_obligations) =
infcx.at(&obligation.cause,
obligation.param_env).eq(DefineOpaqueTypes::Yes, c1, c2) {
return ProcessResult::Changed(mk_pending(obligation,
new_obligations.into_obligations()));
}
}
}
}
let stalled_on = &mut pending_obligation.stalled_on;
let mut evaluate =
|c: Const<'tcx>|
{
if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
match super::try_evaluate_const(self.selcx.infcx, c,
obligation.param_env) {
Ok(val) => Ok(val),
e @ Err(EvaluateConstErr::HasGenericsOrInfers) => {
stalled_on.extend(unevaluated.args.iter().filter_map(TyOrConstInferVar::maybe_from_generic_arg));
e
}
e @
Err(EvaluateConstErr::EvaluationFailure(_) |
EvaluateConstErr::InvalidConstParamTy(_)) => e,
}
} else { Ok(c) }
};
match (evaluate(c1), evaluate(c2)) {
(Ok(c1), Ok(c2)) => {
match self.selcx.infcx.at(&obligation.cause,
obligation.param_env).eq(DefineOpaqueTypes::Yes, c1, c2) {
Ok(inf_ok) =>
ProcessResult::Changed(mk_pending(obligation,
inf_ok.into_obligations())),
Err(err) => {
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(ExpectedFound::new(c1,
c2), err))
}
}
}
(Err(EvaluateConstErr::InvalidConstParamTy(e)), _) |
(_, Err(EvaluateConstErr::InvalidConstParamTy(e))) => {
ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e))))
}
(Err(EvaluateConstErr::EvaluationFailure(e)), _) |
(_, Err(EvaluateConstErr::EvaluationFailure(e))) => {
ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e))))
}
(Err(EvaluateConstErr::HasGenericsOrInfers), _) |
(_, Err(EvaluateConstErr::HasGenericsOrInfers)) => {
if c1.has_non_region_infer() || c2.has_non_region_infer() {
ProcessResult::Unchanged
} else {
let expected_found = ExpectedFound::new(c1, c2);
ProcessResult::Error(FulfillmentErrorCode::ConstEquate(expected_found,
TypeError::ConstMismatch(expected_found)))
}
}
}
}
ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol))
=> {
if may_use_unstable_feature(self.selcx.infcx,
obligation.param_env, symbol) {
ProcessResult::Changed(Default::default())
} else { ProcessResult::Unchanged }
}
},
}
}
}
}#[instrument(level = "debug", skip(self, pending_obligation))]
373 fn process_obligation(
374 &mut self,
375 pending_obligation: &mut PendingPredicateObligation<'tcx>,
376 ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
377 pending_obligation.stalled_on.clear();
378
379 let obligation = &mut pending_obligation.obligation;
380
381 debug!(?obligation, "pre-resolve");
382
383 if obligation.predicate.has_non_region_infer() {
384 obligation.predicate = self.selcx.infcx.resolve_vars_if_possible(obligation.predicate);
385 }
386
387 let obligation = &pending_obligation.obligation;
388
389 let infcx = self.selcx.infcx;
390
391 if sizedness_fast_path(infcx.tcx, obligation.predicate, obligation.param_env) {
392 return ProcessResult::Changed(thin_vec![]);
393 }
394
395 if obligation.predicate.has_aliases() {
396 let mut obligations = PredicateObligations::new();
397 let predicate = normalize_with_depth_to(
398 &mut self.selcx,
399 obligation.param_env,
400 obligation.cause.clone(),
401 obligation.recursion_depth + 1,
402 obligation.predicate,
403 &mut obligations,
404 );
405 if predicate != obligation.predicate {
406 obligations.push(obligation.with(infcx.tcx, predicate));
407 return ProcessResult::Changed(mk_pending(obligation, obligations));
408 }
409 }
410 let binder = obligation.predicate.kind();
411 match binder.no_bound_vars() {
412 None => match binder.skip_binder() {
413 ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_ref)) => {
417 let trait_obligation = obligation.with(infcx.tcx, binder.rebind(trait_ref));
418
419 self.process_trait_obligation(
420 obligation,
421 trait_obligation,
422 &mut pending_obligation.stalled_on,
423 )
424 }
425 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
426 let project_obligation = obligation.with(infcx.tcx, binder.rebind(data));
427
428 self.process_projection_obligation(
429 obligation,
430 project_obligation,
431 &mut pending_obligation.stalled_on,
432 )
433 }
434 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_))
435 | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_))
436 | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
437 | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_))
438 | ty::PredicateKind::DynCompatible(_)
439 | ty::PredicateKind::Subtype(_)
440 | ty::PredicateKind::Coerce(_)
441 | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
442 | ty::PredicateKind::ConstEquate(..)
443 | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..)) => {
447 let pred = ty::Binder::dummy(infcx.enter_forall_and_leak_universe(binder));
448 let mut obligations = PredicateObligations::with_capacity(1);
449 obligations.push(obligation.with(infcx.tcx, pred));
450
451 ProcessResult::Changed(mk_pending(obligation, obligations))
452 }
453 ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
454 ty::PredicateKind::NormalizesTo(..) => {
455 bug!("NormalizesTo is only used by the new solver")
456 }
457 ty::PredicateKind::AliasRelate(..) => {
458 bug!("AliasRelate is only used by the new solver")
459 }
460 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) => {
461 unreachable!("unexpected higher ranked `UnstableFeature` goal")
462 }
463 },
464 Some(pred) => match pred {
465 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
466 let trait_obligation = obligation.with(infcx.tcx, Binder::dummy(data));
467
468 self.process_trait_obligation(
469 obligation,
470 trait_obligation,
471 &mut pending_obligation.stalled_on,
472 )
473 }
474
475 ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(data)) => {
476 let host_obligation = obligation.with(infcx.tcx, data);
477
478 self.process_host_obligation(
479 obligation,
480 host_obligation,
481 &mut pending_obligation.stalled_on,
482 )
483 }
484
485 ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(data)) => {
486 if infcx.considering_regions {
487 infcx.register_region_outlives_constraint(data, &obligation.cause);
488 }
489
490 ProcessResult::Changed(Default::default())
491 }
492
493 ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
494 t_a,
495 r_b,
496 ))) => {
497 if infcx.considering_regions {
498 infcx.register_type_outlives_constraint(t_a, r_b, &obligation.cause);
499 }
500 ProcessResult::Changed(Default::default())
501 }
502
503 ty::PredicateKind::Clause(ty::ClauseKind::Projection(ref data)) => {
504 let project_obligation = obligation.with(infcx.tcx, Binder::dummy(*data));
505
506 self.process_projection_obligation(
507 obligation,
508 project_obligation,
509 &mut pending_obligation.stalled_on,
510 )
511 }
512
513 ty::PredicateKind::DynCompatible(trait_def_id) => {
514 if !self.selcx.tcx().is_dyn_compatible(trait_def_id) {
515 ProcessResult::Error(FulfillmentErrorCode::Select(
516 SelectionError::Unimplemented,
517 ))
518 } else {
519 ProcessResult::Changed(Default::default())
520 }
521 }
522
523 ty::PredicateKind::Ambiguous => ProcessResult::Unchanged,
524 ty::PredicateKind::NormalizesTo(..) => {
525 bug!("NormalizesTo is only used by the new solver")
526 }
527 ty::PredicateKind::AliasRelate(..) => {
528 bug!("AliasRelate is only used by the new solver")
529 }
530 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
534 let ct = infcx.shallow_resolve_const(ct);
535 let ct_ty = match ct.kind() {
536 ty::ConstKind::Infer(var) => {
537 let var = match var {
538 ty::InferConst::Var(vid) => TyOrConstInferVar::Const(vid),
539 ty::InferConst::Fresh(_) => {
540 bug!("encountered fresh const in fulfill")
541 }
542 };
543 pending_obligation.stalled_on.clear();
544 pending_obligation.stalled_on.extend([var]);
545 return ProcessResult::Unchanged;
546 }
547 ty::ConstKind::Error(_) => {
548 return ProcessResult::Changed(PendingPredicateObligations::new());
549 }
550 ty::ConstKind::Value(cv) => cv.ty,
551 ty::ConstKind::Unevaluated(uv) => infcx
552 .tcx
553 .type_of(uv.def)
554 .instantiate(infcx.tcx, uv.args)
555 .skip_norm_wip(),
556 ty::ConstKind::Expr(_) => {
560 return ProcessResult::Changed(mk_pending(
561 obligation,
562 PredicateObligations::new(),
563 ));
564 }
565 ty::ConstKind::Placeholder(_) => {
566 bug!("placeholder const {:?} in old solver", ct)
567 }
568 ty::ConstKind::Bound(_, _) => bug!("escaping bound vars in {:?}", ct),
569 ty::ConstKind::Param(param_ct) => {
570 param_ct.find_const_ty_from_env(obligation.param_env)
571 }
572 };
573
574 match infcx.at(&obligation.cause, obligation.param_env).eq(
575 DefineOpaqueTypes::Yes,
577 ct_ty,
578 ty,
579 ) {
580 Ok(inf_ok) => ProcessResult::Changed(mk_pending(
581 obligation,
582 inf_ok.into_obligations(),
583 )),
584 Err(_) => ProcessResult::Error(FulfillmentErrorCode::Select(
585 SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty: ty },
586 )),
587 }
588 }
589
590 _ if !self
595 .selcx
596 .tcx()
597 .recursion_limit()
598 .value_within_limit(obligation.recursion_depth) =>
599 {
600 self.selcx.infcx.err_ctxt().report_overflow_obligation(&obligation, false);
601 }
602
603 ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(term)) => {
604 if term.is_trivially_wf(self.selcx.tcx()) {
605 return ProcessResult::Changed(thin_vec![]);
606 }
607
608 match wf::obligations(
609 self.selcx.infcx,
610 obligation.param_env,
611 obligation.cause.body_id,
612 obligation.recursion_depth + 1,
613 term,
614 obligation.cause.span,
615 ) {
616 None => {
617 pending_obligation.stalled_on =
618 vec![TyOrConstInferVar::maybe_from_term(term).unwrap()];
619 ProcessResult::Unchanged
620 }
621 Some(os) => ProcessResult::Changed(mk_pending(obligation, os)),
622 }
623 }
624
625 ty::PredicateKind::Subtype(subtype) => {
626 match self.selcx.infcx.subtype_predicate(
627 &obligation.cause,
628 obligation.param_env,
629 Binder::dummy(subtype),
630 ) {
631 Err((a, b)) => {
632 pending_obligation.stalled_on =
634 vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
635 ProcessResult::Unchanged
636 }
637 Ok(Ok(ok)) => {
638 ProcessResult::Changed(mk_pending(obligation, ok.obligations))
639 }
640 Ok(Err(err)) => {
641 let expected_found = if subtype.a_is_expected {
642 ExpectedFound::new(subtype.a, subtype.b)
643 } else {
644 ExpectedFound::new(subtype.b, subtype.a)
645 };
646 ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
647 }
648 }
649 }
650
651 ty::PredicateKind::Coerce(coerce) => {
652 match self.selcx.infcx.coerce_predicate(
653 &obligation.cause,
654 obligation.param_env,
655 Binder::dummy(coerce),
656 ) {
657 Err((a, b)) => {
658 pending_obligation.stalled_on =
660 vec![TyOrConstInferVar::Ty(a), TyOrConstInferVar::Ty(b)];
661 ProcessResult::Unchanged
662 }
663 Ok(Ok(ok)) => {
664 ProcessResult::Changed(mk_pending(obligation, ok.obligations))
665 }
666 Ok(Err(err)) => {
667 let expected_found = ExpectedFound::new(coerce.b, coerce.a);
668 ProcessResult::Error(FulfillmentErrorCode::Subtype(expected_found, err))
669 }
670 }
671 }
672
673 ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(uv)) => {
674 match const_evaluatable::is_const_evaluatable(
675 self.selcx.infcx,
676 uv,
677 obligation.param_env,
678 obligation.cause.span,
679 ) {
680 Ok(()) => ProcessResult::Changed(Default::default()),
681 Err(NotConstEvaluatable::MentionsInfer) => {
682 pending_obligation.stalled_on.clear();
683 pending_obligation.stalled_on.extend(
684 uv.walk().filter_map(TyOrConstInferVar::maybe_from_generic_arg),
685 );
686 ProcessResult::Unchanged
687 }
688 Err(
689 e @ NotConstEvaluatable::MentionsParam
690 | e @ NotConstEvaluatable::Error(_),
691 ) => ProcessResult::Error(FulfillmentErrorCode::Select(
692 SelectionError::NotConstEvaluatable(e),
693 )),
694 }
695 }
696
697 ty::PredicateKind::ConstEquate(c1, c2) => {
698 let tcx = self.selcx.tcx();
699 assert!(
700 tcx.features().generic_const_exprs(),
701 "`ConstEquate` without a feature gate: {c1:?} {c2:?}",
702 );
703 {
708 let c1 = tcx.expand_abstract_consts(c1);
709 let c2 = tcx.expand_abstract_consts(c2);
710 debug!("equating consts:\nc1= {:?}\nc2= {:?}", c1, c2);
711
712 use rustc_hir::def::DefKind;
713 match (c1.kind(), c2.kind()) {
714 (ty::ConstKind::Unevaluated(a), ty::ConstKind::Unevaluated(b))
715 if a.def == b.def
716 && matches!(
717 tcx.def_kind(a.def),
718 DefKind::AssocConst { .. }
719 ) =>
720 {
721 if let Ok(new_obligations) = infcx
722 .at(&obligation.cause, obligation.param_env)
723 .eq(
726 DefineOpaqueTypes::Yes,
727 ty::AliasTerm::from_unevaluated_const(tcx, a),
728 ty::AliasTerm::from_unevaluated_const(tcx, b),
729 )
730 {
731 return ProcessResult::Changed(mk_pending(
732 obligation,
733 new_obligations.into_obligations(),
734 ));
735 }
736 }
737 (_, ty::ConstKind::Unevaluated(_))
738 | (ty::ConstKind::Unevaluated(_), _) => (),
739 (_, _) => {
740 if let Ok(new_obligations) = infcx
741 .at(&obligation.cause, obligation.param_env)
742 .eq(DefineOpaqueTypes::Yes, c1, c2)
745 {
746 return ProcessResult::Changed(mk_pending(
747 obligation,
748 new_obligations.into_obligations(),
749 ));
750 }
751 }
752 }
753 }
754
755 let stalled_on = &mut pending_obligation.stalled_on;
756
757 let mut evaluate = |c: Const<'tcx>| {
758 if let ty::ConstKind::Unevaluated(unevaluated) = c.kind() {
759 match super::try_evaluate_const(
760 self.selcx.infcx,
761 c,
762 obligation.param_env,
763 ) {
764 Ok(val) => Ok(val),
765 e @ Err(EvaluateConstErr::HasGenericsOrInfers) => {
766 stalled_on.extend(
767 unevaluated
768 .args
769 .iter()
770 .filter_map(TyOrConstInferVar::maybe_from_generic_arg),
771 );
772 e
773 }
774 e @ Err(
775 EvaluateConstErr::EvaluationFailure(_)
776 | EvaluateConstErr::InvalidConstParamTy(_),
777 ) => e,
778 }
779 } else {
780 Ok(c)
781 }
782 };
783
784 match (evaluate(c1), evaluate(c2)) {
785 (Ok(c1), Ok(c2)) => {
786 match self.selcx.infcx.at(&obligation.cause, obligation.param_env).eq(
787 DefineOpaqueTypes::Yes,
790 c1,
791 c2,
792 ) {
793 Ok(inf_ok) => ProcessResult::Changed(mk_pending(
794 obligation,
795 inf_ok.into_obligations(),
796 )),
797 Err(err) => {
798 ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
799 ExpectedFound::new(c1, c2),
800 err,
801 ))
802 }
803 }
804 }
805 (Err(EvaluateConstErr::InvalidConstParamTy(e)), _)
806 | (_, Err(EvaluateConstErr::InvalidConstParamTy(e))) => {
807 ProcessResult::Error(FulfillmentErrorCode::Select(
808 SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e)),
809 ))
810 }
811 (Err(EvaluateConstErr::EvaluationFailure(e)), _)
812 | (_, Err(EvaluateConstErr::EvaluationFailure(e))) => {
813 ProcessResult::Error(FulfillmentErrorCode::Select(
814 SelectionError::NotConstEvaluatable(NotConstEvaluatable::Error(e)),
815 ))
816 }
817 (Err(EvaluateConstErr::HasGenericsOrInfers), _)
818 | (_, Err(EvaluateConstErr::HasGenericsOrInfers)) => {
819 if c1.has_non_region_infer() || c2.has_non_region_infer() {
820 ProcessResult::Unchanged
821 } else {
822 let expected_found = ExpectedFound::new(c1, c2);
824 ProcessResult::Error(FulfillmentErrorCode::ConstEquate(
825 expected_found,
826 TypeError::ConstMismatch(expected_found),
827 ))
828 }
829 }
830 }
831 }
832 ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(symbol)) => {
833 if may_use_unstable_feature(self.selcx.infcx, obligation.param_env, symbol) {
834 ProcessResult::Changed(Default::default())
835 } else {
836 ProcessResult::Unchanged
837 }
838 }
839 },
840 }
841 }
842
843 #[inline(never)]
844 fn process_backedge<'c, I>(
845 &mut self,
846 cycle: I,
847 _marker: PhantomData<&'c PendingPredicateObligation<'tcx>>,
848 ) -> Result<(), FulfillmentErrorCode<'tcx>>
849 where
850 I: Clone + Iterator<Item = &'c PendingPredicateObligation<'tcx>>,
851 {
852 if self.selcx.coinductive_match(cycle.clone().map(|s| s.obligation.predicate)) {
853 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:853",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(853u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("process_child_obligations: coinductive match")
as &dyn Value))])
});
} else { ; }
};debug!("process_child_obligations: coinductive match");
854 Ok(())
855 } else {
856 let cycle = cycle.map(|c| c.obligation.clone()).collect();
857 Err(FulfillmentErrorCode::Cycle(cycle))
858 }
859 }
860}
861
862impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> {
863 #[allow(clippy :: suspicious_else_formatting)]
{
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() ||
{ false } {
__tracing_attr_span =
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("process_trait_obligation",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(863u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["trait_obligation"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::SPAN)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let mut interest = ::tracing::subscriber::Interest::never();
if ::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{ interest = __CALLSITE.interest(); !interest.is_never() }
&&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest) {
let meta = __CALLSITE.metadata();
::tracing::Span::new(meta,
&{
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = meta.fields().iter();
meta.fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&trait_obligation)
as &dyn Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[warn(clippy :: suspicious_else_formatting)]
{
#[allow(unknown_lints, unreachable_code, clippy ::
diverging_sub_expression, clippy :: empty_loop, clippy ::
let_unit_value, clippy :: let_with_type_underscore, clippy ::
needless_return, clippy :: unreachable)]
if false {
let __tracing_attr_fake_return:
ProcessResult<PendingPredicateObligation<'tcx>,
FulfillmentErrorCode<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let infcx = self.selcx.infcx;
if obligation.predicate.is_global() &&
!infcx.typing_mode().is_coherence() {
if infcx.predicate_must_hold_considering_regions(obligation) {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:875",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(875u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("selecting trait at depth {0} evaluated to holds",
obligation.recursion_depth) as &dyn Value))])
});
} else { ; }
};
return ProcessResult::Changed(Default::default());
}
}
match self.selcx.poly_select(&trait_obligation) {
Ok(Some(impl_source)) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:885",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(885u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("selecting trait at depth {0} yielded Ok(Some)",
obligation.recursion_depth) as &dyn Value))])
});
} else { ; }
};
ProcessResult::Changed(mk_pending(obligation,
impl_source.nested_obligations()))
}
Ok(None) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:889",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(889u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("selecting trait at depth {0} yielded Ok(None)",
obligation.recursion_depth) as &dyn Value))])
});
} else { ; }
};
stalled_on.clear();
stalled_on.extend(args_infer_vars(&self.selcx,
trait_obligation.predicate.map_bound(|pred|
pred.trait_ref.args)));
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:901",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(901u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("process_predicate: pending obligation {0:?} now stalled on {1:?}",
infcx.resolve_vars_if_possible(obligation.clone()),
stalled_on) as &dyn Value))])
});
} else { ; }
};
ProcessResult::Unchanged
}
Err(selection_err) => {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:910",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(910u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("selecting trait at depth {0} yielded Err",
obligation.recursion_depth) as &dyn Value))])
});
} else { ; }
};
ProcessResult::Error(FulfillmentErrorCode::Select(selection_err))
}
}
}
}
}#[instrument(level = "debug", skip(self, obligation, stalled_on))]
864 fn process_trait_obligation(
865 &mut self,
866 obligation: &PredicateObligation<'tcx>,
867 trait_obligation: PolyTraitObligation<'tcx>,
868 stalled_on: &mut Vec<TyOrConstInferVar>,
869 ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
870 let infcx = self.selcx.infcx;
871 if obligation.predicate.is_global() && !infcx.typing_mode().is_coherence() {
872 if infcx.predicate_must_hold_considering_regions(obligation) {
875 debug!(
876 "selecting trait at depth {} evaluated to holds",
877 obligation.recursion_depth
878 );
879 return ProcessResult::Changed(Default::default());
880 }
881 }
882
883 match self.selcx.poly_select(&trait_obligation) {
884 Ok(Some(impl_source)) => {
885 debug!("selecting trait at depth {} yielded Ok(Some)", obligation.recursion_depth);
886 ProcessResult::Changed(mk_pending(obligation, impl_source.nested_obligations()))
887 }
888 Ok(None) => {
889 debug!("selecting trait at depth {} yielded Ok(None)", obligation.recursion_depth);
890
891 stalled_on.clear();
896 stalled_on.extend(args_infer_vars(
897 &self.selcx,
898 trait_obligation.predicate.map_bound(|pred| pred.trait_ref.args),
899 ));
900
901 debug!(
902 "process_predicate: pending obligation {:?} now stalled on {:?}",
903 infcx.resolve_vars_if_possible(obligation.clone()),
904 stalled_on
905 );
906
907 ProcessResult::Unchanged
908 }
909 Err(selection_err) => {
910 debug!("selecting trait at depth {} yielded Err", obligation.recursion_depth);
911
912 ProcessResult::Error(FulfillmentErrorCode::Select(selection_err))
913 }
914 }
915 }
916
917 fn process_projection_obligation(
918 &mut self,
919 obligation: &PredicateObligation<'tcx>,
920 project_obligation: PolyProjectionObligation<'tcx>,
921 stalled_on: &mut Vec<TyOrConstInferVar>,
922 ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
923 let tcx = self.selcx.tcx();
924 let infcx = self.selcx.infcx;
925 if obligation.predicate.is_global() && !infcx.typing_mode().is_coherence() {
926 if infcx.predicate_must_hold_considering_regions(obligation) {
929 if let Some(key) = ProjectionCacheKey::from_poly_projection_obligation(
930 &mut self.selcx,
931 &project_obligation,
932 ) {
933 infcx
937 .inner
938 .borrow_mut()
939 .projection_cache()
940 .complete(key, EvaluationResult::EvaluatedToOk);
941 }
942 return ProcessResult::Changed(Default::default());
943 } else {
944 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/fulfill.rs:944",
"rustc_trait_selection::traits::fulfill",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/fulfill.rs"),
::tracing_core::__macro_support::Option::Some(944u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::fulfill"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::DEBUG <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::DEBUG <=
::tracing::level_filters::LevelFilter::current() &&
{
let interest = __CALLSITE.interest();
!interest.is_never() &&
::tracing::__macro_support::__is_enabled(__CALLSITE.metadata(),
interest)
};
if enabled {
(|value_set: ::tracing::field::ValueSet|
{
let meta = __CALLSITE.metadata();
::tracing::Event::dispatch(meta, &value_set);
;
})({
#[allow(unused_imports)]
use ::tracing::field::{debug, display, Value};
let mut iter = __CALLSITE.metadata().fields().iter();
__CALLSITE.metadata().fields().value_set(&[(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&format_args!("Does NOT hold: {0:?}",
obligation) as &dyn Value))])
});
} else { ; }
};debug!("Does NOT hold: {:?}", obligation);
945 }
946 }
947
948 match project::poly_project_and_unify_term(&mut self.selcx, &project_obligation) {
949 ProjectAndUnifyResult::Holds(os) => ProcessResult::Changed(mk_pending(obligation, os)),
950 ProjectAndUnifyResult::FailedNormalization => {
951 stalled_on.clear();
952 stalled_on.extend(args_infer_vars(
953 &self.selcx,
954 project_obligation.predicate.map_bound(|pred| pred.projection_term.args),
955 ));
956 ProcessResult::Unchanged
957 }
958 ProjectAndUnifyResult::Recursive => {
960 let mut obligations = PredicateObligations::with_capacity(1);
961 obligations.push(project_obligation.with(tcx, project_obligation.predicate));
962
963 ProcessResult::Changed(mk_pending(obligation, obligations))
964 }
965 ProjectAndUnifyResult::MismatchedProjectionTypes(e) => {
966 ProcessResult::Error(FulfillmentErrorCode::Project(e))
967 }
968 }
969 }
970
971 fn process_host_obligation(
972 &mut self,
973 obligation: &PredicateObligation<'tcx>,
974 host_obligation: HostEffectObligation<'tcx>,
975 stalled_on: &mut Vec<TyOrConstInferVar>,
976 ) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
977 match effects::evaluate_host_effect_obligation(&mut self.selcx, &host_obligation) {
978 Ok(nested) => ProcessResult::Changed(mk_pending(obligation, nested)),
979 Err(effects::EvaluationFailure::Ambiguous) => {
980 stalled_on.clear();
981 stalled_on.extend(args_infer_vars(
982 &self.selcx,
983 ty::Binder::dummy(host_obligation.predicate.trait_ref.args),
984 ));
985 ProcessResult::Unchanged
986 }
987 Err(effects::EvaluationFailure::NoSolution) => {
988 ProcessResult::Error(FulfillmentErrorCode::Select(SelectionError::Unimplemented))
989 }
990 }
991 }
992}
993
994fn args_infer_vars<'tcx>(
996 selcx: &SelectionContext<'_, 'tcx>,
997 args: ty::Binder<'tcx, GenericArgsRef<'tcx>>,
998) -> impl Iterator<Item = TyOrConstInferVar> {
999 selcx
1000 .infcx
1001 .resolve_vars_if_possible(args)
1002 .skip_binder() .iter()
1004 .filter(|arg| arg.has_non_region_infer())
1005 .flat_map(|arg| {
1006 let mut walker = arg.walk();
1007 while let Some(c) = walker.next() {
1008 if !c.has_non_region_infer() {
1009 walker.visited.remove(&c);
1010 walker.skip_current_subtree();
1011 }
1012 }
1013 walker.visited.into_iter()
1014 })
1015 .filter_map(TyOrConstInferVar::maybe_from_generic_arg)
1016}
1017
1018#[derive(#[automatically_derived]
impl<'tcx> ::core::fmt::Debug for OldSolverError<'tcx> {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_tuple_field1_finish(f, "OldSolverError",
&&self.0)
}
}Debug)]
1019pub struct OldSolverError<'tcx>(
1020 Error<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>>,
1021);
1022
1023impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for FulfillmentError<'tcx> {
1024 fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
1025 let mut iter = error.0.backtrace.into_iter();
1026 let obligation = iter.next().unwrap().obligation;
1027 let root_obligation = iter.next_back().map_or_else(|| obligation.clone(), |e| e.obligation);
1030 FulfillmentError::new(obligation, error.0.error, root_obligation)
1031 }
1032}
1033
1034impl<'tcx> FromSolverError<'tcx, OldSolverError<'tcx>> for ScrubbedTraitError<'tcx> {
1035 fn from_solver_error(_infcx: &InferCtxt<'tcx>, error: OldSolverError<'tcx>) -> Self {
1036 match error.0.error {
1037 FulfillmentErrorCode::Select(_)
1038 | FulfillmentErrorCode::Project(_)
1039 | FulfillmentErrorCode::Subtype(_, _)
1040 | FulfillmentErrorCode::ConstEquate(_, _) => ScrubbedTraitError::TrueError,
1041 FulfillmentErrorCode::Ambiguity { overflow: _ } => ScrubbedTraitError::Ambiguity,
1042 FulfillmentErrorCode::Cycle(cycle) => ScrubbedTraitError::Cycle(cycle),
1043 }
1044 }
1045}