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::ty::{
10 self, CallerBoundsIterator, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, elaborate,
11};
12use rustc_span::DUMMY_SP;
13
14use crate::traits::ScrubbedTraitError;
15use crate::traits::outlives_bounds::InferCtxtExt;
16
17pub trait OutlivesEnvironmentBuildExt<'tcx> {
fn new(infcx: &InferCtxt<'tcx>, body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>)
-> Self;
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;
}
impl<'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().non_trait_clauses().iter() {
if let Some(type_outlives) = bound.as_type_outlives_clause() {
if true {
if !(!infcx.next_trait_solver() ||
!type_outlives.has_non_rigid_aliases()) {
::core::panicking::panic("assertion failed: !infcx.next_trait_solver() || !type_outlives.has_non_rigid_aliases()")
};
};
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>)]
18impl<'tcx> OutlivesEnvironment<'tcx> {
19 fn new(
20 infcx: &InferCtxt<'tcx>,
21 body_def_id: LocalDefId,
22 param_env: ty::ParamEnv<'tcx>,
23 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
24 ) -> Self {
25 Self::new_with_implied_bounds_compat(infcx, body_def_id, param_env, assumed_wf_tys, false)
26 }
27
28 fn new_with_implied_bounds_compat(
29 infcx: &InferCtxt<'tcx>,
30 body_def_id: LocalDefId,
31 param_env: ty::ParamEnv<'tcx>,
32 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
33 disable_implied_bounds_hack: bool,
34 ) -> Self {
35 let mut bounds = vec![];
36
37 for bound in param_env.caller_bounds().non_trait_clauses().iter() {
38 if let Some(type_outlives) = bound.as_type_outlives_clause() {
39 debug_assert!(!infcx.next_trait_solver() || !type_outlives.has_non_rigid_aliases());
40 bounds.push(type_outlives);
41 }
42 }
43
44 let higher_ranked_assumptions = infcx.take_registered_region_assumptions();
46 let higher_ranked_assumptions =
47 elaborate::elaborate_outlives_assumptions(infcx.tcx, higher_ranked_assumptions);
48
49 OutlivesEnvironment::from_normalized_bounds(
54 param_env,
55 bounds,
56 infcx.implied_bounds_tys(
57 body_def_id,
58 param_env,
59 assumed_wf_tys,
60 disable_implied_bounds_hack,
61 ),
62 higher_ranked_assumptions,
63 )
64 }
65}
66
67pub trait InferCtxtRegionExt<'tcx> {
#[doc = " Resolve regions lexically."]
#[doc = ""]
#[doc =
" This function assumes that all infer variables are already constrained."]
#[doc = ""]
#[doc =
" FIXME(#155345): this can probably be moved back to `rustc_infer` now that normalization is"]
#[doc =
" no longer required. These two extension traits won\'t be needed then."]
fn resolve_regions(&self, body_def_id: LocalDefId,
param_env: ty::ParamEnv<'tcx>,
assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>)
-> Vec<RegionResolutionError<'tcx>>;
}
impl<'tcx> InferCtxtRegionExt<'tcx> for InferCtxt<'tcx> {
#[doc = " Resolve regions lexically."]
#[doc = ""]
#[doc =
" This function assumes that all infer variables are already constrained."]
#[doc = ""]
#[doc =
" FIXME(#155345): this can probably be moved back to `rustc_infer` now that normalization is"]
#[doc =
" no longer required. These two extension traits won\'t be needed then."]
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))
}
}#[extension(pub trait InferCtxtRegionExt<'tcx>)]
68impl<'tcx> InferCtxt<'tcx> {
69 fn resolve_regions(
76 &self,
77 body_def_id: LocalDefId,
78 param_env: ty::ParamEnv<'tcx>,
79 assumed_wf_tys: impl IntoIterator<Item = Ty<'tcx>>,
80 ) -> Vec<RegionResolutionError<'tcx>> {
81 self.resolve_regions_with_outlives_env(&OutlivesEnvironment::new(
82 self,
83 body_def_id,
84 param_env,
85 assumed_wf_tys,
86 ))
87 }
88}
89
90pub fn ty_known_to_outlive<'tcx>(
93 tcx: TyCtxt<'tcx>,
94 id: LocalDefId,
95 param_env: ty::ParamEnv<'tcx>,
96 wf_tys: &FxIndexSet<Ty<'tcx>>,
97 ty: Unnormalized<'tcx, Ty<'tcx>>,
98 region: ty::Region<'tcx>,
99) -> bool {
100 test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
101 let ty = if infcx.next_trait_solver() {
103 let Ok(ty) = crate::solve::deeply_normalize::<_, ScrubbedTraitError<'tcx>>(
104 infcx.at(&ObligationCause::dummy_with_span(DUMMY_SP), param_env),
105 ty,
106 ) else {
107 return Err(());
108 };
109 ty
110 } else {
111 ty.skip_norm_wip()
112 };
113
114 infcx.register_type_outlives_constraint_inner(TypeOutlivesConstraint {
115 sub_region: region,
116 sup_type: ty,
117 origin: SubregionOrigin::RelateParamBound(DUMMY_SP, ty, None),
118 });
119
120 Ok(())
121 })
122}
123
124pub fn region_known_to_outlive<'tcx>(
127 tcx: TyCtxt<'tcx>,
128 id: LocalDefId,
129 param_env: ty::ParamEnv<'tcx>,
130 wf_tys: &FxIndexSet<Ty<'tcx>>,
131 region_a: ty::Region<'tcx>,
132 region_b: ty::Region<'tcx>,
133) -> bool {
134 test_region_obligations(tcx, id, param_env, wf_tys, |infcx| {
135 infcx.sub_regions(
136 SubregionOrigin::RelateRegionParamBound(DUMMY_SP, None),
137 region_b,
138 region_a,
139 ty::VisibleForLeakCheck::Unreachable,
140 );
141 Ok(())
142 })
143}
144
145pub fn test_region_obligations<'tcx>(
149 tcx: TyCtxt<'tcx>,
150 id: LocalDefId,
151 param_env: ty::ParamEnv<'tcx>,
152 wf_tys: &FxIndexSet<Ty<'tcx>>,
153 add_constraints: impl FnOnce(&InferCtxt<'tcx>) -> Result<(), ()>,
154) -> bool {
155 let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis());
159
160 if add_constraints(&infcx).is_err() {
161 return false;
162 }
163
164 let errors = infcx.resolve_regions(id, param_env, wf_tys.iter().copied());
165 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/regions.rs:165",
"rustc_trait_selection::regions", ::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/f5cedb83a788ea9581097abc36a2a8503a7f541c/compiler/rustc_trait_selection/src/regions.rs"),
::tracing_core::__macro_support::Option::Some(165u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::regions"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("errors")
}> =
::tracing::__macro_support::FieldName::new("errors");
NAME.as_str()
}], ::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};
__CALLSITE.metadata().fields().value_set_all(&[(::tracing::__macro_support::Option::Some(&format_args!("errors")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&errors)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};tracing::debug!(?errors, "errors");
166
167 errors.is_empty()
170}