1use rustc_data_structures::fx::FxHashSet;
2use rustc_hir::def_id::LocalDefId;
3use rustc_infer::infer::SubregionOrigin;
4use rustc_infer::infer::canonical::QueryRegionConstraints;
5use rustc_infer::infer::outlives::env::RegionBoundPairs;
6use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelegate};
7use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound};
8use rustc_infer::traits::query::type_op::DeeplyNormalize;
9use rustc_middle::bug;
10use rustc_middle::ty::{
11 self, GenericArgKind, Ty, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate, fold_regions,
12};
13use rustc_span::Span;
14use rustc_trait_selection::traits::query::type_op::{TypeOp, TypeOpOutput};
15use tracing::{debug, instrument};
16
17use crate::constraints::OutlivesConstraint;
18use crate::region_infer::TypeTest;
19use crate::type_check::{Locations, MirTypeckRegionConstraints};
20use crate::universal_regions::UniversalRegions;
21use crate::{
22 BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory,
23};
24
25pub(crate) struct ConstraintConversion<'a, 'tcx> {
26 infcx: &'a BorrowckInferCtxt<'tcx>,
27 universal_regions: &'a UniversalRegions<'tcx>,
28 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
39 known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
40 locations: Locations,
41 span: Span,
42 category: ConstraintCategory<'tcx>,
43 from_closure: bool,
44 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
45}
46
47impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
48 pub(crate) fn new(
49 infcx: &'a BorrowckInferCtxt<'tcx>,
50 universal_regions: &'a UniversalRegions<'tcx>,
51 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
52 known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesPredicate<'tcx>],
53 locations: Locations,
54 span: Span,
55 category: ConstraintCategory<'tcx>,
56 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
57 ) -> Self {
58 Self {
59 infcx,
60 universal_regions,
61 region_bound_pairs,
62 known_type_outlives_obligations,
63 locations,
64 span,
65 category,
66 constraints,
67 from_closure: false,
68 }
69 }
70
71 #[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("convert_all",
"rustc_borrowck::type_check::constraint_conversion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/type_check/constraint_conversion.rs"),
::tracing_core::__macro_support::Option::Some(71u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::type_check::constraint_conversion"),
::tracing_core::field::FieldSet::new(&["query_constraints"],
::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(&query_constraints)
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: () = loop {};
return __tracing_attr_fake_return;
}
{
let QueryRegionConstraints { constraints, assumptions } =
query_constraints;
let assumptions =
elaborate::elaborate_outlives_assumptions(self.infcx.tcx,
assumptions.iter().copied());
for &(constraint, constraint_category, _) in constraints {
constraint.iter_outlives().for_each(|predicate|
{
self.convert(predicate, constraint_category, &assumptions);
});
}
}
}
}#[instrument(skip(self), level = "debug")]
72 pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
73 let QueryRegionConstraints { constraints, assumptions } = query_constraints;
74 let assumptions =
75 elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
76
77 for &(constraint, constraint_category, _) in constraints {
78 constraint.iter_outlives().for_each(|predicate| {
79 self.convert(predicate, constraint_category, &assumptions);
80 });
81 }
82 }
83
84 #[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("apply_closure_requirements",
"rustc_borrowck::type_check::constraint_conversion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/type_check/constraint_conversion.rs"),
::tracing_core::__macro_support::Option::Some(87u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::type_check::constraint_conversion"),
::tracing_core::field::FieldSet::new(&["closure_requirements",
"closure_def_id", "closure_args"],
::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(&closure_requirements)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&closure_def_id)
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&::tracing::field::debug(&closure_args)
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: () = loop {};
return __tracing_attr_fake_return;
}
{
let closure_mapping =
&UniversalRegions::closure_mapping(self.infcx.tcx,
closure_args, closure_requirements.num_external_vids,
closure_def_id);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/type_check/constraint_conversion.rs:103",
"rustc_borrowck::type_check::constraint_conversion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/type_check/constraint_conversion.rs"),
::tracing_core::__macro_support::Option::Some(103u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::type_check::constraint_conversion"),
::tracing_core::field::FieldSet::new(&["closure_mapping"],
::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(&closure_mapping)
as &dyn Value))])
});
} else { ; }
};
let backup = (self.category, self.span, self.from_closure);
self.from_closure = true;
for outlives_requirement in
&closure_requirements.outlives_requirements {
let outlived_region =
closure_mapping[outlives_requirement.outlived_free_region];
let subject =
match outlives_requirement.subject {
ClosureOutlivesSubject::Region(re) =>
closure_mapping[re].into(),
ClosureOutlivesSubject::Ty(subject_ty) => {
subject_ty.instantiate(self.infcx.tcx,
|vid| closure_mapping[vid]).into()
}
};
self.category = outlives_requirement.category;
self.span = outlives_requirement.blame_span;
self.convert(ty::OutlivesPredicate(subject, outlived_region),
self.category, &Default::default());
}
(self.category, self.span, self.from_closure) = backup;
}
}
}#[instrument(skip(self), level = "debug")]
88 pub(crate) fn apply_closure_requirements(
89 &mut self,
90 closure_requirements: &ClosureRegionRequirements<'tcx>,
91 closure_def_id: LocalDefId,
92 closure_args: ty::GenericArgsRef<'tcx>,
93 ) {
94 let closure_mapping = &UniversalRegions::closure_mapping(
98 self.infcx.tcx,
99 closure_args,
100 closure_requirements.num_external_vids,
101 closure_def_id,
102 );
103 debug!(?closure_mapping);
104
105 let backup = (self.category, self.span, self.from_closure);
107 self.from_closure = true;
108 for outlives_requirement in &closure_requirements.outlives_requirements {
109 let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
110 let subject = match outlives_requirement.subject {
111 ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
112 ClosureOutlivesSubject::Ty(subject_ty) => {
113 subject_ty.instantiate(self.infcx.tcx, |vid| closure_mapping[vid]).into()
114 }
115 };
116
117 self.category = outlives_requirement.category;
118 self.span = outlives_requirement.blame_span;
119 self.convert(
120 ty::OutlivesPredicate(subject, outlived_region),
121 self.category,
122 &Default::default(),
123 );
124 }
125 (self.category, self.span, self.from_closure) = backup;
126 }
127
128 fn convert(
129 &mut self,
130 predicate: ty::ArgOutlivesPredicate<'tcx>,
131 constraint_category: ConstraintCategory<'tcx>,
132 higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesPredicate<'tcx>>,
133 ) {
134 let tcx = self.infcx.tcx;
135 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/type_check/constraint_conversion.rs:135",
"rustc_borrowck::type_check::constraint_conversion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/type_check/constraint_conversion.rs"),
::tracing_core::__macro_support::Option::Some(135u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::type_check::constraint_conversion"),
::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!("generate: constraints at: {0:#?}",
self.locations) as &dyn Value))])
});
} else { ; }
};debug!("generate: constraints at: {:#?}", self.locations);
136
137 let ConstraintConversion {
139 infcx,
140 universal_regions,
141 region_bound_pairs,
142 known_type_outlives_obligations,
143 ..
144 } = *self;
145
146 let mut outlives_predicates = ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[(predicate, constraint_category)]))vec![(predicate, constraint_category)];
147 for iteration in 0.. {
148 if outlives_predicates.is_empty() {
149 break;
150 }
151
152 if !tcx.recursion_limit().value_within_limit(iteration) {
153 ::rustc_middle::util::bug::bug_fmt(format_args!("unexpected overflowed when processing region obligations: {0:#?}",
outlives_predicates));bug!(
157 "unexpected overflowed when processing region obligations: {outlives_predicates:#?}"
158 );
159 }
160
161 let mut next_outlives_predicates = ::alloc::vec::Vec::new()vec![];
162 for (pred, constraint_category) in outlives_predicates {
163 if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
165 && higher_ranked_assumptions.contains(&pred)
166 {
167 continue;
168 }
169
170 let ty::OutlivesPredicate(k1, r2) = pred;
171 match k1.kind() {
172 GenericArgKind::Lifetime(r1) => {
173 let r1_vid = self.to_region_vid(r1);
174 let r2_vid = self.to_region_vid(r2);
175 self.add_outlives(r1_vid, r2_vid, constraint_category);
176 }
177
178 GenericArgKind::Type(mut t1) => {
179 t1 = self.infcx.resolve_vars_if_possible(t1);
181
182 if infcx.next_trait_solver() {
185 t1 = self.normalize_and_add_type_outlives_constraints(
186 t1,
187 &mut next_outlives_predicates,
188 );
189 }
190
191 let implicit_region_bound =
192 ty::Region::new_var(tcx, universal_regions.implicit_region_bound());
193 let origin = SubregionOrigin::RelateParamBound(self.span, t1, None);
196 TypeOutlives::new(
197 &mut *self,
198 tcx,
199 region_bound_pairs,
200 Some(implicit_region_bound),
201 known_type_outlives_obligations,
202 )
203 .type_must_outlive(
204 origin,
205 t1,
206 r2,
207 constraint_category,
208 );
209 }
210
211 GenericArgKind::Const(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
212 }
213 }
214
215 outlives_predicates = next_outlives_predicates;
216 }
217 }
218
219 fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
226 if value.has_placeholders() {
227 fold_regions(self.infcx.tcx, value, |r, _| match r.kind() {
228 ty::RePlaceholder(placeholder) => {
229 self.constraints.placeholder_region(self.infcx, placeholder)
230 }
231 _ => r,
232 })
233 } else {
234 value
235 }
236 }
237
238 fn verify_to_type_test(
239 &mut self,
240 generic_kind: GenericKind<'tcx>,
241 region: ty::Region<'tcx>,
242 verify_bound: VerifyBound<'tcx>,
243 ) -> TypeTest<'tcx> {
244 let lower_bound = self.to_region_vid(region);
245 TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
246 }
247
248 fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
249 if let ty::RePlaceholder(placeholder) = r.kind() {
250 self.constraints.placeholder_region(self.infcx, placeholder).as_var()
251 } else {
252 self.universal_regions.to_region_vid(r)
253 }
254 }
255
256 fn add_outlives(
257 &mut self,
258 sup: ty::RegionVid,
259 sub: ty::RegionVid,
260 category: ConstraintCategory<'tcx>,
261 ) {
262 let category = match self.category {
263 ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
264 _ => self.category,
265 };
266 self.constraints.outlives_constraints.push(OutlivesConstraint {
267 locations: self.locations,
268 category,
269 span: self.span,
270 sub,
271 sup,
272 variance_info: ty::VarianceDiagInfo::default(),
273 from_closure: self.from_closure,
274 });
275 }
276
277 fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
278 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_borrowck/src/type_check/constraint_conversion.rs:278",
"rustc_borrowck::type_check::constraint_conversion",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_borrowck/src/type_check/constraint_conversion.rs"),
::tracing_core::__macro_support::Option::Some(278u32),
::tracing_core::__macro_support::Option::Some("rustc_borrowck::type_check::constraint_conversion"),
::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!("add_type_test(type_test={0:?})",
type_test) as &dyn Value))])
});
} else { ; }
};debug!("add_type_test(type_test={:?})", type_test);
279 self.constraints.type_tests.push(type_test);
280 }
281
282 fn normalize_and_add_type_outlives_constraints(
283 &self,
284 ty: Ty<'tcx>,
285 next_outlives_predicates: &mut Vec<(
286 ty::ArgOutlivesPredicate<'tcx>,
287 ConstraintCategory<'tcx>,
288 )>,
289 ) -> Ty<'tcx> {
290 match self.infcx.param_env.and(DeeplyNormalize { value: ty }).fully_perform(
291 self.infcx,
292 self.infcx.root_def_id,
293 self.span,
294 ) {
295 Ok(TypeOpOutput { output: ty, constraints, .. }) => {
296 if let Some(QueryRegionConstraints { constraints, assumptions: _ }) = constraints {
298 next_outlives_predicates.extend(constraints.iter().flat_map(
299 |(constraint, category, _)| {
300 constraint.iter_outlives().map(|outlives| (outlives, *category))
301 },
302 ));
303 }
304 ty
305 }
306 Err(_) => ty,
307 }
308 }
309}
310
311impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
312 fn push_sub_region_constraint(
313 &mut self,
314 _origin: SubregionOrigin<'tcx>,
315 a: ty::Region<'tcx>,
316 b: ty::Region<'tcx>,
317 constraint_category: ConstraintCategory<'tcx>,
318 ) {
319 let b = self.to_region_vid(b);
320 let a = self.to_region_vid(a);
321 self.add_outlives(b, a, constraint_category);
322 }
323
324 fn push_verify(
325 &mut self,
326 _origin: SubregionOrigin<'tcx>,
327 kind: GenericKind<'tcx>,
328 a: ty::Region<'tcx>,
329 bound: VerifyBound<'tcx>,
330 ) {
331 let kind = self.replace_placeholders_with_nll(kind);
332 let bound = self.replace_placeholders_with_nll(bound);
333 let type_test = self.verify_to_type_test(kind, a, bound);
334 self.add_type_test(type_test);
335 }
336}