rustc_type_ir/
inherent.rs

1//! Set of traits which are used to emulate the inherent impls that are present in `rustc_middle`.
2//! It is customary to glob-import `rustc_type_ir::inherent::*` to bring all of these traits into
3//! scope when programming in interner-agnostic settings, and to avoid importing any of these
4//! directly elsewhere (i.e. specify the full path for an implementation downstream).
5
6use std::fmt::Debug;
7use std::hash::Hash;
8
9use rustc_ast_ir::Mutability;
10
11use crate::elaborate::Elaboratable;
12use crate::fold::{TypeFoldable, TypeSuperFoldable};
13use crate::relate::Relate;
14use crate::solve::{AdtDestructorKind, SizedTraitKind};
15use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt};
16use crate::{self as ty, CollectAndApply, Interner, UpcastFrom};
17
18pub trait Ty<I: Interner<Ty = Self>>:
19    Copy
20    + Debug
21    + Hash
22    + Eq
23    + Into<I::GenericArg>
24    + Into<I::Term>
25    + IntoKind<Kind = ty::TyKind<I>>
26    + TypeSuperVisitable<I>
27    + TypeSuperFoldable<I>
28    + Relate<I>
29    + Flags
30{
31    fn new_unit(interner: I) -> Self;
32
33    fn new_bool(interner: I) -> Self;
34
35    fn new_u8(interner: I) -> Self;
36
37    fn new_usize(interner: I) -> Self;
38
39    fn new_infer(interner: I, var: ty::InferTy) -> Self;
40
41    fn new_var(interner: I, var: ty::TyVid) -> Self;
42
43    fn new_param(interner: I, param: I::ParamTy) -> Self;
44
45    fn new_placeholder(interner: I, param: I::PlaceholderTy) -> Self;
46
47    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundTy) -> Self;
48
49    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
50
51    fn new_alias(interner: I, kind: ty::AliasTyKind, alias_ty: ty::AliasTy<I>) -> Self;
52
53    fn new_projection_from_args(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self {
54        Ty::new_alias(
55            interner,
56            ty::AliasTyKind::Projection,
57            ty::AliasTy::new_from_args(interner, def_id, args),
58        )
59    }
60
61    fn new_projection(
62        interner: I,
63        def_id: I::DefId,
64        args: impl IntoIterator<Item: Into<I::GenericArg>>,
65    ) -> Self {
66        Ty::new_alias(
67            interner,
68            ty::AliasTyKind::Projection,
69            ty::AliasTy::new(interner, def_id, args),
70        )
71    }
72
73    fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
74
75    fn new_adt(interner: I, adt_def: I::AdtDef, args: I::GenericArgs) -> Self;
76
77    fn new_foreign(interner: I, def_id: I::DefId) -> Self;
78
79    fn new_dynamic(
80        interner: I,
81        preds: I::BoundExistentialPredicates,
82        region: I::Region,
83        kind: ty::DynKind,
84    ) -> Self;
85
86    fn new_coroutine(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
87
88    fn new_coroutine_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
89
90    fn new_closure(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
91
92    fn new_coroutine_witness(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
93
94    fn new_ptr(interner: I, ty: Self, mutbl: Mutability) -> Self;
95
96    fn new_ref(interner: I, region: I::Region, ty: Self, mutbl: Mutability) -> Self;
97
98    fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self;
99
100    fn new_slice(interner: I, ty: Self) -> Self;
101
102    fn new_tup(interner: I, tys: &[I::Ty]) -> Self;
103
104    fn new_tup_from_iter<It, T>(interner: I, iter: It) -> T::Output
105    where
106        It: Iterator<Item = T>,
107        T: CollectAndApply<Self, Self>;
108
109    fn new_fn_def(interner: I, def_id: I::DefId, args: I::GenericArgs) -> Self;
110
111    fn new_fn_ptr(interner: I, sig: ty::Binder<I, ty::FnSig<I>>) -> Self;
112
113    fn new_pat(interner: I, ty: Self, pat: I::Pat) -> Self;
114
115    fn new_unsafe_binder(interner: I, ty: ty::Binder<I, I::Ty>) -> Self;
116
117    fn tuple_fields(self) -> I::Tys;
118
119    fn to_opt_closure_kind(self) -> Option<ty::ClosureKind>;
120
121    fn from_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
122
123    fn from_coroutine_closure_kind(interner: I, kind: ty::ClosureKind) -> Self;
124
125    fn is_ty_var(self) -> bool {
126        matches!(self.kind(), ty::Infer(ty::TyVar(_)))
127    }
128
129    fn is_ty_error(self) -> bool {
130        matches!(self.kind(), ty::Error(_))
131    }
132
133    fn is_floating_point(self) -> bool {
134        matches!(self.kind(), ty::Float(_) | ty::Infer(ty::FloatVar(_)))
135    }
136
137    fn is_integral(self) -> bool {
138        matches!(self.kind(), ty::Infer(ty::IntVar(_)) | ty::Int(_) | ty::Uint(_))
139    }
140
141    fn is_fn_ptr(self) -> bool {
142        matches!(self.kind(), ty::FnPtr(..))
143    }
144
145    /// Checks whether this type is an ADT that has unsafe fields.
146    fn has_unsafe_fields(self) -> bool;
147
148    fn fn_sig(self, interner: I) -> ty::Binder<I, ty::FnSig<I>> {
149        self.kind().fn_sig(interner)
150    }
151
152    fn discriminant_ty(self, interner: I) -> I::Ty;
153
154    fn is_known_rigid(self) -> bool {
155        self.kind().is_known_rigid()
156    }
157
158    fn is_guaranteed_unsized_raw(self) -> bool {
159        match self.kind() {
160            ty::Dynamic(_, _, ty::Dyn) | ty::Slice(_) | ty::Str => true,
161            ty::Bool
162            | ty::Char
163            | ty::Int(_)
164            | ty::Uint(_)
165            | ty::Float(_)
166            | ty::Adt(_, _)
167            | ty::Foreign(_)
168            | ty::Array(_, _)
169            | ty::Pat(_, _)
170            | ty::RawPtr(_, _)
171            | ty::Ref(_, _, _)
172            | ty::FnDef(_, _)
173            | ty::FnPtr(_, _)
174            | ty::UnsafeBinder(_)
175            | ty::Closure(_, _)
176            | ty::CoroutineClosure(_, _)
177            | ty::Coroutine(_, _)
178            | ty::CoroutineWitness(_, _)
179            | ty::Never
180            | ty::Tuple(_)
181            | ty::Alias(_, _)
182            | ty::Param(_)
183            | ty::Bound(_, _)
184            | ty::Placeholder(_)
185            | ty::Infer(_)
186            | ty::Error(_) => false,
187        }
188    }
189}
190
191pub trait Tys<I: Interner<Tys = Self>>:
192    Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
193{
194    fn inputs(self) -> I::FnInputTys;
195
196    fn output(self) -> I::Ty;
197}
198
199pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
200    fn rust() -> Self;
201
202    /// Whether this ABI is `extern "Rust"`.
203    fn is_rust(self) -> bool;
204}
205
206pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
207    fn safe() -> Self;
208
209    fn is_safe(self) -> bool;
210
211    fn prefix_str(self) -> &'static str;
212}
213
214pub trait Region<I: Interner<Region = Self>>:
215    Copy
216    + Debug
217    + Hash
218    + Eq
219    + Into<I::GenericArg>
220    + IntoKind<Kind = ty::RegionKind<I>>
221    + Flags
222    + Relate<I>
223{
224    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
225
226    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
227
228    fn new_static(interner: I) -> Self;
229
230    fn new_placeholder(interner: I, var: I::PlaceholderRegion) -> Self;
231
232    fn is_bound(self) -> bool {
233        matches!(self.kind(), ty::ReBound(..))
234    }
235}
236
237pub trait Const<I: Interner<Const = Self>>:
238    Copy
239    + Debug
240    + Hash
241    + Eq
242    + Into<I::GenericArg>
243    + Into<I::Term>
244    + IntoKind<Kind = ty::ConstKind<I>>
245    + TypeSuperVisitable<I>
246    + TypeSuperFoldable<I>
247    + Relate<I>
248    + Flags
249{
250    fn new_infer(interner: I, var: ty::InferConst) -> Self;
251
252    fn new_var(interner: I, var: ty::ConstVid) -> Self;
253
254    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
255
256    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
257
258    fn new_placeholder(interner: I, param: I::PlaceholderConst) -> Self;
259
260    fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
261
262    fn new_expr(interner: I, expr: I::ExprConst) -> Self;
263
264    fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
265
266    fn new_error_with_message(interner: I, msg: impl ToString) -> Self {
267        Self::new_error(interner, interner.delay_bug(msg))
268    }
269
270    fn is_ct_var(self) -> bool {
271        matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
272    }
273
274    fn is_ct_error(self) -> bool {
275        matches!(self.kind(), ty::ConstKind::Error(_))
276    }
277}
278
279pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
280    fn ty(self) -> I::Ty;
281    fn valtree(self) -> I::ValTree;
282}
283
284pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
285    fn args(self) -> I::GenericArgs;
286}
287
288pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
289    fn count(&self) -> usize;
290}
291
292pub trait GenericArg<I: Interner<GenericArg = Self>>:
293    Copy
294    + Debug
295    + Hash
296    + Eq
297    + IntoKind<Kind = ty::GenericArgKind<I>>
298    + TypeVisitable<I>
299    + Relate<I>
300    + From<I::Ty>
301    + From<I::Region>
302    + From<I::Const>
303    + From<I::Term>
304{
305    fn as_term(&self) -> Option<I::Term> {
306        match self.kind() {
307            ty::GenericArgKind::Lifetime(_) => None,
308            ty::GenericArgKind::Type(ty) => Some(ty.into()),
309            ty::GenericArgKind::Const(ct) => Some(ct.into()),
310        }
311    }
312
313    fn as_type(&self) -> Option<I::Ty> {
314        if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
315    }
316
317    fn expect_ty(&self) -> I::Ty {
318        self.as_type().expect("expected a type")
319    }
320
321    fn as_const(&self) -> Option<I::Const> {
322        if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None }
323    }
324
325    fn expect_const(&self) -> I::Const {
326        self.as_const().expect("expected a const")
327    }
328
329    fn as_region(&self) -> Option<I::Region> {
330        if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None }
331    }
332
333    fn expect_region(&self) -> I::Region {
334        self.as_region().expect("expected a const")
335    }
336
337    fn is_non_region_infer(self) -> bool {
338        match self.kind() {
339            ty::GenericArgKind::Lifetime(_) => false,
340            ty::GenericArgKind::Type(ty) => ty.is_ty_var(),
341            ty::GenericArgKind::Const(ct) => ct.is_ct_var(),
342        }
343    }
344}
345
346pub trait Term<I: Interner<Term = Self>>:
347    Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
348{
349    fn as_type(&self) -> Option<I::Ty> {
350        if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
351    }
352
353    fn expect_ty(&self) -> I::Ty {
354        self.as_type().expect("expected a type, but found a const")
355    }
356
357    fn as_const(&self) -> Option<I::Const> {
358        if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
359    }
360
361    fn expect_const(&self) -> I::Const {
362        self.as_const().expect("expected a const, but found a type")
363    }
364
365    fn is_infer(self) -> bool {
366        match self.kind() {
367            ty::TermKind::Ty(ty) => ty.is_ty_var(),
368            ty::TermKind::Const(ct) => ct.is_ct_var(),
369        }
370    }
371
372    fn is_error(self) -> bool {
373        match self.kind() {
374            ty::TermKind::Ty(ty) => ty.is_ty_error(),
375            ty::TermKind::Const(ct) => ct.is_ct_error(),
376        }
377    }
378
379    fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
380        match self.kind() {
381            ty::TermKind::Ty(ty) => match ty.kind() {
382                ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
383                _ => None,
384            },
385            ty::TermKind::Const(ct) => match ct.kind() {
386                ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
387                _ => None,
388            },
389        }
390    }
391}
392
393pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
394    Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
395{
396    fn rebase_onto(
397        self,
398        interner: I,
399        source_def_id: I::DefId,
400        target: I::GenericArgs,
401    ) -> I::GenericArgs;
402
403    fn type_at(self, i: usize) -> I::Ty;
404
405    fn region_at(self, i: usize) -> I::Region;
406
407    fn const_at(self, i: usize) -> I::Const;
408
409    fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
410
411    fn extend_with_error(
412        interner: I,
413        def_id: I::DefId,
414        original_args: &[I::GenericArg],
415    ) -> I::GenericArgs;
416
417    fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
418    fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
419    fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
420
421    fn as_closure(self) -> ty::ClosureArgs<I> {
422        ty::ClosureArgs { args: self }
423    }
424    fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
425        ty::CoroutineClosureArgs { args: self }
426    }
427    fn as_coroutine(self) -> ty::CoroutineArgs<I> {
428        ty::CoroutineArgs { args: self }
429    }
430}
431
432pub trait Predicate<I: Interner<Predicate = Self>>:
433    Copy
434    + Debug
435    + Hash
436    + Eq
437    + TypeSuperVisitable<I>
438    + TypeSuperFoldable<I>
439    + Flags
440    + UpcastFrom<I, ty::PredicateKind<I>>
441    + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
442    + UpcastFrom<I, ty::ClauseKind<I>>
443    + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
444    + UpcastFrom<I, I::Clause>
445    + UpcastFrom<I, ty::NormalizesTo<I>>
446    + UpcastFrom<I, ty::TraitRef<I>>
447    + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
448    + UpcastFrom<I, ty::TraitPredicate<I>>
449    + UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
450    + UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
451    + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
452    + Elaboratable<I>
453{
454    fn as_clause(self) -> Option<I::Clause>;
455
456    fn as_normalizes_to(self) -> Option<ty::Binder<I, ty::NormalizesTo<I>>> {
457        let kind = self.kind();
458        match kind.skip_binder() {
459            ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)),
460            _ => None,
461        }
462    }
463
464    // FIXME: Eventually uplift the impl out of rustc and make this defaulted.
465    fn allow_normalization(self) -> bool;
466}
467
468pub trait Clause<I: Interner<Clause = Self>>:
469    Copy
470    + Debug
471    + Hash
472    + Eq
473    + TypeFoldable<I>
474    + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
475    + UpcastFrom<I, ty::TraitRef<I>>
476    + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
477    + UpcastFrom<I, ty::TraitPredicate<I>>
478    + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
479    + UpcastFrom<I, ty::ProjectionPredicate<I>>
480    + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
481    + IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
482    + Elaboratable<I>
483{
484    fn as_predicate(self) -> I::Predicate;
485
486    fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
487        self.kind()
488            .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
489            .transpose()
490    }
491
492    fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
493        self.kind()
494            .map_bound(
495                |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
496            )
497            .transpose()
498    }
499
500    fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
501        self.kind()
502            .map_bound(
503                |clause| {
504                    if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None }
505                },
506            )
507            .transpose()
508    }
509
510    /// Performs a instantiation suitable for going from a
511    /// poly-trait-ref to supertraits that must hold if that
512    /// poly-trait-ref holds. This is slightly different from a normal
513    /// instantiation in terms of what happens with bound regions.
514    fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
515}
516
517pub trait Clauses<I: Interner<Clauses = Self>>:
518    Copy
519    + Debug
520    + Hash
521    + Eq
522    + TypeSuperVisitable<I>
523    + TypeSuperFoldable<I>
524    + Flags
525    + SliceLike<Item = I::Clause>
526{
527}
528
529/// Common capabilities of placeholder kinds
530pub trait PlaceholderLike<I: Interner>: Copy + Debug + Hash + Eq {
531    fn universe(self) -> ty::UniverseIndex;
532    fn var(self) -> ty::BoundVar;
533
534    type Bound: BoundVarLike<I>;
535    fn new(ui: ty::UniverseIndex, bound: Self::Bound) -> Self;
536    fn new_anon(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
537    fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
538}
539
540pub trait PlaceholderConst<I: Interner>: PlaceholderLike<I, Bound = I::BoundConst> {
541    fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty;
542}
543impl<I: Interner> PlaceholderConst<I> for I::PlaceholderConst {
544    fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty {
545        let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
546            // `ConstArgHasType` are never desugared to be higher ranked.
547            match clause.kind().skip_binder() {
548                ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
549                    assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
550
551                    match placeholder_ct.kind() {
552                        ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
553                            Some(ty)
554                        }
555                        _ => None,
556                    }
557                }
558                _ => None,
559            }
560        });
561
562        // N.B. it may be tempting to fix ICEs by making this function return
563        // `Option<Ty<'tcx>>` instead of `Ty<'tcx>`; however, this is generally
564        // considered to be a bandaid solution, since it hides more important
565        // underlying issues with how we construct generics and predicates of
566        // items. It's advised to fix the underlying issue rather than trying
567        // to modify this function.
568        let ty = candidates.next().unwrap_or_else(|| {
569            panic!("cannot find `{self:?}` in param-env: {env:#?}");
570        });
571        assert!(
572            candidates.next().is_none(),
573            "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}"
574        );
575        ty
576    }
577}
578
579pub trait IntoKind {
580    type Kind;
581
582    fn kind(self) -> Self::Kind;
583}
584
585pub trait BoundVarLike<I: Interner>: Copy + Debug + Hash + Eq {
586    fn var(self) -> ty::BoundVar;
587
588    fn assert_eq(self, var: I::BoundVarKind);
589}
590
591pub trait ParamLike: Copy + Debug + Hash + Eq {
592    fn index(self) -> u32;
593}
594
595pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
596    fn def_id(self) -> I::DefId;
597
598    fn is_struct(self) -> bool;
599
600    /// Returns the type of the struct tail.
601    ///
602    /// Expects the `AdtDef` to be a struct. If it is not, then this will panic.
603    fn struct_tail_ty(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
604
605    fn is_phantom_data(self) -> bool;
606
607    fn is_manually_drop(self) -> bool;
608
609    // FIXME: perhaps use `all_fields` and expose `FieldDef`.
610    fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
611
612    fn sizedness_constraint(
613        self,
614        interner: I,
615        sizedness: SizedTraitKind,
616    ) -> Option<ty::EarlyBinder<I, I::Ty>>;
617
618    fn is_fundamental(self) -> bool;
619
620    fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
621}
622
623pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
624    fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
625}
626
627pub trait Features<I: Interner>: Copy {
628    fn generic_const_exprs(self) -> bool;
629
630    fn coroutine_clone(self) -> bool;
631
632    fn associated_const_equality(self) -> bool;
633}
634
635pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
636    fn is_local(self) -> bool;
637
638    fn as_local(self) -> Option<I::LocalDefId>;
639}
640
641pub trait BoundExistentialPredicates<I: Interner>:
642    Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
643{
644    fn principal_def_id(self) -> Option<I::DefId>;
645
646    fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
647
648    fn auto_traits(self) -> impl IntoIterator<Item = I::DefId>;
649
650    fn projection_bounds(
651        self,
652    ) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
653}
654
655pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
656    fn dummy() -> Self;
657}
658
659pub trait OpaqueTypeStorageEntries: Debug + Copy + Default {
660    /// Whether the number of opaques has changed in a way that necessitates
661    /// reevaluating a goal. For now, this is only when the number of non-duplicated
662    /// entries changed.
663    fn needs_reevaluation(self, canonicalized: usize) -> bool;
664}
665
666pub trait SliceLike: Sized + Copy {
667    type Item: Copy;
668    type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator;
669
670    fn iter(self) -> Self::IntoIter;
671
672    fn as_slice(&self) -> &[Self::Item];
673
674    fn get(self, idx: usize) -> Option<Self::Item> {
675        self.as_slice().get(idx).copied()
676    }
677
678    fn len(self) -> usize {
679        self.as_slice().len()
680    }
681
682    fn is_empty(self) -> bool {
683        self.len() == 0
684    }
685
686    fn contains(self, t: &Self::Item) -> bool
687    where
688        Self::Item: PartialEq,
689    {
690        self.as_slice().contains(t)
691    }
692
693    fn to_vec(self) -> Vec<Self::Item> {
694        self.as_slice().to_vec()
695    }
696
697    fn last(self) -> Option<Self::Item> {
698        self.as_slice().last().copied()
699    }
700
701    fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> {
702        self.as_slice().split_last()
703    }
704}
705
706impl<'a, T: Copy> SliceLike for &'a [T] {
707    type Item = T;
708    type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
709
710    fn iter(self) -> Self::IntoIter {
711        self.iter().copied()
712    }
713
714    fn as_slice(&self) -> &[Self::Item] {
715        *self
716    }
717}
718
719impl<'a, T: Copy, const N: usize> SliceLike for &'a [T; N] {
720    type Item = T;
721    type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
722
723    fn iter(self) -> Self::IntoIter {
724        self.into_iter().copied()
725    }
726
727    fn as_slice(&self) -> &[Self::Item] {
728        *self
729    }
730}
731
732impl<'a, S: SliceLike> SliceLike for &'a S {
733    type Item = S::Item;
734    type IntoIter = S::IntoIter;
735
736    fn iter(self) -> Self::IntoIter {
737        (*self).iter()
738    }
739
740    fn as_slice(&self) -> &[Self::Item] {
741        (*self).as_slice()
742    }
743}