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