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_middle::ty::{
9 self, GenericArgKind, RegionExt, TyCtxt, TypeFoldable, TypeVisitableExt, elaborate,
10 fold_regions,
11};
12use rustc_span::Span;
13use tracing::{debug, instrument};
14
15use crate::constraints::OutlivesConstraint;
16use crate::region_infer::TypeTest;
17use crate::type_check::{Locations, MirTypeckRegionConstraints};
18use crate::universal_regions::UniversalRegions;
19use crate::{
20 BorrowckInferCtxt, ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory,
21};
22
23pub(crate) struct ConstraintConversion<'a, 'tcx> {
24 infcx: &'a BorrowckInferCtxt<'tcx>,
25 universal_regions: &'a UniversalRegions<'tcx>,
26 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
37 known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesClause<'tcx>],
38 locations: Locations,
39 span: Span,
40 category: ConstraintCategory<'tcx>,
41 from_closure: bool,
42 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
43}
44
45impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> {
46 pub(crate) fn new(
47 infcx: &'a BorrowckInferCtxt<'tcx>,
48 universal_regions: &'a UniversalRegions<'tcx>,
49 region_bound_pairs: &'a RegionBoundPairs<'tcx>,
50 known_type_outlives_obligations: &'a [ty::PolyTypeOutlivesClause<'tcx>],
51 locations: Locations,
52 span: Span,
53 category: ConstraintCategory<'tcx>,
54 constraints: &'a mut MirTypeckRegionConstraints<'tcx>,
55 ) -> Self {
56 Self {
57 infcx,
58 universal_regions,
59 region_bound_pairs,
60 known_type_outlives_obligations,
61 locations,
62 span,
63 category,
64 constraints,
65 from_closure: false,
66 }
67 }
68
69 #[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(69u32),
::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")]
70 pub(super) fn convert_all(&mut self, query_constraints: &QueryRegionConstraints<'tcx>) {
71 let QueryRegionConstraints { constraints, assumptions } = query_constraints;
72 let assumptions =
73 elaborate::elaborate_outlives_assumptions(self.infcx.tcx, assumptions.iter().copied());
74
75 for &QueryRegionConstraint { constraint, category, .. } in constraints {
76 constraint.iter_outlives().for_each(|predicate| {
77 self.convert(predicate, category, &assumptions);
78 });
79 }
80 }
81
82 #[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(85u32),
::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:101",
"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(101u32),
::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::OutlivesClause(subject, outlived_region),
self.category, &Default::default());
}
(self.category, self.span, self.from_closure) = backup;
}
}
}#[instrument(skip(self), level = "debug")]
86 pub(crate) fn apply_closure_requirements(
87 &mut self,
88 closure_requirements: &ClosureRegionRequirements<'tcx>,
89 closure_def_id: LocalDefId,
90 closure_args: ty::GenericArgsRef<'tcx>,
91 ) {
92 let closure_mapping = &UniversalRegions::closure_mapping(
96 self.infcx.tcx,
97 closure_args,
98 closure_requirements.num_external_vids,
99 closure_def_id,
100 );
101 debug!(?closure_mapping);
102
103 let backup = (self.category, self.span, self.from_closure);
105 self.from_closure = true;
106 for outlives_requirement in &closure_requirements.outlives_requirements {
107 let outlived_region = closure_mapping[outlives_requirement.outlived_free_region];
108 let subject = match outlives_requirement.subject {
109 ClosureOutlivesSubject::Region(re) => closure_mapping[re].into(),
110 ClosureOutlivesSubject::Ty(subject_ty) => {
111 subject_ty.instantiate(self.infcx.tcx, |vid| closure_mapping[vid]).into()
112 }
113 };
114
115 self.category = outlives_requirement.category;
116 self.span = outlives_requirement.blame_span;
117 self.convert(
118 ty::OutlivesClause(subject, outlived_region),
119 self.category,
120 &Default::default(),
121 );
122 }
123 (self.category, self.span, self.from_closure) = backup;
124 }
125
126 fn convert(
127 &mut self,
128 clause: ty::ArgOutlivesClause<'tcx>,
129 constraint_category: ConstraintCategory<'tcx>,
130 higher_ranked_assumptions: &FxHashSet<ty::ArgOutlivesClause<'tcx>>,
131 ) {
132 let tcx = self.infcx.tcx;
133 {
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:133",
"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(133u32),
::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);
134
135 let ConstraintConversion {
137 infcx: _,
138 universal_regions,
139 region_bound_pairs,
140 known_type_outlives_obligations,
141 ..
142 } = *self;
143
144 if self.infcx.tcx.sess.opts.unstable_opts.higher_ranked_assumptions
146 && higher_ranked_assumptions.contains(&clause)
147 {
148 return;
149 }
150
151 let ty::OutlivesClause(k1, r2) = clause;
152 match k1.kind() {
153 GenericArgKind::Lifetime(r1) => {
154 let r1_vid = self.to_region_vid(r1);
155 let r2_vid = self.to_region_vid(r2);
156 self.add_outlives(r1_vid, r2_vid, constraint_category);
157 }
158
159 GenericArgKind::Type(mut t1) => {
160 t1 = self.infcx.resolve_vars_if_possible(t1);
162
163 let implicit_region_bound =
164 ty::Region::new_var(tcx, universal_regions.implicit_region_bound());
165 let origin = SubregionOrigin::RelateParamBound(self.span, t1, None);
168 TypeOutlives::new(
169 &mut *self,
170 tcx,
171 region_bound_pairs,
172 Some(implicit_region_bound),
173 known_type_outlives_obligations,
174 )
175 .type_must_outlive(origin, t1, r2, constraint_category);
176 }
177
178 GenericArgKind::Const(_) => ::core::panicking::panic("internal error: entered unreachable code")unreachable!(),
179 }
180 }
181
182 fn replace_placeholders_with_nll<T: TypeFoldable<TyCtxt<'tcx>>>(&mut self, value: T) -> T {
189 if value.has_placeholders() {
190 fold_regions(self.infcx.tcx, value, |r, _| match r.kind() {
191 ty::RePlaceholder(placeholder) => {
192 self.constraints.placeholder_region(self.infcx, placeholder)
193 }
194 _ => r,
195 })
196 } else {
197 value
198 }
199 }
200
201 fn verify_to_type_test(
202 &mut self,
203 generic_kind: GenericKind<'tcx>,
204 region: ty::Region<'tcx>,
205 verify_bound: VerifyBound<'tcx>,
206 ) -> TypeTest<'tcx> {
207 let lower_bound = self.to_region_vid(region);
208 TypeTest { generic_kind, lower_bound, span: self.span, verify_bound }
209 }
210
211 fn to_region_vid(&mut self, r: ty::Region<'tcx>) -> ty::RegionVid {
212 if let ty::RePlaceholder(placeholder) = r.kind() {
213 self.constraints.placeholder_region(self.infcx, placeholder).as_var()
214 } else {
215 self.universal_regions.to_region_vid(r)
216 }
217 }
218
219 fn add_outlives(
220 &mut self,
221 sup: ty::RegionVid,
222 sub: ty::RegionVid,
223 category: ConstraintCategory<'tcx>,
224 ) {
225 let category = match self.category {
226 ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation => category,
227 _ => self.category,
228 };
229 self.constraints.outlives_constraints.push(OutlivesConstraint {
230 locations: self.locations,
231 category,
232 span: self.span,
233 sub,
234 sup,
235 variance_info: ty::VarianceDiagInfo::default(),
236 from_closure: self.from_closure,
237 });
238 }
239
240 fn add_type_test(&mut self, type_test: TypeTest<'tcx>) {
241 {
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:241",
"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(241u32),
::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);
242 self.constraints.type_tests.push(type_test);
243 }
244}
245
246impl<'a, 'b, 'tcx> TypeOutlivesDelegate<'tcx> for &'a mut ConstraintConversion<'b, 'tcx> {
247 fn push_sub_region_constraint(
248 &mut self,
249 _origin: SubregionOrigin<'tcx>,
250 a: ty::Region<'tcx>,
251 b: ty::Region<'tcx>,
252 constraint_category: ConstraintCategory<'tcx>,
253 ) {
254 let b = self.to_region_vid(b);
255 let a = self.to_region_vid(a);
256 self.add_outlives(b, a, constraint_category);
257 }
258
259 fn push_verify(
260 &mut self,
261 _origin: SubregionOrigin<'tcx>,
262 kind: GenericKind<'tcx>,
263 a: ty::Region<'tcx>,
264 bound: VerifyBound<'tcx>,
265 ) {
266 let kind = self.replace_placeholders_with_nll(kind);
267 let bound = self.replace_placeholders_with_nll(bound);
268 let type_test = self.verify_to_type_test(kind, a, bound);
269 self.add_type_test(type_test);
270 }
271}