1use std::collections::VecDeque;
2
3use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
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::bug;
10use rustc_middle::ty::fast_reject::DeepRejectCtxt;
11use rustc_middle::ty::{
12 self, PolyTraitPredicate, PredicatePolarity, SizedTraitKind, TraitPredicate, TraitRef, Ty,
13 TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Unnormalized,
14};
15pub use rustc_next_trait_solver::placeholder::BoundVarReplacer;
16use rustc_span::Span;
17use smallvec::{SmallVec, smallvec};
18use tracing::debug;
19
20pub fn expand_trait_aliases<'tcx>(
36 tcx: TyCtxt<'tcx>,
37 clauses: impl IntoIterator<Item = (ty::Clause<'tcx>, Span)>,
38) -> (
39 Vec<(ty::PolyTraitPredicate<'tcx>, SmallVec<[Span; 1]>)>,
40 Vec<(ty::PolyProjectionPredicate<'tcx>, Span)>,
41) {
42 let mut trait_preds = ::alloc::vec::Vec::new()vec![];
43 let mut projection_preds = ::alloc::vec::Vec::new()vec![];
44 let mut seen_projection_preds = FxHashSet::default();
45
46 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();
47
48 while let Some((clause, spans)) = queue.pop_front() {
49 match clause.kind().skip_binder() {
50 ty::ClauseKind::Trait(trait_pred) => {
51 if tcx.is_trait_alias(trait_pred.def_id()) {
52 queue.extend(
53 tcx.explicit_super_predicates_of(trait_pred.def_id())
54 .iter_identity_copied()
55 .map(Unnormalized::skip_norm_wip)
56 .map(|(super_clause, span)| {
57 let mut spans = spans.clone();
58 spans.push(span);
59 (
60 super_clause.instantiate_supertrait(
61 tcx,
62 clause.kind().rebind(trait_pred.trait_ref),
63 ),
64 spans,
65 )
66 }),
67 );
68 } else {
69 trait_preds.push((clause.kind().rebind(trait_pred), spans));
70 }
71 }
72 ty::ClauseKind::Projection(projection_pred) => {
73 let projection_pred = clause.kind().rebind(projection_pred);
74 if !seen_projection_preds.insert(tcx.anonymize_bound_vars(projection_pred)) {
75 continue;
76 }
77 projection_preds.push((projection_pred, *spans.last().unwrap()));
78 }
79 ty::ClauseKind::RegionOutlives(..)
80 | ty::ClauseKind::TypeOutlives(..)
81 | ty::ClauseKind::ConstArgHasType(_, _)
82 | ty::ClauseKind::WellFormed(_)
83 | ty::ClauseKind::ConstEvaluatable(_)
84 | ty::ClauseKind::UnstableFeature(_)
85 | ty::ClauseKind::HostEffect(..) => {}
86 }
87 }
88
89 (trait_preds, projection_preds)
90}
91
92pub fn upcast_choices<'tcx>(
100 tcx: TyCtxt<'tcx>,
101 source_trait_ref: ty::PolyTraitRef<'tcx>,
102 target_trait_def_id: DefId,
103) -> Vec<ty::PolyTraitRef<'tcx>> {
104 if source_trait_ref.def_id() == target_trait_def_id {
105 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]; }
107
108 supertraits(tcx, source_trait_ref).filter(|r| r.def_id() == target_trait_def_id).collect()
109}
110
111pub(crate) fn closure_trait_ref_and_return_type<'tcx>(
112 tcx: TyCtxt<'tcx>,
113 fn_trait_def_id: DefId,
114 self_ty: Ty<'tcx>,
115 sig: ty::PolyFnSig<'tcx>,
116 tuple_arguments: TupleArgumentsFlag,
117) -> ty::Binder<'tcx, (ty::TraitRef<'tcx>, Ty<'tcx>)> {
118 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());
119 let arguments_tuple = match tuple_arguments {
120 TupleArgumentsFlag::No => sig.skip_binder().inputs()[0],
121 TupleArgumentsFlag::Yes => Ty::new_tup(tcx, sig.skip_binder().inputs()),
122 };
123 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, arguments_tuple]);
124 sig.map_bound(|sig| (trait_ref, sig.output()))
125}
126
127pub(crate) fn coroutine_trait_ref_and_outputs<'tcx>(
128 tcx: TyCtxt<'tcx>,
129 fn_trait_def_id: DefId,
130 self_ty: Ty<'tcx>,
131 sig: ty::GenSig<TyCtxt<'tcx>>,
132) -> (ty::TraitRef<'tcx>, Ty<'tcx>, Ty<'tcx>) {
133 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());
134 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty, sig.resume_ty]);
135 (trait_ref, sig.yield_ty, sig.return_ty)
136}
137
138pub(crate) fn future_trait_ref_and_outputs<'tcx>(
139 tcx: TyCtxt<'tcx>,
140 fn_trait_def_id: DefId,
141 self_ty: Ty<'tcx>,
142 sig: ty::GenSig<TyCtxt<'tcx>>,
143) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
144 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());
145 let trait_ref = ty::TraitRef::new(tcx, fn_trait_def_id, [self_ty]);
146 (trait_ref, sig.return_ty)
147}
148
149pub(crate) fn iterator_trait_ref_and_outputs<'tcx>(
150 tcx: TyCtxt<'tcx>,
151 iterator_def_id: DefId,
152 self_ty: Ty<'tcx>,
153 sig: ty::GenSig<TyCtxt<'tcx>>,
154) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
155 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());
156 let trait_ref = ty::TraitRef::new(tcx, iterator_def_id, [self_ty]);
157 (trait_ref, sig.yield_ty)
158}
159
160pub(crate) fn async_iterator_trait_ref_and_outputs<'tcx>(
161 tcx: TyCtxt<'tcx>,
162 async_iterator_def_id: DefId,
163 self_ty: Ty<'tcx>,
164 sig: ty::GenSig<TyCtxt<'tcx>>,
165) -> (ty::TraitRef<'tcx>, Ty<'tcx>) {
166 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());
167 let trait_ref = ty::TraitRef::new(tcx, async_iterator_def_id, [self_ty]);
168 (trait_ref, sig.yield_ty)
169}
170
171pub fn impl_item_is_final(tcx: TyCtxt<'_>, assoc_item: &ty::AssocItem) -> bool {
172 assoc_item.defaultness(tcx).is_final()
173 && tcx.defaultness(assoc_item.container_id(tcx)).is_final()
174}
175
176pub(crate) enum TupleArgumentsFlag {
177 Yes,
178 No,
179}
180
181pub fn with_replaced_escaping_bound_vars<
194 'a,
195 'tcx,
196 T: TypeFoldable<TyCtxt<'tcx>>,
197 R: TypeFoldable<TyCtxt<'tcx>>,
198>(
199 infcx: &'a InferCtxt<'tcx>,
200 universe_indices: &'a mut Vec<Option<ty::UniverseIndex>>,
201 value: T,
202 f: impl FnOnce(T) -> R,
203) -> R {
204 if value.has_escaping_bound_vars() {
205 let (value, mapped_regions, mapped_types, mapped_consts) =
206 BoundVarReplacer::replace_bound_vars(infcx, universe_indices, value);
207 let result = f(value);
208 PlaceholderReplacer::replace_placeholders(
209 infcx,
210 mapped_regions,
211 mapped_types,
212 mapped_consts,
213 universe_indices,
214 result,
215 )
216 } else {
217 f(value)
218 }
219}
220
221pub struct PlaceholderReplacer<'a, 'tcx> {
223 infcx: &'a InferCtxt<'tcx>,
224 mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
225 mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
226 mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
227 universe_indices: &'a [Option<ty::UniverseIndex>],
228 current_index: ty::DebruijnIndex,
229}
230
231impl<'a, 'tcx> PlaceholderReplacer<'a, 'tcx> {
232 pub fn replace_placeholders<T: TypeFoldable<TyCtxt<'tcx>>>(
233 infcx: &'a InferCtxt<'tcx>,
234 mapped_regions: FxIndexMap<ty::PlaceholderRegion<'tcx>, ty::BoundRegion<'tcx>>,
235 mapped_types: FxIndexMap<ty::PlaceholderType<'tcx>, ty::BoundTy<'tcx>>,
236 mapped_consts: FxIndexMap<ty::PlaceholderConst<'tcx>, ty::BoundConst<'tcx>>,
237 universe_indices: &'a [Option<ty::UniverseIndex>],
238 value: T,
239 ) -> T {
240 let mut replacer = PlaceholderReplacer {
241 infcx,
242 mapped_regions,
243 mapped_types,
244 mapped_consts,
245 universe_indices,
246 current_index: ty::INNERMOST,
247 };
248 value.fold_with(&mut replacer)
249 }
250}
251
252impl<'tcx> TypeFolder<TyCtxt<'tcx>> for PlaceholderReplacer<'_, 'tcx> {
253 fn cx(&self) -> TyCtxt<'tcx> {
254 self.infcx.tcx
255 }
256
257 fn fold_binder<T: TypeFoldable<TyCtxt<'tcx>>>(
258 &mut self,
259 t: ty::Binder<'tcx, T>,
260 ) -> ty::Binder<'tcx, T> {
261 if !t.has_placeholders() && !t.has_infer() {
262 return t;
263 }
264 self.current_index.shift_in(1);
265 let t = t.super_fold_with(self);
266 self.current_index.shift_out(1);
267 t
268 }
269
270 fn fold_region(&mut self, r0: ty::Region<'tcx>) -> ty::Region<'tcx> {
271 let r1 = match r0.kind() {
272 ty::ReVar(vid) => self
273 .infcx
274 .inner
275 .borrow_mut()
276 .unwrap_region_constraints()
277 .opportunistic_resolve_var(self.infcx.tcx, vid),
278 _ => r0,
279 };
280
281 let r2 = match r1.kind() {
282 ty::RePlaceholder(p) => {
283 let replace_var = self.mapped_regions.get(&p);
284 match replace_var {
285 Some(replace_var) => {
286 let index = self
287 .universe_indices
288 .iter()
289 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
290 .unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("Unexpected placeholder universe."))bug!("Unexpected placeholder universe."));
291 let db = ty::DebruijnIndex::from_usize(
292 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
293 );
294 ty::Region::new_bound(self.cx(), db, *replace_var)
295 }
296 None => r1,
297 }
298 }
299 _ => r1,
300 };
301
302 {
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:302",
"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(302u32),
::tracing_core::__macro_support::Option::Some("rustc_trait_selection::traits::util"),
::tracing_core::field::FieldSet::new(&["message", "r0",
"r1", "r2"],
::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!("fold_region")
as &dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r0) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r1) as
&dyn Value)),
(&::tracing::__macro_support::Iterator::next(&mut iter).expect("FieldSet corrupted (this is a bug)"),
::tracing::__macro_support::Option::Some(&debug(&r2) as
&dyn Value))])
});
} else { ; }
};debug!(?r0, ?r1, ?r2, "fold_region");
303
304 r2
305 }
306
307 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
308 let ty = self.infcx.shallow_resolve(ty);
309 match *ty.kind() {
310 ty::Placeholder(p) => {
311 let replace_var = self.mapped_types.get(&p);
312 match replace_var {
313 Some(replace_var) => {
314 let index = self
315 .universe_indices
316 .iter()
317 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
318 .unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("Unexpected placeholder universe."))bug!("Unexpected placeholder universe."));
319 let db = ty::DebruijnIndex::from_usize(
320 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
321 );
322 Ty::new_bound(self.infcx.tcx, db, *replace_var)
323 }
324 None => {
325 if ty.has_infer() {
326 ty.super_fold_with(self)
327 } else {
328 ty
329 }
330 }
331 }
332 }
333
334 _ if ty.has_placeholders() || ty.has_infer() => ty.super_fold_with(self),
335 _ => ty,
336 }
337 }
338
339 fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> {
340 let ct = self.infcx.shallow_resolve_const(ct);
341 if let ty::ConstKind::Placeholder(p) = ct.kind() {
342 let replace_var = self.mapped_consts.get(&p);
343 match replace_var {
344 Some(replace_var) => {
345 let index = self
346 .universe_indices
347 .iter()
348 .position(|u| #[allow(non_exhaustive_omitted_patterns)] match u {
Some(pu) if *pu == p.universe => true,
_ => false,
}matches!(u, Some(pu) if *pu == p.universe))
349 .unwrap_or_else(|| ::rustc_middle::util::bug::bug_fmt(format_args!("Unexpected placeholder universe."))bug!("Unexpected placeholder universe."));
350 let db = ty::DebruijnIndex::from_usize(
351 self.universe_indices.len() - index + self.current_index.as_usize() - 1,
352 );
353 ty::Const::new_bound(self.infcx.tcx, db, *replace_var)
354 }
355 None => {
356 if ct.has_infer() {
357 ct.super_fold_with(self)
358 } else {
359 ct
360 }
361 }
362 }
363 } else {
364 ct.super_fold_with(self)
365 }
366 }
367}
368
369pub fn sizedness_fast_path<'tcx>(
370 tcx: TyCtxt<'tcx>,
371 predicate: ty::Predicate<'tcx>,
372 param_env: ty::ParamEnv<'tcx>,
373) -> bool {
374 if let ty::PredicateKind::Clause(ty::ClauseKind::Trait(trait_pred)) =
378 predicate.kind().skip_binder()
379 && trait_pred.polarity == ty::PredicatePolarity::Positive
380 {
381 let sizedness = match tcx.as_lang_item(trait_pred.def_id()) {
382 Some(LangItem::Sized) => SizedTraitKind::Sized,
383 Some(LangItem::MetaSized) => SizedTraitKind::MetaSized,
384 _ => return false,
385 };
386
387 if trait_pred.self_ty().has_trivial_sizedness(tcx, sizedness) {
388 {
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:388",
"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(388u32),
::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");
389 return true;
390 }
391
392 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(_)) {
393 for clause in param_env.caller_bounds() {
394 if let ty::ClauseKind::Trait(clause_pred) = clause.kind().skip_binder()
395 && clause_pred.polarity == ty::PredicatePolarity::Positive
396 && clause_pred.self_ty() == trait_pred.self_ty()
397 && (clause_pred.def_id() == trait_pred.def_id()
398 || (sizedness == SizedTraitKind::MetaSized
399 && tcx.is_lang_item(clause_pred.def_id(), LangItem::Sized)))
400 {
401 return true;
402 }
403 }
404 }
405 }
406
407 false
408}
409
410pub(crate) fn lazily_elaborate_sizedness_candidate<'tcx>(
414 infcx: &InferCtxt<'tcx>,
415 obligation: &PolyTraitObligation<'tcx>,
416 candidate: PolyTraitPredicate<'tcx>,
417) -> PolyTraitPredicate<'tcx> {
418 if !infcx.tcx.is_lang_item(obligation.predicate.def_id(), LangItem::MetaSized)
419 || !infcx.tcx.is_lang_item(candidate.def_id(), LangItem::Sized)
420 {
421 return candidate;
422 }
423
424 if obligation.predicate.polarity() != PredicatePolarity::Positive
425 || candidate.polarity() != PredicatePolarity::Positive
426 {
427 return candidate;
428 }
429
430 let drcx = DeepRejectCtxt::relate_rigid_rigid(infcx.tcx);
431 if !drcx.args_may_unify(
432 obligation.predicate.skip_binder().trait_ref.args,
433 candidate.skip_binder().trait_ref.args,
434 ) {
435 return candidate;
436 }
437
438 candidate.map_bound(|c| TraitPredicate {
439 trait_ref: TraitRef::new_from_args(
440 infcx.tcx,
441 obligation.predicate.def_id(),
442 c.trait_ref.args,
443 ),
444 polarity: c.polarity,
445 })
446}