rustc_hir_typeck/fn_ctxt/
inspect_obligations.rs1use rustc_infer::traits::{self, ObligationCause, PredicateObligations};
4use rustc_middle::ty::{self, Ty, TypeVisitableExt};
5use rustc_span::Span;
6use rustc_trait_selection::solve::Certainty;
7use rustc_trait_selection::solve::inspect::{
8 InferCtxtProofTreeExt, InspectConfig, InspectGoal, ProofTreeVisitor,
9};
10use tracing::{debug, instrument, trace};
11
12use crate::FnCtxt;
13
14impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
15 #[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("obligations_for_self_ty",
"rustc_hir_typeck::fn_ctxt::inspect_obligations",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs"),
::tracing_core::__macro_support::Option::Some(17u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::inspect_obligations"),
::tracing_core::field::FieldSet::new(&["self_ty"],
::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(&self_ty)
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: PredicateObligations<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
if self.next_trait_solver() {
self.obligations_for_self_ty_next(self_ty)
} else {
let ty_var_root = self.root_var(self_ty);
let mut obligations =
self.fulfillment_cx.borrow().pending_obligations();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs:24",
"rustc_hir_typeck::fn_ctxt::inspect_obligations",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs"),
::tracing_core::__macro_support::Option::Some(24u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::inspect_obligations"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::TRACE <=
::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!("pending_obligations = {0:#?}",
obligations) as &dyn Value))])
});
} else { ; }
};
obligations.retain(|obligation|
self.predicate_has_self_ty(obligation.predicate,
ty_var_root));
obligations
}
}
}
}#[instrument(skip(self), level = "debug")]
18 pub(crate) fn obligations_for_self_ty(&self, self_ty: ty::TyVid) -> PredicateObligations<'tcx> {
19 if self.next_trait_solver() {
20 self.obligations_for_self_ty_next(self_ty)
21 } else {
22 let ty_var_root = self.root_var(self_ty);
23 let mut obligations = self.fulfillment_cx.borrow().pending_obligations();
24 trace!("pending_obligations = {:#?}", obligations);
25 obligations
26 .retain(|obligation| self.predicate_has_self_ty(obligation.predicate, ty_var_root));
27 obligations
28 }
29 }
30
31 x;#[instrument(level = "debug", skip(self), ret)]
32 fn predicate_has_self_ty(
33 &self,
34 predicate: ty::Predicate<'tcx>,
35 expected_vid: ty::TyVid,
36 ) -> bool {
37 match predicate.kind().skip_binder() {
38 ty::PredicateKind::Clause(ty::ClauseKind::Trait(data)) => {
39 self.type_matches_expected_vid(expected_vid, data.self_ty())
40 }
41 ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
42 self.type_matches_expected_vid(expected_vid, data.projection_term.self_ty())
43 }
44 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(..))
45 | ty::PredicateKind::Subtype(..)
46 | ty::PredicateKind::Coerce(..)
47 | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..))
48 | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(..))
49 | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(..))
50 | ty::PredicateKind::DynCompatible(..)
51 | ty::PredicateKind::NormalizesTo(..)
52 | ty::PredicateKind::AliasRelate(..)
53 | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(..))
54 | ty::PredicateKind::ConstEquate(..)
55 | ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(..))
56 | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_))
57 | ty::PredicateKind::Ambiguous => false,
58 }
59 }
60
61 x;#[instrument(level = "debug", skip(self), ret)]
62 fn type_matches_expected_vid(&self, expected_vid: ty::TyVid, ty: Ty<'tcx>) -> bool {
63 let ty = self.shallow_resolve(ty);
64 debug!(?ty);
65
66 match *ty.kind() {
67 ty::Infer(ty::TyVar(found_vid)) => {
68 self.root_var(expected_vid) == self.root_var(found_vid)
69 }
70 _ => false,
71 }
72 }
73
74 pub(crate) fn obligations_for_self_ty_next(
75 &self,
76 self_ty: ty::TyVid,
77 ) -> PredicateObligations<'tcx> {
78 let obligations = self.fulfillment_cx.borrow().pending_obligations();
79 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs:79",
"rustc_hir_typeck::fn_ctxt::inspect_obligations",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_hir_typeck/src/fn_ctxt/inspect_obligations.rs"),
::tracing_core::__macro_support::Option::Some(79u32),
::tracing_core::__macro_support::Option::Some("rustc_hir_typeck::fn_ctxt::inspect_obligations"),
::tracing_core::field::FieldSet::new(&["obligations"],
::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(&debug(&obligations)
as &dyn Value))])
});
} else { ; }
};debug!(?obligations);
80 let mut obligations_for_self_ty = PredicateObligations::new();
81 for obligation in obligations {
82 let mut visitor = NestedObligationsForSelfTy {
83 fcx: self,
84 self_ty,
85 obligations_for_self_ty: &mut obligations_for_self_ty,
86 root_cause: &obligation.cause,
87 };
88
89 let goal = obligation.as_goal();
90 self.visit_proof_tree(goal, &mut visitor);
91 }
92
93 obligations_for_self_ty.retain_mut(|obligation| {
94 obligation.predicate = self.resolve_vars_if_possible(obligation.predicate);
95 !obligation.predicate.has_placeholders()
96 });
97 obligations_for_self_ty
98 }
99}
100
101struct NestedObligationsForSelfTy<'a, 'tcx> {
102 fcx: &'a FnCtxt<'a, 'tcx>,
103 self_ty: ty::TyVid,
104 root_cause: &'a ObligationCause<'tcx>,
105 obligations_for_self_ty: &'a mut PredicateObligations<'tcx>,
106}
107
108impl<'a, 'tcx> ProofTreeVisitor<'tcx> for NestedObligationsForSelfTy<'a, 'tcx> {
109 fn span(&self) -> Span {
110 self.root_cause.span
111 }
112
113 fn config(&self) -> InspectConfig {
114 InspectConfig { max_depth: 5 }
118 }
119
120 fn visit_goal(&mut self, inspect_goal: &InspectGoal<'_, 'tcx>) {
121 if inspect_goal.result() == Ok(Certainty::Yes) {
124 return;
125 }
126
127 let tcx = self.fcx.tcx;
128 let goal = inspect_goal.goal();
129 if self.fcx.predicate_has_self_ty(goal.predicate, self.self_ty) {
130 self.obligations_for_self_ty.push(traits::Obligation::new(
131 tcx,
132 self.root_cause.clone(),
133 goal.param_env,
134 goal.predicate,
135 ));
136 }
137
138 if let Some(candidate) = inspect_goal.unique_applicable_candidate() {
143 candidate.visit_nested_no_probe(self)
144 }
145 }
146}