1use rustc_data_structures::assert_matches;
2use rustc_middle::ty::outlives::{Component, compute_alias_components_recursive};
3use rustc_middle::ty::{self, OutlivesPredicate, Ty, TyCtxt};
4use smallvec::smallvec;
5use tracing::{debug, instrument, trace};
67use crate::infer::outlives::env::RegionBoundPairs;
8use crate::infer::region_constraints::VerifyIfEq;
9use crate::infer::{GenericKind, VerifyBound};
1011/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
12/// obligation into a series of `'a: 'b` constraints and "verifys", as
13/// described on the module comment. The final constraints are emitted
14/// via a "delegate" of type `D` -- this is usually the `infcx`, which
15/// accrues them into the `region_obligations` code, but for NLL we
16/// use something else.
17pub(crate) struct VerifyBoundCx<'cx, 'tcx> {
18 tcx: TyCtxt<'tcx>,
19 region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
20/// During borrowck, if there are no outlives bounds on a generic
21 /// parameter `T`, we assume that `T: 'in_fn_body` holds.
22 ///
23 /// Outside of borrowck the only way to prove `T: '?0` is by
24 /// setting `'?0` to `'empty`.
25implicit_region_bound: Option<ty::Region<'tcx>>,
26 caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>],
27}
2829impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
30pub(crate) fn new(
31 tcx: TyCtxt<'tcx>,
32 region_bound_pairs: &'cx RegionBoundPairs<'tcx>,
33 implicit_region_bound: Option<ty::Region<'tcx>>,
34 caller_bounds: &'cx [ty::PolyTypeOutlivesPredicate<'tcx>],
35 ) -> Self {
36Self { tcx, region_bound_pairs, implicit_region_bound, caller_bounds }
37 }
3839#[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("param_or_placeholder_bound",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(39u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::tracing_core::field::FieldSet::new(&["ty"],
::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(&ty)
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: VerifyBound<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let declared_bounds_from_env =
self.declared_generic_bounds_from_env(ty);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/outlives/verify.rs:45",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(45u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::tracing_core::field::FieldSet::new(&["declared_bounds_from_env"],
::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(&declared_bounds_from_env)
as &dyn Value))])
});
} else { ; }
};
let mut param_bounds = ::alloc::vec::Vec::new();
for declared_bound in declared_bounds_from_env {
let bound_region =
declared_bound.map_bound(|outlives| outlives.1);
if let Some(region) = bound_region.no_bound_vars() {
param_bounds.push(VerifyBound::OutlivedBy(region));
} else {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/outlives/verify.rs:54",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(54u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::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!("found that {0:?} outlives any lifetime, returning empty vector",
ty) as &dyn Value))])
});
} else { ; }
};
return VerifyBound::AllBounds(::alloc::vec::Vec::new());
}
}
if let Some(r) = self.implicit_region_bound {
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/outlives/verify.rs:62",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(62u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::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!("adding implicit region bound of {0:?}",
r) as &dyn Value))])
});
} else { ; }
};
param_bounds.push(VerifyBound::OutlivedBy(r));
}
if param_bounds.is_empty() {
VerifyBound::IsEmpty
} else if param_bounds.len() == 1 {
param_bounds.pop().unwrap()
} else { VerifyBound::AnyBound(param_bounds) }
}
}
}#[instrument(level = "debug", skip(self))]40pub(crate) fn param_or_placeholder_bound(&self, ty: Ty<'tcx>) -> VerifyBound<'tcx> {
41// Start with anything like `T: 'a` we can scrape from the
42 // environment. If the environment contains something like
43 // `for<'a> T: 'a`, then we know that `T` outlives everything.
44let declared_bounds_from_env = self.declared_generic_bounds_from_env(ty);
45debug!(?declared_bounds_from_env);
46let mut param_bounds = vec![];
47for declared_bound in declared_bounds_from_env {
48let bound_region = declared_bound.map_bound(|outlives| outlives.1);
49if let Some(region) = bound_region.no_bound_vars() {
50// This is `T: 'a` for some free region `'a`.
51param_bounds.push(VerifyBound::OutlivedBy(region));
52 } else {
53// This is `for<'a> T: 'a`. This means that `T` outlives everything! All done here.
54debug!("found that {ty:?} outlives any lifetime, returning empty vector");
55return VerifyBound::AllBounds(vec![]);
56 }
57 }
5859// Add in the default bound of fn body that applies to all in
60 // scope type parameters:
61if let Some(r) = self.implicit_region_bound {
62debug!("adding implicit region bound of {r:?}");
63 param_bounds.push(VerifyBound::OutlivedBy(r));
64 }
6566if param_bounds.is_empty() {
67// We know that all types `T` outlive `'empty`, so if we
68 // can find no other bound, then check that the region
69 // being tested is `'empty`.
70VerifyBound::IsEmpty
71 } else if param_bounds.len() == 1 {
72// Micro-opt: no need to store the vector if it's just len 1
73param_bounds.pop().unwrap()
74 } else {
75// If we can find any other bound `R` such that `T: R`, then
76 // we don't need to check for `'empty`, because `R: 'empty`.
77VerifyBound::AnyBound(param_bounds)
78 }
79 }
8081/// Given a projection like `T::Item`, searches the environment
82 /// for where-clauses like `T::Item: 'a`. Returns the set of
83 /// regions `'a` that it finds.
84 ///
85 /// This is an "approximate" check -- it may not find all
86 /// applicable bounds, and not all the bounds it returns can be
87 /// relied upon. In particular, this check ignores region
88 /// identity. So, for example, if we have `<T as
89 /// Trait<'0>>::Item` where `'0` is a region variable, and the
90 /// user has `<T as Trait<'a>>::Item: 'b` in the environment, then
91 /// the clause from the environment only applies if `'0 = 'a`,
92 /// which we don't know yet. But we would still include `'b` in
93 /// this list.
94pub(crate) fn approx_declared_bounds_from_env(
95&self,
96 alias_ty: ty::AliasTy<'tcx>,
97 ) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
98let erased_alias_ty = self.tcx.erase_and_anonymize_regions(alias_ty.to_ty(self.tcx));
99self.declared_generic_bounds_from_env_for_erased_ty(erased_alias_ty)
100 }
101102#[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("alias_bound",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(102u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::tracing_core::field::FieldSet::new(&["alias_ty"],
::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(&alias_ty)
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: VerifyBound<'tcx> = loop {};
return __tracing_attr_fake_return;
}
{
let env_bounds =
self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder|
{
if let Some(ty::OutlivesPredicate(ty, r)) =
binder.no_bound_vars() &&
let ty::Alias(_, alias_ty_from_bound) = *ty.kind() &&
alias_ty_from_bound == alias_ty {
VerifyBound::OutlivedBy(r)
} else {
let verify_if_eq_b =
binder.map_bound(|ty::OutlivesPredicate(ty, bound)|
VerifyIfEq { ty, bound });
VerifyBound::IfEq(verify_if_eq_b)
}
});
let definition_bounds =
self.declared_bounds_from_definition(alias_ty).map(|r|
VerifyBound::OutlivedBy(r));
let recursive_bound =
{
let mut components = ::smallvec::SmallVec::new();
let kind = alias_ty.kind(self.tcx);
compute_alias_components_recursive(self.tcx, kind, alias_ty,
&mut components);
self.bound_from_components(&components)
};
VerifyBound::AnyBound(env_bounds.chain(definition_bounds).collect()).or(recursive_bound)
}
}
}#[instrument(level = "debug", skip(self))]103pub(crate) fn alias_bound(&self, alias_ty: ty::AliasTy<'tcx>) -> VerifyBound<'tcx> {
104// Search the env for where clauses like `P: 'a`.
105let env_bounds = self.approx_declared_bounds_from_env(alias_ty).into_iter().map(|binder| {
106if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars()
107 && let ty::Alias(_, alias_ty_from_bound) = *ty.kind()
108 && alias_ty_from_bound == alias_ty
109 {
110// Micro-optimize if this is an exact match (this
111 // occurs often when there are no region variables
112 // involved).
113VerifyBound::OutlivedBy(r)
114 } else {
115let verify_if_eq_b =
116 binder.map_bound(|ty::OutlivesPredicate(ty, bound)| VerifyIfEq { ty, bound });
117 VerifyBound::IfEq(verify_if_eq_b)
118 }
119 });
120121// Extend with bounds that we can find from the definition.
122let definition_bounds =
123self.declared_bounds_from_definition(alias_ty).map(|r| VerifyBound::OutlivedBy(r));
124125// see the extensive comment in projection_must_outlive
126let recursive_bound = {
127let mut components = smallvec![];
128let kind = alias_ty.kind(self.tcx);
129 compute_alias_components_recursive(self.tcx, kind, alias_ty, &mut components);
130self.bound_from_components(&components)
131 };
132133 VerifyBound::AnyBound(env_bounds.chain(definition_bounds).collect()).or(recursive_bound)
134 }
135136fn bound_from_components(&self, components: &[Component<TyCtxt<'tcx>>]) -> VerifyBound<'tcx> {
137let mut bounds = components138 .iter()
139 .map(|component| self.bound_from_single_component(component))
140// Remove bounds that must hold, since they are not interesting.
141.filter(|bound| !bound.must_hold());
142143match (bounds.next(), bounds.next()) {
144 (Some(first), None) => first,
145 (first, second) => {
146 VerifyBound::AllBounds(first.into_iter().chain(second).chain(bounds).collect())
147 }
148 }
149 }
150151fn bound_from_single_component(
152&self,
153 component: &Component<TyCtxt<'tcx>>,
154 ) -> VerifyBound<'tcx> {
155match *component {
156 Component::Region(lt) => VerifyBound::OutlivedBy(lt),
157 Component::Param(param_ty) => self.param_or_placeholder_bound(param_ty.to_ty(self.tcx)),
158 Component::Placeholder(placeholder_ty) => {
159self.param_or_placeholder_bound(Ty::new_placeholder(self.tcx, placeholder_ty))
160 }
161 Component::Alias(alias_ty) => self.alias_bound(alias_ty),
162 Component::EscapingAlias(ref components) => self.bound_from_components(components),
163 Component::UnresolvedInferenceVariable(v) => {
164// Ignore this, we presume it will yield an error later, since
165 // if a type variable is not resolved by this point it never
166 // will be.
167self.tcx
168 .dcx()
169 .delayed_bug(::alloc::__export::must_use({
::alloc::fmt::format(format_args!("unresolved inference variable in outlives: {0:?}",
v))
})format!("unresolved inference variable in outlives: {v:?}"));
170// Add a bound that never holds.
171 VerifyBound::AnyBound(::alloc::vec::Vec::new()vec![])
172 }
173 }
174 }
175176/// Searches the environment for where-clauses like `G: 'a` where
177 /// `G` is either some type parameter `T` or a projection like
178 /// `T::Item`. Returns a vector of the `'a` bounds it can find.
179 ///
180 /// This is a conservative check -- it may not find all applicable
181 /// bounds, but all the bounds it returns can be relied upon.
182fn declared_generic_bounds_from_env(
183&self,
184 generic_ty: Ty<'tcx>,
185 ) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
186match generic_ty.kind() {
ty::Param(_) | ty::Placeholder(_) => {}
ref left_val => {
::core::panicking::assert_matches_failed(left_val,
"ty::Param(_) | ty::Placeholder(_)",
::core::option::Option::None);
}
};assert_matches!(generic_ty.kind(), ty::Param(_) | ty::Placeholder(_));
187self.declared_generic_bounds_from_env_for_erased_ty(generic_ty)
188 }
189190/// Searches the environment to find all bounds that apply to `erased_ty`.
191 /// Obviously these must be approximate -- they are in fact both *over* and
192 /// and *under* approximated:
193 ///
194 /// * Over-approximated because we don't consider equality of regions.
195 /// * Under-approximated because we look for syntactic equality and so for complex types
196 /// like `<T as Foo<fn(&u32, &u32)>>::Item` or whatever we may fail to figure out
197 /// all the subtleties.
198 ///
199 /// In some cases, such as when `erased_ty` represents a `ty::Param`, however,
200 /// the result is precise.
201#[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("declared_generic_bounds_from_env_for_erased_ty",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(201u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::tracing_core::field::FieldSet::new(&["erased_ty"],
::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(&erased_ty)
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:
Vec<ty::PolyTypeOutlivesPredicate<'tcx>> = loop {};
return __tracing_attr_fake_return;
}
{
let tcx = self.tcx;
let mut bounds = ::alloc::vec::Vec::new();
bounds.extend(self.caller_bounds.iter().copied().filter(move
|outlives_predicate|
{
super::test_type_match::can_match_erased_ty(tcx,
*outlives_predicate, erased_ty)
}));
bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p,
r)|
{
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/outlives/verify.rs:228",
"rustc_infer::infer::outlives::verify",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(228u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::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!("declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {0:?}",
(r, p)) as &dyn Value))])
});
} else { ; }
};
match (&p, erased_ty.kind()) {
(GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
(GenericKind::Placeholder(p1), ty::Placeholder(p2)) if
p1 == p2 => {}
(GenericKind::Alias(a1), ty::Alias(_, a2)) if
a1.def_id == a2.def_id => {}
_ => return None,
}
let p_ty = p.to_ty(tcx);
let erased_p_ty =
self.tcx.erase_and_anonymize_regions(p_ty);
(erased_p_ty ==
erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty,
r)))
}));
bounds
}
}
}#[instrument(level = "debug", skip(self))]202fn declared_generic_bounds_from_env_for_erased_ty(
203&self,
204 erased_ty: Ty<'tcx>,
205 ) -> Vec<ty::PolyTypeOutlivesPredicate<'tcx>> {
206let tcx = self.tcx;
207let mut bounds = vec![];
208209// To start, collect bounds from user environment. Note that
210 // parameter environments are already elaborated, so we don't
211 // have to worry about that.
212bounds.extend(self.caller_bounds.iter().copied().filter(move |outlives_predicate| {
213super::test_type_match::can_match_erased_ty(tcx, *outlives_predicate, erased_ty)
214 }));
215216// Next, collect regions we scraped from the well-formedness
217 // constraints in the fn signature. To do that, we walk the list
218 // of known relations from the fn ctxt.
219 //
220 // This is crucial because otherwise code like this fails:
221 //
222 // fn foo<'a, A>(x: &'a A) { x.bar() }
223 //
224 // The problem is that the type of `x` is `&'a A`. To be
225 // well-formed, then, A must outlive `'a`, but we don't know that
226 // this holds from first principles.
227bounds.extend(self.region_bound_pairs.iter().filter_map(|&OutlivesPredicate(p, r)| {
228debug!(
229"declared_generic_bounds_from_env_for_erased_ty: region_bound_pair = {:?}",
230 (r, p)
231 );
232// Fast path for the common case.
233match (&p, erased_ty.kind()) {
234// In outlive routines, all types are expected to be fully normalized.
235 // And therefore we can safely use structural equality for alias types.
236(GenericKind::Param(p1), ty::Param(p2)) if p1 == p2 => {}
237 (GenericKind::Placeholder(p1), ty::Placeholder(p2)) if p1 == p2 => {}
238 (GenericKind::Alias(a1), ty::Alias(_, a2)) if a1.def_id == a2.def_id => {}
239_ => return None,
240 }
241242let p_ty = p.to_ty(tcx);
243let erased_p_ty = self.tcx.erase_and_anonymize_regions(p_ty);
244 (erased_p_ty == erased_ty).then_some(ty::Binder::dummy(ty::OutlivesPredicate(p_ty, r)))
245 }));
246247 bounds
248 }
249250/// Given a projection like `<T as Foo<'x>>::Bar`, returns any bounds
251 /// declared in the trait definition. For example, if the trait were
252 ///
253 /// ```rust
254 /// trait Foo<'a> {
255 /// type Bar: 'a;
256 /// }
257 /// ```
258 ///
259 /// If we were given the `DefId` of `Foo::Bar`, we would return
260 /// `'a`. You could then apply the instantiations from the
261 /// projection to convert this into your namespace. This also
262 /// works if the user writes `where <Self as Foo<'a>>::Bar: 'a` on
263 /// the trait. In fact, it works by searching for just such a
264 /// where-clause.
265 ///
266 /// It will not, however, work for higher-ranked bounds like:
267 ///
268 /// ```ignore(this does compile today, previously was marked as `compile_fail,E0311`)
269 /// trait Foo<'a, 'b>
270 /// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
271 /// {
272 /// type Bar;
273 /// }
274 /// ```
275 ///
276 /// This is for simplicity, and because we are not really smart
277 /// enough to cope with such bounds anywhere.
278pub(crate) fn declared_bounds_from_definition(
279&self,
280 alias_ty: ty::AliasTy<'tcx>,
281 ) -> impl Iterator<Item = ty::Region<'tcx>> {
282let tcx = self.tcx;
283let bounds = tcx.item_self_bounds(alias_ty.def_id);
284{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_infer/src/infer/outlives/verify.rs:284",
"rustc_infer::infer::outlives::verify",
::tracing::Level::TRACE,
::tracing_core::__macro_support::Option::Some("compiler/rustc_infer/src/infer/outlives/verify.rs"),
::tracing_core::__macro_support::Option::Some(284u32),
::tracing_core::__macro_support::Option::Some("rustc_infer::infer::outlives::verify"),
::tracing_core::field::FieldSet::new(&["message"],
::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::TRACE <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::TRACE <=
::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!("{0:#?}",
bounds.skip_binder()) as &dyn Value))])
});
} else { ; }
};trace!("{:#?}", bounds.skip_binder());
285bounds286 .iter_instantiated(tcx, alias_ty.args)
287 .filter_map(|p| p.as_type_outlives_clause())
288 .filter_map(|p| p.no_bound_vars())
289 .map(|OutlivesPredicate(_, r)| r)
290 }
291}