1use rustc_data_structures::fx::FxIndexSet;
2use rustc_hir::def_id::LocalDefId;
3use rustc_infer::infer::outlives::env::OutlivesEnvironment;
4use rustc_infer::infer::{
5 InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt, TypeOutlivesConstraint,
6};
7use rustc_macros::extension;
8use rustc_middle::traits::ObligationCause;
9use rustc_middle::traits::query::NoSolution;
10use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode, Unnormalized, elaborate};
11use rustc_span::{DUMMY_SP, Span};
12
13use crate::traits::ScrubbedTraitError;
14use crate::traits::outlives_bounds::InferCtxtExt;
15
16impl<'tcx> OutlivesEnvironmentBuildExt<'tcx> for OutlivesEnvironment<'tcx> {
fn new(infcx: &InferCtxt<'tcx>, body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>) -> Self {
Self::new_with_implied_bounds_compat(infcx, body_def_id, param_env,
assumed_wf_tys, false)
}
fn new_with_implied_bounds_compat(infcx: &InferCtxt<'tcx>,
body_def_id: LocalDefId, param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
disable_implied_bounds_hack: bool) -> Self {
let mut bounds = ::alloc::vec::Vec::new();
for bound in param_env.caller_bounds() {
if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
if infcx.next_trait_solver() {
match crate::solve::deeply_normalize::<_,
ScrubbedTraitError<'tcx>>(infcx.at(&ObligationCause::dummy(),
param_env), Unnormalized::new_wip(type_outlives)) {
Ok(new) => type_outlives = new,
Err(_) => {
infcx.dcx().delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("could not normalize `{0}`",
bound))
}));
}
}
}
bounds.push(type_outlives);
}
}
let higher_ranked_assumptions =
infcx.take_registered_region_assumptions();
let higher_ranked_assumptions =
elaborate::elaborate_outlives_assumptions(infcx.tcx,
higher_ranked_assumptions);
OutlivesEnvironment::from_normalized_bounds(param_env, bounds,
infcx.implied_bounds_tys(body_def_id, param_env, assumed_wf_tys,
disable_implied_bounds_hack), higher_ranked_assumptions)
}
}#[extension(pub trait OutlivesEnvironmentBuildExt<'tcx>)]
17impl<'tcx> OutlivesEnvironment<'tcx> {
18 fn new(
19 infcx: &InferCtxt<'tcx>,
20 body_def_id: LocalDefId,
21 param_env: ty::ParamEnv<'tcx>,
22 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
23 ) -> Self {
24 Self::new_with_implied_bounds_compat(infcx, body_def_id, param_env, assumed_wf_tys, false)
25 }
26
27 fn new_with_implied_bounds_compat(
28 infcx: &InferCtxt<'tcx>,
29 body_def_id: LocalDefId,
30 param_env: ty::ParamEnv<'tcx>,
31 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
32 disable_implied_bounds_hack: bool,
33 ) -> Self {
34 let mut bounds = vec![];
35
36 for bound in param_env.caller_bounds() {
37 if let Some(mut type_outlives) = bound.as_type_outlives_clause() {
38 if infcx.next_trait_solver() {
39 match crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
40 infcx.at(&ObligationCause::dummy(), param_env),
41 Unnormalized::new_wip(type_outlives),
42 ) {
43 Ok(new) => type_outlives = new,
44 Err(_) => {
45 infcx.dcx().delayed_bug(format!("could not normalize `{bound}`"));
46 }
47 }
48 }
49 bounds.push(type_outlives);
50 }
51 }
52
53 let higher_ranked_assumptions = infcx.take_registered_region_assumptions();
55 let higher_ranked_assumptions =
56 elaborate::elaborate_outlives_assumptions(infcx.tcx, higher_ranked_assumptions);
57
58 OutlivesEnvironment::from_normalized_bounds(
63 param_env,
64 bounds,
65 infcx.implied_bounds_tys(
66 body_def_id,
67 param_env,
68 assumed_wf_tys,
69 disable_implied_bounds_hack,
70 ),
71 higher_ranked_assumptions,
72 )
73 }
74}
75
76impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
#[doc =
" Resolve regions, using the deep normalizer to normalize any type-outlives"]
#[doc =
" obligations in the process. This is in `rustc_trait_selection` because"]
#[doc = " we need to normalize."]
#[doc = ""]
#[doc =
" Prefer this method over `resolve_regions_with_normalize`, unless you are"]
#[doc = " doing something specific for normalization."]
#[doc = ""]
#[doc =
" This function assumes that all infer variables are already constrained."]
fn resolve_regions(&self, body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>)
-> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new(self,
body_def_id, param_env, assumed_wf_tys),
self.tcx.def_span(body_def_id))
}
#[doc = " Don\'t call this directly unless you know what you\'re doing."]
fn resolve_regions_with_outlives_env(&self,
outlives_env: &OutlivesEnvironment<'tcx>, span: Span)
-> Vec<RegionResolutionError<'tcx>> {
self.resolve_regions_with_normalize(&outlives_env,
|ty, origin|
{
let ty = self.resolve_vars_if_possible(ty);
if self.next_trait_solver() {
crate::solve::deeply_normalize(self.at(&ObligationCause::dummy_with_span(origin.span()),
outlives_env.param_env),
Unnormalized::new_wip(ty)).map_err(|_:
Vec<ScrubbedTraitError<'tcx>>| NoSolution)
} else { Ok(ty) }
}, span)
}
}#[extension(pub trait InferCtxtRegionExt<'tcx>)]
77impl<'tcx> InferCtxt<'tcx> {
78 fn resolve_regions(
87 &self,
88 body_def_id: LocalDefId,
89 param_env: ty::ParamEnv<'tcx>,
90 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
91 ) -> Vec<RegionResolutionError<'tcx>> {
92 self.resolve_regions_with_outlives_env(
93 &OutlivesEnvironment::new(self, body_def_id, param_env, assumed_wf_tys),
94 self.tcx.def_span(body_def_id),
95 )
96 }
97
98 fn resolve_regions_with_outlives_env(
100 &self,
101 outlives_env: &OutlivesEnvironment<'tcx>,
102 span: Span,
103 ) -> Vec<RegionResolutionError<'tcx>> {
104 self.resolve_regions_with_normalize(
105 &outlives_env,
106 |ty, origin| {
107 let ty = self.resolve_vars_if_possible(ty);
108
109 if self.next_trait_solver() {
110 crate::solve::deeply_normalize(
111 self.at(
112 &ObligationCause::dummy_with_span(origin.span()),
113 outlives_env.param_env,
114 ),
115 Unnormalized::new_wip(ty),
116 )
117 .map_err(|_: Vec<ScrubbedTraitError<'tcx>>| NoSolution)
118 } else {
119 Ok(ty)
120 }
121 },
122 span,
123 )
124 }
125}
126
127pub fn ty_known_to_outlive<'tcx>(
130 tcx: TyCtxt<'tcx>,
131 id: LocalDefId,
132 param_env: ty::ParamEnv<'tcx>,
133 wf_tys: &FxIndexSet<Ty<'tcx>>,
134 ty: Ty<'tcx>,
135 region: ty::Region<'tcx>,
136) -> bool {
137 test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
138 infcx.register_type_outlives_constraint_inner(TypeOutlivesConstraint {
139 sub_region: region,
140 sup_type: ty,
141 origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None),
142 });
143 })
144}
145
146pub fn region_known_to_outlive<'tcx>(
149 tcx: TyCtxt<'tcx>,
150 id: LocalDefId,
151 param_env: ty::ParamEnv<'tcx>,
152 wf_tys: &FxIndexSet<Ty<'tcx>>,
153 region_a: ty::Region<'tcx>,
154 region_b: ty::Region<'tcx>,
155) -> bool {
156 test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
157 infcx.sub_regions(
158 SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
159 region_b,
160 region_a,
161 ty::VisibleForLeakCheck::Unreachable,
162 );
163 })
164}
165
166pub fn test_region_obligations<'tcx>(
170 tcx: TyCtxt<'tcx>,
171 id: LocalDefId,
172 param_env: ty::ParamEnv<'tcx>,
173 wf_tys: &FxIndexSet<Ty<'tcx>>,
174 add_constraints: impl FnOnce(&InferCtxt<'tcx>),
175) -> bool {
176 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
180
181 add_constraints(&infcx);
182
183 let errors = infcx.resolve_regions(id, param_env, wf_tys.iter().copied());
184 {
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/regions.rs:184",
"rustc_trait_selection::regions", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/regions.rs"),
::tracing_core::__macro_support::Option::Some(184u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::regions"),
::tracing_core::field::FieldSet::new(&["message", "errors"],
::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!("errors")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&errors) as
&dyn Value))])
});
} else { ; }
};tracing::debug!(?errors, "errors");
185
186 errors.is_empty()
189}