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