rustc_trait_selection/traits/
util.rs1use std::collections::VecDeque;
2
3use rustc_data_structures::fx::FxHashSet;
4use rustc_hir::LangItem;
5use rustc_hir::def_id::DefId;
6use rustc_infer::infer::InferCtxt;
7use rustc_infer::traits::PolyTraitObligation;
8pub use rustc_infer::traits::util::*;
9use rustc_middle::ty::fast_reject::DeepRejectCtxt;
10use rustc_middle::ty::{
11 self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
12 TyCtxt, TypeFoldable, TypeVisitableExt, Unnormalized,
13};
14pub use rustc_next_trait_solver::placeholder::{BoundVarReplacer, PlaceholderReplacer};
15use rustc_span::Span;
16use smallvec::{SmallVec, smallvec};
17use tracing::debug;
18
19pub fn expand_trait_aliases<'tcx>(
35 tcx: TyCtxt<'tcx>,
36 clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
37) -> (
38 Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
39 Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
40) {
41 let mut trait_preds = ::alloc::vec::Vec::new()vec![];
42 let mut projection_preds = ::alloc::vec::Vec::new()vec![];
43 let mut seen_projection_preds = FxHashSet::default();
44
45 let mut queue: VecDeque<_> = clauses.into_iter().map(|(p, s)| (p, {
let count = 0usize + 1usize;
let mut vec = ::smallvec::SmallVec::new();
if count <= vec.inline_size() {
vec.push(s);
vec
} else {
::smallvec::SmallVec::from_vec(::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[s])))
}
}smallvec![s])).collect();
46
47 while let Some((clause, spans)) = queue.pop_front() {
48 match clause.kind().skip_binder() {
49 ty::ClauseKind::Trait(trait_pred) => {
50 if tcx.is_trait_alias(trait_pred.def_id()) {
51 queue.extend(
52 tcx.explicit_super_predicates_of(trait_pred.def_id())
53 .iter_identity_copied()
54 .map(Unnormalized::skip_norm_wip)
55 .map(|(super_clause, span)| {
56 let mut spans = spans.clone();
57 spans.push(span);
58 (
59 super_clause.instantiate_supertrait(
60 tcx,
61 clause.kind().rebind(trait_pred.trait_ref),
62 ),
63 spans,
64 )
65 }),
66 );
67 } else {
68 trait_preds.push((clause.kind().rebind(trait_pred), spans));
69 }
70 }
71 ty::ClauseKind::Projection(projection_pred) => {
72 let projection_pred = clause.kind().rebind(projection_pred);
73 if !seen_projection_preds.insert(tcx.anonymize_bound_vars(projection_pred)) {
74 continue;
75 }
76 projection_preds.push((projection_pred, *spans.last().unwrap()));
77 }
78 ty::ClauseKind::RegionOutlives(..)
79 | ty::ClauseKind::TypeOutlives(..)
80 | ty::ClauseKind::ConstArgHasType(_, _)
81 | ty::ClauseKind::WellFormed(_)
82 | ty::ClauseKind::ConstEvaluatable(_)
83 | ty::ClauseKind::UnstableFeature(_)
84 | ty::ClauseKind::HostEffect(..) => {}
85 }
86 }
87
88 (trait_preds, projection_preds)
89}
90
91pub fn upcast_choices<'tcx>(
99 tcx: TyCtxt<'tcx>,
100 source_trait_ref: ty::PolyTraitRef<'tcx>,
101 target_trait_def_id: DefId,
102) -> Vec<ty::PolyTraitRef<'tcx>> {
103 if source_trait_ref.def_id() == target_trait_def_id {
104 return ::alloc::boxed::box_assume_init_into_vec_unsafe(::alloc::intrinsics::write_box_via_move(::alloc::boxed::Box::new_uninit(),
[source_trait_ref]))vec![source_trait_ref]; }
106
107 supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
108}
109
110pub(crate) fn closure_trait_ref_and_return_type<'tcx>(
111 tcx: TyCtxt<'tcx>,
112 fn_trait_def_id: DefId,
113 self_ty: Ty<'tcx>,
114 sig: ty::PolyFnSig<'tcx>,
115 tuple_arguments: TupleArgumentsFlag,
116) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
117 if !!self_ty.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !self_ty.has_escaping_bound_vars()")
};assert!(!self_ty.has_escaping_bound_vars());
118 let arguments_tuple = match tuple_arguments {
119 TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
120 TupleArgumentsFlag::Yes => Ty::new_tup(tcx, sig.skip_binder().inputs()),
121 };
122 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, arguments_tuple]);
123 sig.map_bound(|sig| (trait_ref, sig.output()))
124}
125
126pub(crate) fn coroutine_trait_ref_and_outputs<'tcx>(
127 tcx: TyCtxt<'tcx>,
128 fn_trait_def_id: DefId,
129 self_ty: Ty<'tcx>,
130 sig: ty::GenSig<TyCtxt<'tcx>>,
131) -> (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>) {
132 if !!self_ty.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !self_ty.has_escaping_bound_vars()")
};assert!(!self_ty.has_escaping_bound_vars());
133 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, sig.resume_ty]);
134 (trait_ref, sig.yield_ty, sig.return_ty)
135}
136
137pub(crate) fn future_trait_ref_and_outputs<'tcx>(
138 tcx: TyCtxt<'tcx>,
139 fn_trait_def_id: DefId,
140 self_ty: Ty<'tcx>,
141 sig: ty::GenSig<TyCtxt<'tcx>>,
142) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
143 if !!self_ty.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !self_ty.has_escaping_bound_vars()")
};assert!(!self_ty.has_escaping_bound_vars());
144 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty]);
145 (trait_ref, sig.return_ty)
146}
147
148pub(crate) fn iterator_trait_ref_and_outputs<'tcx>(
149 tcx: TyCtxt<'tcx>,
150 iterator_def_id: DefId,
151 self_ty: Ty<'tcx>,
152 sig: ty::GenSig<TyCtxt<'tcx>>,
153) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
154 if !!self_ty.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !self_ty.has_escaping_bound_vars()")
};assert!(!self_ty.has_escaping_bound_vars());
155 let trait_ref = ty::TraitRef::new(tcx, iterator_def_id, [self_ty]);
156 (trait_ref, sig.yield_ty)
157}
158
159pub(crate) fn async_iterator_trait_ref_and_outputs<'tcx>(
160 tcx: TyCtxt<'tcx>,
161 async_iterator_def_id: DefId,
162 self_ty: Ty<'tcx>,
163 sig: ty::GenSig<TyCtxt<'tcx>>,
164) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
165 if !!self_ty.has_escaping_bound_vars() {
::core::panicking::panic("assertion failed: !self_ty.has_escaping_bound_vars()")
};assert!(!self_ty.has_escaping_bound_vars());
166 let trait_ref = ty::TraitRef::new(tcx, async_iterator_def_id, [self_ty]);
167 (trait_ref, sig.yield_ty)
168}
169
170pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
171 assoc_item.defaultness(tcx).is_final()
172 && tcx.defaultness(assoc_item.container_id(tcx)).is_final()
173}
174
175pub(crate) enum TupleArgumentsFlag {
176 Yes,
177 No,
178}
179
180pub fn with_replaced_escaping_bound_vars<
193 'a,
194 'tcx,
195 T: TypeFoldable<TyCtxt<'tcx>>,
196 R: TypeFoldable<TyCtxt<'tcx>>,
197>(
198 infcx: &'a InferCtxt<'tcx>,
199 universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
200 value: T,
201 f: impl FnOnce(T) -> R,
202) -> R {
203 if value.has_escaping_bound_vars() {
204 let (value, mapped_regions, mapped_types, mapped_consts) =
205 BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
206 let result = f(value);
207 PlaceholderReplacer::replace_placeholders(
208 infcx,
209 mapped_regions,
210 mapped_types,
211 mapped_consts,
212 universe_indices,
213 result,
214 )
215 } else {
216 f(value)
217 }
218}
219
220pub fn sizedness_fast_path<'tcx>(
221 tcx: TyCtxt<'tcx>,
222 predicate: ty::Predicate<'tcx>,
223 param_env: ty::ParamEnv<'tcx>,
224) -> bool {
225 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
229 predicate.kind().skip_binder()
230 && trait_pred.polarity == ty::PredicatePolarity::Positive
231 {
232 let sizedness = match tcx.as_lang_item(trait_pred.def_id()) {
233 Some(LangItem::Sized) => SizedTraitKind::Sized,
234 Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
235 _ => return false,
236 };
237
238 if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
239 {
use ::tracing::__macro_support::Callsite as _;
static __CALLSITE: ::tracing::callsite::DefaultCallsite =
{
static META: ::tracing::Metadata<'static> =
{
::tracing_core::metadata::Metadata::new("event compiler/rustc_trait_selection/src/traits/util.rs:239",
"rustc_trait_selection::traits::util",
::tracing::Level::DEBUG,
::tracing_core::__macro_support::Option::Some("compiler/rustc_trait_selection/src/traits/util.rs"),
::tracing_core::__macro_support::Option::Some(239u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::util"),
::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!("fast path -- trivial sizedness")
as &dyn Value))])
});
} else { ; }
};debug!("fast path -- trivial sizedness");
240 return true;
241 }
242
243 if #[allow(non_exhaustive_omitted_patterns)] match trait_pred.self_ty().kind() {
ty::Param(_) | ty::Placeholder(_) => true,
_ => false,
}matches!(trait_pred.self_ty().kind(), ty::Param(_) | ty::Placeholder(_)) {
244 for clause in param_env.caller_bounds() {
245 if let ty::ClauseKind::Trait(clause_pred) = clause.kind().skip_binder()
246 && clause_pred.polarity == ty::PredicatePolarity::Positive
247 && clause_pred.self_ty() == trait_pred.self_ty()
248 && (clause_pred.def_id() == trait_pred.def_id()
249 || (sizedness == SizedTraitKind::MetaSized
250 && tcx.is_lang_item(clause_pred.def_id(), LangItem::Sized)))
251 {
252 return true;
253 }
254 }
255 }
256 }
257
258 false
259}
260
261pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
265 infcx: &InferCtxt<'tcx>,
266 obligation: &PolyTraitObligation<'tcx>,
267 candidate: PolyTraitPredicate<'tcx>,
268) -> PolyTraitPredicate<'tcx> {
269 if !infcx.tcx.is_lang_item(obligation.predicate.def_id(), LangItem::MetaSized)
270 || !infcx.tcx.is_lang_item(candidate.def_id(), LangItem::Sized)
271 {
272 return candidate;
273 }
274
275 if obligation.predicate.polarity() != PredicatePolarity::Positive
276 || candidate.polarity() != PredicatePolarity::Positive
277 {
278 return candidate;
279 }
280
281 let drcx = DeepRejectCtxt::relate_rigid_rigid(infcx.tcx);
282 if !drcx.args_may_unify(
283 obligation.predicate.skip_binder().trait_ref.args,
284 candidate.skip_binder().trait_ref.args,
285 ) {
286 return candidate;
287 }
288
289 candidate.map_bound(|c| TraitPredicate {
290 trait_ref: TraitRef::new_from_args(
291 infcx.tcx,
292 obligation.predicate.def_id(),
293 c.trait_ref.args,
294 ),
295 polarity: c.polarity,
296 })
297}