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