1//! Core logic responsible for determining what it means for various type system
2//! primitives to be "well formed". Actually checking whether these primitives are
3//! well formed is performed elsewhere (e.g. during type checking or item well formedness
4//! checking).
56use std::iter;
78use rustc_hiras hir;
9use rustc_hir::attrs::lang_items::LangItem;
10use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, PredicateObligations};
11use rustc_middle::bug;
12use rustc_middle::ty::{
13self, DelayedSet, GenericArgsRef, Term, TermKind, Ty, TyCtxt, TypeSuperVisitable,
14TypeVisitable, TypeVisitableExt, TypeVisitor,
15};
16use rustc_session::diagnostics::feature_err;
17use rustc_span::def_id::{DefId, LocalDefId};
18use rustc_span::{Span, sym};
19use tracing::{debug, instrument};
2021use crate::infer::InferCtxt;
22use crate::traits;
2324/// Returns the set of obligations needed to make `term` well-formed.
25/// If `term` contains unresolved inference variables, this may include
26/// further WF obligations. However, if `term` IS an unresolved
27/// inference variable, returns `None`, because we are not able to
28/// make any progress at all. This is to prevent cycles where we
29/// say "?0 is WF if ?0 is WF".
30pub fn obligations<'tcx>(
31 infcx: &InferCtxt<'tcx>,
32 param_env: ty::ParamEnv<'tcx>,
33 body_def_id: LocalDefId,
34 recursion_depth: usize,
35 term: Term<'tcx>,
36 span: Span,
37) -> Option<PredicateObligations<'tcx>> {
38// Handle the "cycle" case (see comment above) by bailing out if necessary.
39let term = match term.kind() {
40TermKind::Ty(ty) => {
41match ty.kind() {
42 ty::Infer(ty::TyVar(_)) => {
43let resolved_ty = infcx.shallow_resolve(ty);
44if resolved_ty == ty {
45// No progress, bail out to prevent cycles.
46return None;
47 } else {
48resolved_ty49 }
50 }
51_ => ty,
52 }
53 .into()
54 }
55TermKind::Const(ct) => {
56match ct.kind() {
57 ty::ConstKind::Infer(_) => {
58let resolved = infcx.shallow_resolve_const(ct);
59if resolved == ct {
60// No progress, bail out to prevent cycles.
61return None;
62 } else {
63resolved64 }
65 }
66_ => ct,
67 }
68 .into()
69 }
70 };
7172let mut wf = WfPredicates {
73infcx,
74param_env,
75body_def_id,
76span,
77 out: PredicateObligations::new(),
78recursion_depth,
79 item: None,
80 visited_tys: Default::default(),
81 };
82wf.add_wf_preds_for_term(term);
83{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:83",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(83u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::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!("wf::obligations({0:?}, body_def_id={1:?}) = {2:?}",
term, body_def_id, wf.out) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("wf::obligations({:?}, body_def_id={:?}) = {:?}", term, body_def_id, wf.out);
8485let result = wf.normalize(infcx);
86{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:86",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(86u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::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!("wf::obligations({0:?}, body_def_id={1:?}) ~~> {2:?}",
term, body_def_id, result) as
&dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("wf::obligations({:?}, body_def_id={:?}) ~~> {:?}", term, body_def_id, result);
87Some(result)
88}
8990/// Compute the predicates that are required for a type to be well-formed.
91///
92/// This is only intended to be used in the new solver, since it does not
93/// take into account recursion depth or proper error-reporting spans.
94pub fn unnormalized_obligations<'tcx>(
95 infcx: &InferCtxt<'tcx>,
96 param_env: ty::ParamEnv<'tcx>,
97 term: Term<'tcx>,
98 span: Span,
99 body_def_id: LocalDefId,
100) -> Option<PredicateObligations<'tcx>> {
101if true {
{
match (&term, &infcx.resolve_vars_if_possible(term)) {
(left_val, right_val) => {
if !(*left_val == *right_val) {
let kind = ::core::panicking::AssertKind::Eq;
::core::panicking::assert_failed(kind, &*left_val,
&*right_val, ::core::option::Option::None);
}
}
}
};
};debug_assert_eq!(term, infcx.resolve_vars_if_possible(term));
102103// However, if `term` IS an unresolved inference variable, returns `None`,
104 // because we are not able to make any progress at all. This is to prevent
105 // cycles where we say "?0 is WF if ?0 is WF".
106if term.is_infer() {
107return None;
108 }
109110let mut wf = WfPredicates {
111infcx,
112param_env,
113body_def_id,
114span,
115 out: PredicateObligations::new(),
116 recursion_depth: 0,
117 item: None,
118 visited_tys: Default::default(),
119 };
120wf.add_wf_preds_for_term(term);
121Some(wf.out)
122}
123124/// Returns the obligations that make this trait reference
125/// well-formed. For example, if there is a trait `Set` defined like
126/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
127/// if `Bar: Eq`.
128pub fn trait_obligations<'tcx>(
129 infcx: &InferCtxt<'tcx>,
130 param_env: ty::ParamEnv<'tcx>,
131 body_def_id: LocalDefId,
132 trait_pred: ty::TraitClause<'tcx>,
133 span: Span,
134 item: &'tcx hir::Item<'tcx>,
135) -> PredicateObligations<'tcx> {
136let mut wf = WfPredicates {
137infcx,
138param_env,
139body_def_id,
140span,
141 out: PredicateObligations::new(),
142 recursion_depth: 0,
143 item: Some(item),
144 visited_tys: Default::default(),
145 };
146wf.add_wf_preds_for_trait_pred(trait_pred, Elaborate::All);
147{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:147",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(147u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("obligations")
}> =
::tracing::__macro_support::FieldName::new("obligations");
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(&wf.out)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(obligations = ?wf.out);
148wf.normalize(infcx)
149}
150151/// Returns the requirements for `clause` to be well-formed.
152///
153/// For example, if there is a trait `Set` defined like
154/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
155/// if `Bar: Eq`.
156{}
let __tracing_attr_span;
let __tracing_attr_guard;
if ::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::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("clause_obligations",
"rustc_trait_selection::traits::wf", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(156u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("param_env")
}> =
::tracing::__macro_support::FieldName::new("param_env");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("body_def_id")
}> =
::tracing::__macro_support::FieldName::new("body_def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("clause")
}> =
::tracing::__macro_support::FieldName::new("clause");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("span")
}> =
::tracing::__macro_support::FieldName::new("span");
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::INFO <=
::tracing::level_filters::STATIC_MAX_LEVEL &&
::tracing::Level::INFO <=
::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(¶m_env)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&body_def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&clause)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&span)
as &dyn ::tracing::field::Value))])
})
} else {
let span =
::tracing::__macro_support::__disabled_span(__CALLSITE.metadata());
{};
span
}
};
__tracing_attr_guard = __tracing_attr_span.enter();
}
#[allow(clippy :: redundant_closure_call)]
let x =
(move ||
{
#[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: PredicateObligations<'tcx> =
loop {};
return __tracing_attr_fake_return;
}
{
let mut wf =
WfPredicates {
infcx,
param_env,
body_def_id,
span,
out: PredicateObligations::new(),
recursion_depth: 0,
item: None,
visited_tys: Default::default(),
};
match clause.kind().skip_binder() {
ty::ClauseKind::Trait(t) => {
wf.add_wf_preds_for_trait_pred(t, Elaborate::None);
}
ty::ClauseKind::HostEffect(..) => {}
ty::ClauseKind::RegionOutlives(..) => {}
ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ty, _reg))
=> {
wf.add_wf_preds_for_term(ty.into());
}
ty::ClauseKind::Projection(t) => {
wf.add_wf_preds_for_projection_term(t.projection_term);
wf.add_wf_preds_for_term(t.term);
}
ty::ClauseKind::ConstArgHasType(ct, ty) => {
wf.add_wf_preds_for_term(ct.into());
wf.add_wf_preds_for_term(ty.into());
}
ty::ClauseKind::WellFormed(term) => {
wf.add_wf_preds_for_term(term);
}
ty::ClauseKind::ConstEvaluatable(ct) => {
wf.add_wf_preds_for_term(ct.into());
}
ty::ClauseKind::UnstableFeature(_) => {}
}
wf.normalize(infcx)
}
})();
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:156",
"rustc_trait_selection::traits::wf", ::tracing::Level::INFO,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(156u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("return")
}> =
::tracing::__macro_support::FieldName::new("return");
NAME.as_str()
}], ::tracing_core::callsite::Identifier(&__CALLSITE)),
::tracing::metadata::Kind::EVENT)
};
::tracing::callsite::DefaultCallsite::new(&META)
};
let enabled =
::tracing::Level::INFO <= ::tracing::level_filters::STATIC_MAX_LEVEL
&&
::tracing::Level::INFO <=
::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(&x)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
x;#[instrument(skip(infcx), ret)]157pub fn clause_obligations<'tcx>(
158 infcx: &InferCtxt<'tcx>,
159 param_env: ty::ParamEnv<'tcx>,
160 body_def_id: LocalDefId,
161 clause: ty::Clause<'tcx>,
162 span: Span,
163) -> PredicateObligations<'tcx> {
164let mut wf = WfPredicates {
165 infcx,
166 param_env,
167 body_def_id,
168 span,
169 out: PredicateObligations::new(),
170 recursion_depth: 0,
171 item: None,
172 visited_tys: Default::default(),
173 };
174175// It's ok to skip the binder here because wf code is prepared for it
176match clause.kind().skip_binder() {
177 ty::ClauseKind::Trait(t) => {
178 wf.add_wf_preds_for_trait_pred(t, Elaborate::None);
179 }
180 ty::ClauseKind::HostEffect(..) => {
181// Technically the well-formedness of this clause is implied by
182 // the corresponding trait clause it should've been generated beside.
183}
184 ty::ClauseKind::RegionOutlives(..) => {}
185 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ty, _reg)) => {
186 wf.add_wf_preds_for_term(ty.into());
187 }
188 ty::ClauseKind::Projection(t) => {
189 wf.add_wf_preds_for_projection_term(t.projection_term);
190 wf.add_wf_preds_for_term(t.term);
191 }
192 ty::ClauseKind::ConstArgHasType(ct, ty) => {
193 wf.add_wf_preds_for_term(ct.into());
194 wf.add_wf_preds_for_term(ty.into());
195 }
196 ty::ClauseKind::WellFormed(term) => {
197 wf.add_wf_preds_for_term(term);
198 }
199200 ty::ClauseKind::ConstEvaluatable(ct) => {
201 wf.add_wf_preds_for_term(ct.into());
202 }
203 ty::ClauseKind::UnstableFeature(_) => {}
204 }
205206 wf.normalize(infcx)
207}
208209struct WfPredicates<'a, 'tcx> {
210 infcx: &'a InferCtxt<'tcx>,
211 param_env: ty::ParamEnv<'tcx>,
212 body_def_id: LocalDefId,
213 span: Span,
214 out: PredicateObligations<'tcx>,
215 recursion_depth: usize,
216 item: Option<&'tcx hir::Item<'tcx>>,
217 visited_tys: DelayedSet<Ty<'tcx>>,
218}
219220/// Controls whether we "elaborate" supertraits and so forth on the WF
221/// predicates. This is a kind of hack to address #43784. The
222/// underlying problem in that issue was a trait structure like:
223///
224/// ```ignore (illustrative)
225/// trait Foo: Copy { }
226/// trait Bar: Foo { }
227/// impl<T: Bar> Foo for T { }
228/// impl<T> Bar for T { }
229/// ```
230///
231/// Here, in the `Foo` impl, we will check that `T: Copy` holds -- but
232/// we decide that this is true because `T: Bar` is in the
233/// where-clauses (and we can elaborate that to include `T:
234/// Copy`). This wouldn't be a problem, except that when we check the
235/// `Bar` impl, we decide that `T: Foo` must hold because of the `Foo`
236/// impl. And so nowhere did we check that `T: Copy` holds!
237///
238/// To resolve this, we elaborate the WF requirements that must be
239/// proven when checking impls. This means that (e.g.) the `impl Bar
240/// for T` will be forced to prove not only that `T: Foo` but also `T:
241/// Copy` (which it won't be able to do, because there is no `Copy`
242/// impl for `T`).
243#[derive(#[automatically_derived]
impl ::core::fmt::Debug for Elaborate {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::write_str(f,
match self {
Elaborate::All => "All",
Elaborate::None => "None",
})
}
}Debug, #[automatically_derived]
impl ::core::marker::StructuralPartialEq for Elaborate { }
#[automatically_derived]
impl ::core::cmp::PartialEq for Elaborate {
#[inline]
fn eq(&self, other: &Elaborate) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr
}
}PartialEq, #[automatically_derived]
impl ::core::cmp::Eq for Elaborate {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::marker::Copy for Elaborate { }Copy, #[automatically_derived]
#[doc(hidden)]
unsafe impl ::core::clone::TrivialClone for Elaborate { }
#[automatically_derived]
impl ::core::clone::Clone for Elaborate {
#[inline]
fn clone(&self) -> Elaborate { *self }
}Clone)]
244enum Elaborate {
245 All,
246None,
247}
248249/// Points the cause span of a super predicate at the relevant associated type.
250///
251/// Given a trait impl item:
252///
253/// ```ignore (incomplete)
254/// impl TargetTrait for TargetType {
255/// type Assoc = SomeType;
256/// }
257/// ```
258///
259/// And a super predicate of `TargetTrait` that has any of the following forms:
260///
261/// 1. `<OtherType as OtherTrait>::Assoc == <TargetType as TargetTrait>::Assoc`
262/// 2. `<<TargetType as TargetTrait>::Assoc as OtherTrait>::Assoc == OtherType`
263/// 3. `<TargetType as TargetTrait>::Assoc: OtherTrait`
264///
265/// Replace the span of the cause with the span of the associated item:
266///
267/// ```ignore (incomplete)
268/// impl TargetTrait for TargetType {
269/// type Assoc = SomeType;
270/// // ^^^^^^^^ this span
271/// }
272/// ```
273///
274/// Note that bounds that can be expressed as associated item bounds are **not**
275/// super predicates. This means that form 2 and 3 from above are only relevant if
276/// the [`GenericArgsRef`] of the projection type are not its identity arguments.
277fn extend_cause_with_original_assoc_item_obligation<'tcx>(
278 tcx: TyCtxt<'tcx>,
279 item: Option<&hir::Item<'tcx>>,
280 cause: &mut traits::ObligationCause<'tcx>,
281 pred: ty::Predicate<'tcx>,
282) {
283{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:283",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(283u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&["message",
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("item")
}> =
::tracing::__macro_support::FieldName::new("item");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("cause")
}> =
::tracing::__macro_support::FieldName::new("cause");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("pred")
}> =
::tracing::__macro_support::FieldName::new("pred");
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!("extended_cause_with_original_assoc_item_obligation")
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&item)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&cause)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&pred)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?item, ?cause, ?pred, "extended_cause_with_original_assoc_item_obligation");
284let (items, impl_def_id) = match item {
285Some(hir::Item { kind: hir::ItemKind::Impl(impl_), owner_id, .. }) => {
286 (impl_.items, *owner_id)
287 }
288_ => return,
289 };
290291let ty_to_impl_span = |ty: Ty<'_>| {
292if let ty::Alias(_, ty::AliasTy { kind: ty::Projection { def_id }, .. }) = ty.kind()
293 && let Some(&impl_item_id) = tcx.impl_item_implementor_ids(impl_def_id).get(def_id)
294 && let Some(impl_item) =
295items.iter().find(|item| item.owner_id.to_def_id() == impl_item_id)
296 {
297Some(tcx.hir_impl_item(*impl_item).expect_type().span)
298 } else {
299None300 }
301 };
302303// It is fine to skip the binder as we don't care about regions here.
304match pred.kind().skip_binder() {
305 ty::PredicateKind::Clause(ty::ClauseKind::Projection(proj)) => {
306// Form 1: The obligation comes not from the current `impl` nor the `trait` being
307 // implemented, but rather from a "second order" obligation, where an associated
308 // type has a projection coming from another associated type.
309 // See `tests/ui/traits/assoc-type-in-superbad.rs` for an example.
310if let Some(term_ty) = proj.term.as_type()
311 && let Some(impl_item_span) = ty_to_impl_span(term_ty)
312 {
313cause.span = impl_item_span;
314 }
315316// Form 2: A projection obligation for an associated item failed to be met.
317 // We overwrite the span from above to ensure that a bound like
318 // `Self::Assoc1: Trait<OtherAssoc = Self::Assoc2>` gets the same
319 // span for both obligations that it is lowered to.
320if let Some(impl_item_span) = ty_to_impl_span(proj.self_ty()) {
321cause.span = impl_item_span;
322 }
323 }
324325 ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => {
326// Form 3: A trait obligation for an associated item failed to be met.
327{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:327",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(327u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::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!("extended_cause_with_original_assoc_item_obligation trait proj {0:?}",
pred) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("extended_cause_with_original_assoc_item_obligation trait proj {:?}", pred);
328if let Some(impl_item_span) = ty_to_impl_span(pred.self_ty()) {
329cause.span = impl_item_span;
330 }
331 }
332_ => {}
333 }
334}
335336impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
337fn tcx(&self) -> TyCtxt<'tcx> {
338self.infcx.tcx
339 }
340341fn cause(&self, code: traits::ObligationCauseCode<'tcx>) -> traits::ObligationCause<'tcx> {
342 traits::ObligationCause::new(self.span, self.body_def_id, code)
343 }
344345fn normalize(self, infcx: &InferCtxt<'tcx>) -> PredicateObligations<'tcx> {
346// Do not normalize `wf` obligations with the new solver.
347 //
348 // The current deep normalization routine with the new solver does not
349 // handle ambiguity and the new solver correctly deals with unnnormalized goals.
350 // If the user relies on normalized types, e.g. for `fn implied_outlives_bounds`,
351 // it is their responsibility to normalize while avoiding ambiguity.
352if infcx.next_trait_solver() {
353return self.out;
354 }
355356let cause = self.cause(ObligationCauseCode::WellFormed(None));
357let param_env = self.param_env;
358let mut obligations = PredicateObligations::with_capacity(self.out.len());
359for mut obligation in self.out {
360if !!obligation.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !obligation.has_escaping_bound_vars()")
};assert!(!obligation.has_escaping_bound_vars());
361let mut selcx = traits::SelectionContext::new(infcx);
362// Don't normalize the whole obligation, the param env is either
363 // already normalized, or we're currently normalizing the
364 // param_env. Either way we should only normalize the predicate.
365let normalized_predicate = traits::normalize::normalize_with_depth_to(
366&mut selcx,
367 param_env,
368 cause.clone(),
369self.recursion_depth,
370 ty::Unnormalized::new_wip(obligation.predicate),
371&mut obligations,
372 );
373 obligation.predicate = normalized_predicate;
374 obligations.push(obligation);
375 }
376obligations377 }
378379/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
380fn add_wf_preds_for_trait_pred(
381&mut self,
382 trait_pred: ty::TraitClause<'tcx>,
383 elaborate: Elaborate,
384 ) {
385let tcx = self.tcx();
386let trait_ref = trait_pred.trait_ref;
387388// Negative trait predicates don't require supertraits to hold, just
389 // that their args are WF.
390if trait_pred.polarity == ty::ClausePolarity::Negative {
391self.add_wf_preds_for_negative_trait_pred(trait_ref);
392return;
393 }
394395let param_env = self.param_env;
396let depth = self.recursion_depth;
397398let item = self.item;
399400let extend = |traits::PredicateObligation { predicate, mut cause, .. }| {
401if let Some(parent_trait_pred) = predicate.as_trait_clause() {
402cause = cause.derived_cause(
403parent_trait_pred,
404 traits::ObligationCauseCode::WellFormedDerived,
405 );
406 }
407extend_cause_with_original_assoc_item_obligation(tcx, item, &mut cause, predicate);
408 traits::Obligation::with_depth(tcx, cause, depth, param_env, predicate)
409 };
410411// if the trait predicate is not const, the wf obligations should not be const as well.
412if let Elaborate::All = elaborate {
413let mut obligations = PredicateObligations::new();
414self.nominal_obligations(trait_ref.def_id, trait_ref.args, |_, obligation| {
415obligations.push(obligation)
416 });
417{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:417",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(417u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::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!("compute_trait_pred obligations {0:?}",
obligations) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("compute_trait_pred obligations {:?}", obligations);
418let implied_obligations = traits::util::elaborate(tcx, obligations);
419let implied_obligations = implied_obligations.map(extend);
420self.out.extend(implied_obligations);
421 } else {
422self.nominal_obligations(trait_ref.def_id, trait_ref.args, |this, obligation| {
423this.out.push(obligation)
424 });
425 }
426427self.out.extend(
428trait_ref429 .args
430 .iter()
431 .enumerate()
432 .filter_map(|(i, arg)| arg.as_term().map(|t| (i, t)))
433 .filter(|(_, term)| !term.has_escaping_bound_vars())
434 .map(|(i, term)| {
435let mut cause = traits::ObligationCause::misc(self.span, self.body_def_id);
436// The first arg is the self ty - use the correct span for it.
437if i == 0 {
438if let Some(hir::ItemKind::Impl(hir::Impl { self_ty, .. })) =
439item.map(|i| &i.kind)
440 {
441cause.span = self_ty.span;
442 }
443 }
444 traits::Obligation::with_depth(
445tcx,
446cause,
447depth,
448param_env,
449 ty::ClauseKind::WellFormed(term),
450 )
451 }),
452 );
453 }
454455// Compute the obligations that are required for `trait_ref` to be WF,
456 // given that it is a *negative* trait predicate.
457fn add_wf_preds_for_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
458for arg in trait_ref.args {
459if let Some(term) = arg.as_term() {
460self.add_wf_preds_for_term(term);
461 }
462 }
463 }
464465/// Pushes the obligations required for a projection to be WF into `self.out`.
466fn add_wf_preds_for_projection_term(&mut self, data: ty::AliasTerm<'tcx>) {
467// A projection is well-formed if
468 //
469 // (a) its predicates hold (*)
470 // (b) its args are wf
471 //
472 // (*) The predicates of an associated type include the predicates of
473 // the trait that it's contained in. For example, given
474 //
475 // trait A<T>: Clone {
476 // type X where T: Copy;
477 // }
478 //
479 // The predicates of `<() as A<i32>>::X` are:
480 // [
481 // `(): Sized`
482 // `(): Clone`
483 // `(): A<i32>`
484 // `i32: Sized`
485 // `i32: Clone`
486 // `i32: Copy`
487 // ]
488self.nominal_obligations(data.expect_projection_def_id(), data.args, |this, obligation| {
489this.out.push(obligation)
490 });
491492self.add_wf_preds_for_projection_args(data.args);
493 }
494495/// Pushes the obligations required for an inherent alias to be WF
496 /// into `self.out`.
497// FIXME(inherent_associated_types): Merge this function with `fn compute_alias`.
498fn add_wf_preds_for_inherent_projection(&mut self, data: ty::AliasTerm<'tcx>) {
499// An inherent projection is well-formed if
500 //
501 // (a) its predicates hold (*)
502 // (b) its args are wf
503 //
504 // (*) The predicates of an inherent associated type include the
505 // predicates of the impl that it's contained in.
506507 // In an ideal world, there are no escaping bound vars here. However, WF is jank, and
508 // sometimes there are. We can only `compute_inherent_assoc_term_args` if the Self ty in the
509 // args has no escaping bound vars. If we already have impl format args, though,
510 // `compute_inherent_assoc_term_args` is a no-op (and we have no Self type), so no need to
511 // check for escaping bound vars.
512let can_compute_impl_args =
513#[allow(non_exhaustive_omitted_patterns)] match data.kind {
ty::AliasTermKind::InherentConstImpl { .. } => true,
_ => false,
}matches!(data.kind, ty::AliasTermKind::InherentConstImpl { .. })514 || !data.self_ty().has_escaping_bound_vars();
515516if can_compute_impl_args {
517// FIXME(inherent_associated_types): Should this happen inside of a snapshot?
518 // FIXME(inherent_associated_types): This is incompatible with the new solver and lazy norm!
519let args = traits::project::compute_inherent_assoc_term_args(
520&mut traits::SelectionContext::new(self.infcx),
521self.param_env,
522data,
523self.cause(ObligationCauseCode::WellFormed(None)),
524self.recursion_depth,
525&mut self.out,
526 );
527let def_id = data.expect_inherent_def_id();
528self.nominal_obligations(def_id, args, |this, obligation| this.out.push(obligation));
529 }
530531data.args.visit_with(self);
532 }
533534fn add_wf_preds_for_projection_args(&mut self, args: GenericArgsRef<'tcx>) {
535let tcx = self.tcx();
536let cause = self.cause(ObligationCauseCode::WellFormed(None));
537let param_env = self.param_env;
538let depth = self.recursion_depth;
539540self.out.extend(
541args.iter()
542 .filter_map(|arg| arg.as_term())
543 .filter(|term| !term.has_escaping_bound_vars())
544 .map(|term| {
545 traits::Obligation::with_depth(
546tcx,
547cause.clone(),
548depth,
549param_env,
550 ty::ClauseKind::WellFormed(term),
551 )
552 }),
553 );
554 }
555556fn require_sized(&mut self, subty: Ty<'tcx>, cause: traits::ObligationCauseCode<'tcx>) {
557if !subty.has_escaping_bound_vars() {
558let cause = self.cause(cause);
559let trait_ref = ty::TraitRef::new(
560self.tcx(),
561self.tcx().require_lang_item(LangItem::Sized, cause.span),
562 [subty],
563 );
564self.out.push(traits::Obligation::with_depth(
565self.tcx(),
566cause,
567self.recursion_depth,
568self.param_env,
569 ty::Binder::dummy(trait_ref),
570 ));
571 }
572 }
573574/// Pushes all the predicates needed to validate that `term` is WF into `out`.
575{}
#[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("add_wf_preds_for_term",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(575u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("term")
}> =
::tracing::__macro_support::FieldName::new("term");
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(&term)
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;
}
{
term.visit_with(self);
{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:578",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(578u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("self.out")
}> =
::tracing::__macro_support::FieldName::new("self.out");
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(&self.out)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};
}
}
}#[instrument(level = "debug", skip(self))]576fn add_wf_preds_for_term(&mut self, term: Term<'tcx>) {
577 term.visit_with(self);
578debug!(?self.out);
579 }
580581{}
#[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("nominal_obligations",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(581u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("def_id")
}> =
::tracing::__macro_support::FieldName::new("def_id");
NAME.as_str()
},
{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("args")
}> =
::tracing::__macro_support::FieldName::new("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(&def_id)
as &dyn ::tracing::field::Value)),
(::tracing::__macro_support::Option::Some(&::tracing::field::debug(&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;
}
{
if self.tcx().is_lang_item(def_id, LangItem::Sized) { return; }
if self.tcx().is_lang_item(def_id, LangItem::ConstParamTy) &&
self.tcx().features().const_param_ty_unchecked() {
return;
}
let tcx = self.tcx();
let mut head = (def_id, tcx.clauses_of(def_id));
let mut inner_levels = Vec::new();
while let Some(parent) = head.1.parent {
inner_levels.push(head);
head = (parent, tcx.clauses_of(parent));
}
for &(origin_def_id, clauses) in
iter::once(&head).chain(inner_levels.iter().rev()) {
for (clause, span) in clauses.instantiate_own(tcx, args) {
if !clause.has_escaping_bound_vars() {
let code =
ObligationCauseCode::WhereClause(origin_def_id, span);
let cause = self.cause(code);
let obligation =
traits::Obligation::with_depth(tcx, cause,
self.recursion_depth, self.param_env,
clause.skip_norm_wip());
push_obligation(self, obligation);
}
}
}
}
}
}#[instrument(level = "debug", skip(self, push_obligation))]582fn nominal_obligations(
583&mut self,
584 def_id: DefId,
585 args: GenericArgsRef<'tcx>,
586mut push_obligation: impl FnMut(&mut Self, PredicateObligation<'tcx>),
587 ) {
588// PERF: `Sized`'s predicates include `MetaSized`, but both are compiler implemented marker
589 // traits, so `MetaSized` will always be WF if `Sized` is WF and vice-versa. Determining
590 // the nominal obligations of `Sized` would in-effect just elaborate `MetaSized` and make
591 // the compiler do a bunch of work needlessly.
592if self.tcx().is_lang_item(def_id, LangItem::Sized) {
593return;
594 }
595if self.tcx().is_lang_item(def_id, LangItem::ConstParamTy)
596 && self.tcx().features().const_param_ty_unchecked()
597 {
598return;
599 }
600601let tcx = self.tcx();
602let mut head = (def_id, tcx.clauses_of(def_id));
603let mut inner_levels = Vec::new(); // only allocates if a parent chain exists
604while let Some(parent) = head.1.parent {
605 inner_levels.push(head);
606 head = (parent, tcx.clauses_of(parent));
607 }
608609// Emit outermost first, as diagnostics rely on that order.
610for &(origin_def_id, clauses) in iter::once(&head).chain(inner_levels.iter().rev()) {
611for (clause, span) in clauses.instantiate_own(tcx, args) {
612if !clause.has_escaping_bound_vars() {
613let code = ObligationCauseCode::WhereClause(origin_def_id, span);
614let cause = self.cause(code);
615let obligation = traits::Obligation::with_depth(
616 tcx,
617 cause,
618self.recursion_depth,
619self.param_env,
620 clause.skip_norm_wip(),
621 );
622 push_obligation(self, obligation);
623 }
624 }
625 }
626 }
627628fn add_wf_preds_for_dyn_ty(
629&mut self,
630 ty: Ty<'tcx>,
631 data: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
632 region: ty::Region<'tcx>,
633 ) {
634// Imagine a type like this:
635 //
636 // trait Foo { }
637 // trait Bar<'c> : 'c { }
638 //
639 // &'b (Foo+'c+Bar<'d>)
640 // ^
641 //
642 // In this case, the following relationships must hold:
643 //
644 // 'b <= 'c
645 // 'd <= 'c
646 //
647 // The first conditions is due to the normal region pointer
648 // rules, which say that a reference cannot outlive its
649 // referent.
650 //
651 // The final condition may be a bit surprising. In particular,
652 // you may expect that it would have been `'c <= 'd`, since
653 // usually lifetimes of outer things are conservative
654 // approximations for inner things. However, it works somewhat
655 // differently with trait objects: here the idea is that if the
656 // user specifies a region bound (`'c`, in this case) it is the
657 // "master bound" that *implies* that bounds from other traits are
658 // all met. (Remember that *all bounds* in a type like
659 // `Foo+Bar+Zed` must be met, not just one, hence if we write
660 // `Foo<'x>+Bar<'y>`, we know that the type outlives *both* 'x and
661 // 'y.)
662 //
663 // Note: in fact we only permit builtin traits, not `Bar<'d>`, I
664 // am looking forward to the future here.
665if !data.has_escaping_bound_vars() && !region.has_escaping_bound_vars() {
666let implicit_bounds = object_region_bounds(self.tcx(), data);
667668let explicit_bound = region;
669670self.out.reserve(implicit_bounds.len());
671for implicit_bound in implicit_bounds {
672let cause = self.cause(ObligationCauseCode::ObjectTypeBound(ty, explicit_bound));
673let outlives =
674 ty::Binder::dummy(ty::OutlivesClause(explicit_bound, implicit_bound));
675self.out.push(traits::Obligation::with_depth(
676self.tcx(),
677 cause,
678self.recursion_depth,
679self.param_env,
680 outlives,
681 ));
682 }
683684// We don't add any wf predicates corresponding to the trait ref's generic arguments
685 // which allows code like this to compile:
686 // ```rust
687 // trait Trait<T: Sized> {}
688 // fn foo(_: &dyn Trait<[u32]>) {}
689 // ```
690}
691 }
692693fn add_wf_preds_for_pat_ty(&mut self, base_ty: Ty<'tcx>, pat: ty::Pattern<'tcx>) {
694let tcx = self.tcx();
695match *pat {
696 ty::PatternKind::Range { start, end } => {
697let mut check = |c| {
698let cause = self.cause(ObligationCauseCode::Misc);
699self.out.push(traits::Obligation::with_depth(
700tcx,
701cause.clone(),
702self.recursion_depth,
703self.param_env,
704 ty::Binder::dummy(ty::PredicateKind::Clause(
705 ty::ClauseKind::ConstArgHasType(c, base_ty),
706 )),
707 ));
708if !tcx.features().generic_pattern_types() {
709if c.has_param() {
710if self.span.is_dummy() {
711self.tcx()
712 .dcx()
713 .delayed_bug("feature error should be reported elsewhere, too");
714 } else {
715feature_err(
716&self.tcx().sess,
717 sym::generic_pattern_types,
718self.span,
719"wraparound pattern type ranges cause monomorphization time errors",
720 )
721 .emit();
722 }
723 }
724 }
725 };
726check(start);
727check(end);
728 }
729 ty::PatternKind::NotNull => {}
730 ty::PatternKind::Or(patterns) => {
731for pat in patterns {
732self.add_wf_preds_for_pat_ty(base_ty, pat)
733 }
734 }
735 }
736 }
737}
738739impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
740fn visit_ty(&mut self, t: Ty<'tcx>) -> Self::Result {
741{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:741",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(741u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::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!("wf bounds for t={0:?} t.kind={1:#?}",
t, t.kind()) as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!("wf bounds for t={:?} t.kind={:#?}", t, t.kind());
742743if !self.visited_tys.insert(t) {
744return;
745 }
746747let tcx = self.tcx();
748749match *t.kind() {
750 ty::Bool751 | ty::Char752 | ty::Int(..)
753 | ty::Uint(..)
754 | ty::Float(..)
755 | ty::Error(_)
756 | ty::Str757 | ty::CoroutineWitness(..)
758 | ty::Never759 | ty::Param(_)
760 | ty::Bound(..)
761 | ty::Placeholder(..)
762 | ty::Foreign(..) => {
763// WfScalar, WfParameter, etc
764}
765766// Can only infer to `ty::Int(_) | ty::Uint(_)`.
767ty::Infer(ty::IntVar(_)) => {}
768769// Can only infer to `ty::Float(_)`.
770ty::Infer(ty::FloatVar(_)) => {}
771772 ty::Slice(subty) => {
773self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
774 }
775776 ty::Array(subty, len) => {
777self.require_sized(subty, ObligationCauseCode::SliceOrArrayElem);
778// Note that the len being WF is implicitly checked while visiting.
779 // Here we just check that it's of type usize.
780let cause = self.cause(ObligationCauseCode::ArrayLen(t));
781self.out.push(traits::Obligation::with_depth(
782tcx,
783cause,
784self.recursion_depth,
785self.param_env,
786 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
787len,
788tcx.types.usize,
789 ))),
790 ));
791 }
792793 ty::Pat(base_ty, pat) => {
794self.require_sized(base_ty, ObligationCauseCode::Misc);
795self.add_wf_preds_for_pat_ty(base_ty, pat);
796 }
797798 ty::Tuple(tys) => {
799if let Some((last, rest)) = tys.split_last() {
800for &elem in rest {
801self.require_sized(elem, ObligationCauseCode::TupleElem);
802if elem.is_scalable_vector() && !self.span.is_dummy() {
803self.tcx()
804 .dcx()
805 .struct_span_err(
806self.span,
807"scalable vectors cannot be tuple fields",
808 )
809 .emit();
810 }
811 }
812813if last.is_scalable_vector() && !self.span.is_dummy() {
814self.tcx()
815 .dcx()
816 .struct_span_err(self.span, "scalable vectors cannot be tuple fields")
817 .emit();
818 }
819 }
820 }
821822 ty::RawPtr(_, _) => {
823// Simple cases that are WF if their type args are WF.
824}
825826 ty::Alias(
827_,
828 ty::AliasTy {
829 kind: ty::Projection { def_id } | ty::Opaque { def_id } | ty::Free { def_id },
830 args,
831 ..
832 },
833 ) => {
834self.nominal_obligations(def_id, args, |this, obligation| {
835this.out.push(obligation)
836 });
837 }
838 ty::Alias(_, data @ ty::AliasTy { kind: ty::Inherent { .. }, .. }) => {
839self.add_wf_preds_for_inherent_projection(data.into());
840return; // Subtree handled by compute_inherent_projection.
841}
842843 ty::Adt(def, args) => {
844// WfNominalType
845self.nominal_obligations(def.did(), args, |this, obligation| {
846this.out.push(obligation)
847 });
848 }
849850 ty::FnDef(did, args) => {
851let args = args.no_bound_vars().unwrap();
852// HACK: Check the return type of function definitions for
853 // well-formedness to mostly fix #84533. This is still not
854 // perfect and there may be ways to abuse the fact that we
855 // ignore requirements with escaping bound vars. That's a
856 // more general issue however.
857let fn_sig = tcx.fn_sig(did).instantiate(tcx, args).skip_norm_wip();
858fn_sig.output().skip_binder().visit_with(self);
859860self.nominal_obligations(did, args, |this, obligation| this.out.push(obligation));
861 }
862863 ty::Ref(r, rty, _) => {
864// WfReference
865if !r.has_escaping_bound_vars() && !rty.has_escaping_bound_vars() {
866let cause = self.cause(ObligationCauseCode::ReferenceOutlivesReferent(t));
867self.out.push(traits::Obligation::with_depth(
868tcx,
869cause,
870self.recursion_depth,
871self.param_env,
872 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(
873 ty::OutlivesClause(rty, r),
874 ))),
875 ));
876 }
877 }
878879 ty::Coroutine(did, args, ..) => {
880// Walk ALL the types in the coroutine: this will
881 // include the upvar types as well as the yield
882 // type. Note that this is mildly distinct from
883 // the closure case, where we have to be careful
884 // about the signature of the closure. We don't
885 // have the problem of implied bounds here since
886 // coroutines don't take arguments.
887self.nominal_obligations(did, args, |this, obligation| this.out.push(obligation));
888 }
889890 ty::Closure(did, args) => {
891// Note that we cannot skip the generic types
892 // types. Normally, within the fn
893 // body where they are created, the generics will
894 // always be WF, and outside of that fn body we
895 // are not directly inspecting closure types
896 // anyway, except via auto trait matching (which
897 // only inspects the upvar types).
898 // But when a closure is part of a type-alias-impl-trait
899 // then the function that created the defining site may
900 // have had more bounds available than the type alias
901 // specifies. This may cause us to have a closure in the
902 // hidden type that is not actually well formed and
903 // can cause compiler crashes when the user abuses unsafe
904 // code to procure such a closure.
905 // See tests/ui/type-alias-impl-trait/wf_check_closures.rs
906self.nominal_obligations(did, args, |this, obligation| this.out.push(obligation));
907// Only check the upvar types for WF, not the rest
908 // of the types within. This is needed because we
909 // capture the signature and it may not be WF
910 // without the implied bounds. Consider a closure
911 // like `|x: &'a T|` -- it may be that `T: 'a` is
912 // not known to hold in the creator's context (and
913 // indeed the closure may not be invoked by its
914 // creator, but rather turned to someone who *can*
915 // verify that).
916 //
917 // The special treatment of closures here really
918 // ought not to be necessary either; the problem
919 // is related to #25860 -- there is no way for us
920 // to express a fn type complete with the implied
921 // bounds that it is assuming. I think in reality
922 // the WF rules around fn are a bit messed up, and
923 // that is the rot problem: `fn(&'a T)` should
924 // probably always be WF, because it should be
925 // shorthand for something like `where(T: 'a) {
926 // fn(&'a T) }`, as discussed in #25860.
927let upvars = args.as_closure().tupled_upvars_ty();
928return upvars.visit_with(self);
929 }
930931 ty::CoroutineClosure(did, args) => {
932// See the above comments. The same apply to coroutine-closures.
933self.nominal_obligations(did, args, |this, obligation| this.out.push(obligation));
934let upvars = args.as_coroutine_closure().tupled_upvars_ty();
935return upvars.visit_with(self);
936 }
937938 ty::FnPtr(..) => {
939// Let the visitor iterate into the argument/return
940 // types appearing in the fn signature.
941}
942 ty::UnsafeBinder(ty) => {
943// FIXME(unsafe_binders): For now, we have no way to express
944 // that a type must be `ManuallyDrop` OR `Copy` (or a pointer).
945if !ty.has_escaping_bound_vars() {
946self.out.push(traits::Obligation::new(
947self.tcx(),
948self.cause(ObligationCauseCode::Misc),
949self.param_env,
950ty.map_bound(|ty| {
951 ty::TraitRef::new(
952self.tcx(),
953self.tcx().require_lang_item(
954 LangItem::BikeshedGuaranteedNoDrop,
955self.span,
956 ),
957 [ty],
958 )
959 }),
960 ));
961 }
962963// We recurse into the binder below.
964}
965966 ty::Dynamic(data, r) => {
967// WfObject
968 //
969 // Here, we defer WF checking due to higher-ranked
970 // regions. This is perhaps not ideal.
971self.add_wf_preds_for_dyn_ty(t, data, r);
972973// FIXME(#27579) RFC also considers adding trait
974 // obligations that don't refer to Self and
975 // checking those
976if let Some(principal) = data.principal() {
977let principal_def_id = principal.skip_binder().def_id;
978self.out.push(traits::Obligation::with_depth(
979tcx,
980self.cause(ObligationCauseCode::WellFormed(None)),
981self.recursion_depth,
982self.param_env,
983 ty::Binder::dummy(ty::PredicateKind::DynCompatible(principal_def_id)),
984 ));
985986// For the most part we don't add wf predicates corresponding to
987 // the trait ref's generic arguments which allows code like this
988 // to compile:
989 // ```rust
990 // trait Trait<T: Sized> {}
991 // fn foo(_: &dyn Trait<[u32]>) {}
992 // ```
993 //
994 // However, we sometimes incidentally check that const arguments
995 // have the correct type as a side effect of the anon const
996 // desugaring. To make this "consistent" for users we explicitly
997 // check `ConstArgHasType` clauses so that const args that don't
998 // go through an anon const still have their types checked.
999 //
1000 // See also: https://rustc-dev-guide.rust-lang.org/const-generics.html
1001let args = principal.skip_binder().with_self_ty(self.tcx(), t).args;
1002self.nominal_obligations(principal_def_id, args, |this, obligation| {
1003let kind = obligation.predicate.kind().skip_binder();
1004let keep = match kind {
1005 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _))
1006if #[allow(non_exhaustive_omitted_patterns)] match ct.kind() {
ty::ConstKind::Param(..) => true,
_ => false,
}matches!(ct.kind(), ty::ConstKind::Param(..)) =>
1007 {
1008// ConstArgHasType clauses are not higher kinded. Assert as
1009 // such so we can fix this up if that ever changes.
1010if !obligation.predicate.kind().bound_vars().is_empty() {
::core::panicking::panic("assertion failed: obligation.predicate.kind().bound_vars().is_empty()")
};assert!(obligation.predicate.kind().bound_vars().is_empty());
1011// In stable rust, variables from the trait object binder
1012 // cannot be referenced by a ConstArgHasType clause. However,
1013 // under `generic_const_parameter_types`, it can. Ignore those
1014 // predicates for now, to not have HKT-ConstArgHasTypes.
1015!kind.has_escaping_bound_vars()
1016 }
1017_ => false,
1018 };
1019if keep {
1020this.out.push(obligation);
1021 }
1022 });
1023 }
10241025if !t.has_escaping_bound_vars() {
1026for projection in data.projection_bounds() {
1027let pred_binder = projection
1028 .with_self_ty(tcx, t)
1029 .map_bound(|p| {
1030 p.term.as_const().map(|ct| {
1031let assoc_const_ty = tcx
1032 .type_of(p.def_id())
1033 .instantiate(tcx, p.projection_term.args)
1034 .skip_norm_wip();
1035 ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(
1036 ct,
1037 assoc_const_ty,
1038 ))
1039 })
1040 })
1041 .transpose();
1042if let Some(pred_binder) = pred_binder {
1043self.out.push(traits::Obligation::with_depth(
1044 tcx,
1045self.cause(ObligationCauseCode::WellFormed(None)),
1046self.recursion_depth,
1047self.param_env,
1048 pred_binder,
1049 ));
1050 }
1051 }
1052 }
1053 }
10541055// Inference variables are the complicated case, since we don't
1056 // know what type they are. We do two things:
1057 //
1058 // 1. Check if they have been resolved, and if so proceed with
1059 // THAT type.
1060 // 2. If not, we've at least simplified things (e.g., we went
1061 // from `Vec?0>: WF` to `?0: WF`), so we can
1062 // register a pending obligation and keep
1063 // moving. (Goal is that an "inductive hypothesis"
1064 // is satisfied to ensure termination.)
1065 // See also the comment on `fn obligations`, describing cycle
1066 // prevention, which happens before this can be reached.
1067ty::Infer(_) => {
1068let cause = self.cause(ObligationCauseCode::WellFormed(None));
1069self.out.push(traits::Obligation::with_depth(
1070tcx,
1071cause,
1072self.recursion_depth,
1073self.param_env,
1074 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
1075t.into(),
1076 ))),
1077 ));
1078 }
1079 }
10801081t.super_visit_with(self)
1082 }
10831084fn visit_const(&mut self, c: ty::Const<'tcx>) -> Self::Result {
1085let tcx = self.tcx();
10861087match c.kind() {
1088 ty::ConstKind::Alias(_, alias_const) => {
1089if !c.has_escaping_bound_vars() {
1090// Skip type consts as mGCA doesn't support evaluatable clauses
1091if !alias_const.kind.is_direct_const(tcx)
1092 && !tcx.features().generic_const_args()
1093 {
1094let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
1095 ty::ClauseKind::ConstEvaluatable(c),
1096 ));
1097let cause = self.cause(ObligationCauseCode::WellFormed(None));
1098self.out.push(traits::Obligation::with_depth(
1099tcx,
1100cause,
1101self.recursion_depth,
1102self.param_env,
1103predicate,
1104 ));
1105 }
11061107match alias_const.kind {
1108 ty::AliasConstKind::InherentSelf { .. } => {
1109self.add_wf_preds_for_inherent_projection(alias_const.into());
1110return; // Subtree is handled by above function
1111}
1112// FIXME: This should be unreachable but isn't because we normalize in item
1113 // wfck before computing wf requirements
1114ty::AliasConstKind::InherentImpl { .. } => {
1115self.add_wf_preds_for_inherent_projection(alias_const.into());
1116return;
1117 }
1118 ty::AliasConstKind::Projection { def_id }
1119 | ty::AliasConstKind::Free { def_id }
1120 | ty::AliasConstKind::Anon { def_id } => {
1121self.nominal_obligations(
1122def_id,
1123alias_const.args,
1124 |this, obligation| this.out.push(obligation),
1125 );
1126 }
1127 }
1128 }
1129 }
1130 ty::ConstKind::Infer(_) => {
1131let cause = self.cause(ObligationCauseCode::WellFormed(None));
11321133self.out.push(traits::Obligation::with_depth(
1134tcx,
1135cause,
1136self.recursion_depth,
1137self.param_env,
1138 ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(
1139c.into(),
1140 ))),
1141 ));
1142 }
1143 ty::ConstKind::Expr(_) => {
1144// FIXME(generic_const_exprs): this doesn't verify that given `Expr(N + 1)` the
1145 // trait bound `typeof(N): Add<typeof(1)>` holds. This is currently unnecessary
1146 // as `ConstKind::Expr` is only produced via normalization of `ConstKind::Alias`
1147 // which means that the `DefId` would have been typeck'd elsewhere. However in
1148 // the future we may allow directly lowering to `ConstKind::Expr` in which case
1149 // we would not be proving bounds we should.
11501151let predicate = ty::Binder::dummy(ty::PredicateKind::Clause(
1152 ty::ClauseKind::ConstEvaluatable(c),
1153 ));
1154let cause = self.cause(ObligationCauseCode::WellFormed(None));
1155self.out.push(traits::Obligation::with_depth(
1156tcx,
1157cause,
1158self.recursion_depth,
1159self.param_env,
1160predicate,
1161 ));
1162 }
11631164 ty::ConstKind::Error(_)
1165 | ty::ConstKind::Param(_)
1166 | ty::ConstKind::Bound(..)
1167 | ty::ConstKind::Placeholder(..) => {
1168// These variants are trivially WF, so nothing to do here.
1169}
1170 ty::ConstKind::Value(val) => {
1171// FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased
1172if tcx.features().min_generic_const_args() {
1173match val.ty.kind() {
1174 ty::Adt(adt_def, args) => {
1175let adt_val = val.destructure_adt_const();
1176let variant_def = adt_def.variant(adt_val.variant);
1177let cause = self.cause(ObligationCauseCode::WellFormed(None));
1178self.out.extend(variant_def.fields.iter().zip(adt_val.fields).map(
1179 |(field_def, &field_val)| {
1180let field_ty = tcx1181 .type_of(field_def.did)
1182 .instantiate(tcx, args)
1183 .skip_norm_wip();
1184let predicate = ty::PredicateKind::Clause(
1185 ty::ClauseKind::ConstArgHasType(field_val, field_ty),
1186 );
1187 traits::Obligation::with_depth(
1188tcx,
1189cause.clone(),
1190self.recursion_depth,
1191self.param_env,
1192predicate,
1193 )
1194 },
1195 ));
1196 }
1197 ty::Tuple(field_tys) => {
1198let field_vals = val.to_branch();
1199let cause = self.cause(ObligationCauseCode::WellFormed(None));
1200self.out.extend(field_tys.iter().zip(field_vals).map(
1201 |(field_ty, &field_val)| {
1202let predicate = ty::PredicateKind::Clause(
1203 ty::ClauseKind::ConstArgHasType(field_val, field_ty),
1204 );
1205 traits::Obligation::with_depth(
1206tcx,
1207cause.clone(),
1208self.recursion_depth,
1209self.param_env,
1210predicate,
1211 )
1212 },
1213 ));
1214 }
1215 ty::Array(elem_ty, _len) => {
1216let elem_vals = val.to_branch();
1217let cause = self.cause(ObligationCauseCode::WellFormed(None));
12181219self.out.extend(elem_vals.iter().map(|&elem_val| {
1220let predicate = ty::PredicateKind::Clause(
1221 ty::ClauseKind::ConstArgHasType(elem_val, *elem_ty),
1222 );
1223 traits::Obligation::with_depth(
1224tcx,
1225cause.clone(),
1226self.recursion_depth,
1227self.param_env,
1228predicate,
1229 )
1230 }));
1231 }
1232_ => {}
1233 }
1234 }
12351236// FIXME: Enforce that values are structurally-matchable.
1237}
1238 }
12391240c.super_visit_with(self)
1241 }
12421243fn visit_predicate(&mut self, _p: ty::Predicate<'tcx>) -> Self::Result {
1244::rustc_middle::util::bug::bug_fmt(format_args!("predicate should not be checked for well-formedness"));bug!("predicate should not be checked for well-formedness");
1245 }
1246}
12471248/// Given an object type like `SomeTrait + Send`, computes the lifetime
1249/// bounds that must hold on the elided self type. These are derived
1250/// from the declarations of `SomeTrait`, `Send`, and friends -- if
1251/// they declare `trait SomeTrait : 'static`, for example, then
1252/// `'static` would appear in the list.
1253///
1254/// N.B., in some cases, particularly around higher-ranked bounds,
1255/// this function returns a kind of conservative approximation.
1256/// That is, all regions returned by this function are definitely
1257/// required, but there may be other region bounds that are not
1258/// returned, as well as requirements like `for<'a> T: 'a`.
1259///
1260/// Requires that trait definitions have been processed so that we can
1261/// elaborate predicates and walk supertraits.
1262pub fn object_region_bounds<'tcx>(
1263 tcx: TyCtxt<'tcx>,
1264 existential_predicates: &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
1265) -> Vec<ty::Region<'tcx>> {
1266let erased_self_ty = tcx.types.trait_object_dummy_self;
12671268let clauses =
1269existential_predicates.iter().map(|predicate| predicate.with_self_ty(tcx, erased_self_ty));
12701271 traits::elaborate(tcx, clauses)
1272 .filter_map(|clause| {
1273{
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event /rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs:1273",
"rustc_trait_selection::traits::wf",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("/rustc-dev/cea272fa356e94bd2ee2cadf376630aa0683867a/compiler/rustc_trait_selection/src/traits/wf.rs"),
::tracing_core::__macro_support::Option::Some(1273u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::wf"),
::tracing_core::field::FieldSet::new(&[{
const NAME:
::tracing::__macro_support::FieldName<{
::tracing::__macro_support::FieldName::len("clause")
}> =
::tracing::__macro_support::FieldName::new("clause");
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(&clause)
as &dyn ::tracing::field::Value))])
});
} else { ; }
};debug!(?clause);
1274match clause.kind().skip_binder() {
1275 ty::ClauseKind::TypeOutlives(ty::OutlivesClause(ref t, ref r)) => {
1276// Search for a bound of the form `erased_self_ty
1277 // : 'a`, but be wary of something like `for<'a>
1278 // erased_self_ty : 'a` (we interpret a
1279 // higher-ranked bound like that as 'static,
1280 // though at present the code in `fulfill.rs`
1281 // considers such bounds to be unsatisfiable, so
1282 // it's kind of a moot point since you could never
1283 // construct such an object, but this seems
1284 // correct even if that code changes).
1285if t == &erased_self_ty && !r.has_escaping_bound_vars() {
1286Some(*r)
1287 } else {
1288None1289 }
1290 }
1291 ty::ClauseKind::Trait(_)
1292 | ty::ClauseKind::HostEffect(..)
1293 | ty::ClauseKind::RegionOutlives(_)
1294 | ty::ClauseKind::Projection(_)
1295 | ty::ClauseKind::ConstArgHasType(_, _)
1296 | ty::ClauseKind::WellFormed(_)
1297 | ty::ClauseKind::UnstableFeature(_)
1298 | ty::ClauseKind::ConstEvaluatable(_) => None,
1299 }
1300 })
1301 .collect()
1302}