1use 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 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 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
295pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
296 fn args(self) -> I::GenericArgs;
297}
298
299pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
300 fn count(&self) -> usize;
301}
302
303pub trait GenericArg<I: Interner<GenericArg = Self>>:
304 Copy
305 + Debug
306 + Hash
307 + Eq
308 + IntoKind<Kind = ty::GenericArgKind<I>>
309 + TypeVisitable<I>
310 + Relate<I>
311 + From<I::Ty>
312 + From<I::Region>
313 + From<I::Const>
314 + From<I::Term>
315{
316 fn as_term(&self) -> Option<I::Term> {
317 match self.kind() {
318 ty::GenericArgKind::Lifetime(_) => None,
319 ty::GenericArgKind::Type(ty) => Some(ty.into()),
320 ty::GenericArgKind::Const(ct) => Some(ct.into()),
321 }
322 }
323
324 fn as_type(&self) -> Option<I::Ty> {
325 if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
326 }
327
328 fn expect_ty(&self) -> I::Ty {
329 self.as_type().expect("expected a type")
330 }
331
332 fn as_const(&self) -> Option<I::Const> {
333 if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None }
334 }
335
336 fn expect_const(&self) -> I::Const {
337 self.as_const().expect("expected a const")
338 }
339
340 fn as_region(&self) -> Option<I::Region> {
341 if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None }
342 }
343
344 fn expect_region(&self) -> I::Region {
345 self.as_region().expect("expected a const")
346 }
347
348 fn is_non_region_infer(self) -> bool {
349 match self.kind() {
350 ty::GenericArgKind::Lifetime(_) => false,
351 ty::GenericArgKind::Type(ty) => ty.is_ty_var(),
352 ty::GenericArgKind::Const(ct) => ct.is_ct_var(),
353 }
354 }
355}
356
357pub trait Term<I: Interner<Term = Self>>:
358 Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
359{
360 fn as_type(&self) -> Option<I::Ty> {
361 if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
362 }
363
364 fn expect_ty(&self) -> I::Ty {
365 self.as_type().expect("expected a type, but found a const")
366 }
367
368 fn as_const(&self) -> Option<I::Const> {
369 if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
370 }
371
372 fn expect_const(&self) -> I::Const {
373 self.as_const().expect("expected a const, but found a type")
374 }
375
376 fn is_infer(self) -> bool {
377 match self.kind() {
378 ty::TermKind::Ty(ty) => ty.is_ty_var(),
379 ty::TermKind::Const(ct) => ct.is_ct_var(),
380 }
381 }
382
383 fn is_error(self) -> bool {
384 match self.kind() {
385 ty::TermKind::Ty(ty) => ty.is_ty_error(),
386 ty::TermKind::Const(ct) => ct.is_ct_error(),
387 }
388 }
389
390 fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
391 match self.kind() {
392 ty::TermKind::Ty(ty) => match ty.kind() {
393 ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
394 _ => None,
395 },
396 ty::TermKind::Const(ct) => match ct.kind() {
397 ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
398 _ => None,
399 },
400 }
401 }
402}
403
404pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
405 Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
406{
407 fn rebase_onto(
408 self,
409 interner: I,
410 source_def_id: I::DefId,
411 target: I::GenericArgs,
412 ) -> I::GenericArgs;
413
414 fn type_at(self, i: usize) -> I::Ty;
415
416 fn region_at(self, i: usize) -> I::Region;
417
418 fn const_at(self, i: usize) -> I::Const;
419
420 fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
421
422 fn extend_with_error(
423 interner: I,
424 def_id: I::DefId,
425 original_args: &[I::GenericArg],
426 ) -> I::GenericArgs;
427
428 fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
429 fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
430 fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
431
432 fn as_closure(self) -> ty::ClosureArgs<I> {
433 ty::ClosureArgs { args: self }
434 }
435 fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
436 ty::CoroutineClosureArgs { args: self }
437 }
438 fn as_coroutine(self) -> ty::CoroutineArgs<I> {
439 ty::CoroutineArgs { args: self }
440 }
441}
442
443pub trait Predicate<I: Interner<Predicate = Self>>:
444 Copy
445 + Debug
446 + Hash
447 + Eq
448 + TypeSuperVisitable<I>
449 + TypeSuperFoldable<I>
450 + Flags
451 + UpcastFrom<I, ty::PredicateKind<I>>
452 + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
453 + UpcastFrom<I, ty::ClauseKind<I>>
454 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
455 + UpcastFrom<I, I::Clause>
456 + UpcastFrom<I, ty::NormalizesTo<I>>
457 + UpcastFrom<I, ty::TraitRef<I>>
458 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
459 + UpcastFrom<I, ty::TraitPredicate<I>>
460 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
461 + UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
462 + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
463 + Elaboratable<I>
464{
465 fn as_clause(self) -> Option<I::Clause>;
466
467 fn as_normalizes_to(self) -> Option<ty::Binder<I, ty::NormalizesTo<I>>> {
468 let kind = self.kind();
469 match kind.skip_binder() {
470 ty::PredicateKind::NormalizesTo(pred) => Some(kind.rebind(pred)),
471 _ => None,
472 }
473 }
474
475 fn allow_normalization(self) -> bool;
477}
478
479pub trait Clause<I: Interner<Clause = Self>>:
480 Copy
481 + Debug
482 + Hash
483 + Eq
484 + TypeFoldable<I>
485 + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
486 + UpcastFrom<I, ty::TraitRef<I>>
487 + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
488 + UpcastFrom<I, ty::TraitPredicate<I>>
489 + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
490 + UpcastFrom<I, ty::ProjectionPredicate<I>>
491 + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
492 + IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
493 + Elaboratable<I>
494{
495 fn as_predicate(self) -> I::Predicate;
496
497 fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
498 self.kind()
499 .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
500 .transpose()
501 }
502
503 fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
504 self.kind()
505 .map_bound(
506 |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
507 )
508 .transpose()
509 }
510
511 fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
512 self.kind()
513 .map_bound(
514 |clause| {
515 if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None }
516 },
517 )
518 .transpose()
519 }
520
521 fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
526}
527
528pub trait Clauses<I: Interner<Clauses = Self>>:
529 Copy
530 + Debug
531 + Hash
532 + Eq
533 + TypeSuperVisitable<I>
534 + TypeSuperFoldable<I>
535 + Flags
536 + SliceLike<Item = I::Clause>
537{
538}
539
540pub trait PlaceholderLike<I: Interner>: Copy + Debug + Hash + Eq {
542 fn universe(self) -> ty::UniverseIndex;
543 fn var(self) -> ty::BoundVar;
544
545 type Bound: BoundVarLike<I>;
546 fn new(ui: ty::UniverseIndex, bound: Self::Bound) -> Self;
547 fn new_anon(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
548 fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
549}
550
551pub trait PlaceholderConst<I: Interner>: PlaceholderLike<I, Bound = I::BoundConst> {
552 fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty;
553}
554impl<I: Interner> PlaceholderConst<I> for I::PlaceholderConst {
555 fn find_const_ty_from_env(self, env: I::ParamEnv) -> I::Ty {
556 let mut candidates = env.caller_bounds().iter().filter_map(|clause| {
557 match clause.kind().skip_binder() {
559 ty::ClauseKind::ConstArgHasType(placeholder_ct, ty) => {
560 assert!(!(placeholder_ct, ty).has_escaping_bound_vars());
561
562 match placeholder_ct.kind() {
563 ty::ConstKind::Placeholder(placeholder_ct) if placeholder_ct == self => {
564 Some(ty)
565 }
566 _ => None,
567 }
568 }
569 _ => None,
570 }
571 });
572
573 let ty = candidates.next().unwrap_or_else(|| {
580 panic!("cannot find `{self:?}` in param-env: {env:#?}");
581 });
582 assert!(
583 candidates.next().is_none(),
584 "did not expect duplicate `ConstParamHasTy` for `{self:?}` in param-env: {env:#?}"
585 );
586 ty
587 }
588}
589
590pub trait IntoKind {
591 type Kind;
592
593 fn kind(self) -> Self::Kind;
594}
595
596pub trait BoundVarLike<I: Interner>: Copy + Debug + Hash + Eq {
597 fn var(self) -> ty::BoundVar;
598
599 fn assert_eq(self, var: I::BoundVarKind);
600}
601
602pub trait ParamLike: Copy + Debug + Hash + Eq {
603 fn index(self) -> u32;
604}
605
606pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
607 fn def_id(self) -> I::AdtId;
608
609 fn is_struct(self) -> bool;
610
611 fn struct_tail_ty(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
615
616 fn is_phantom_data(self) -> bool;
617
618 fn is_manually_drop(self) -> bool;
619
620 fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
622
623 fn sizedness_constraint(
624 self,
625 interner: I,
626 sizedness: SizedTraitKind,
627 ) -> Option<ty::EarlyBinder<I, I::Ty>>;
628
629 fn is_fundamental(self) -> bool;
630
631 fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
632}
633
634pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
635 fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
636}
637
638pub trait Features<I: Interner>: Copy {
639 fn generic_const_exprs(self) -> bool;
640
641 fn coroutine_clone(self) -> bool;
642
643 fn associated_const_equality(self) -> bool;
644
645 fn feature_bound_holds_in_crate(self, symbol: I::Symbol) -> bool;
646}
647
648pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
649 fn is_local(self) -> bool;
650
651 fn as_local(self) -> Option<I::LocalDefId>;
652}
653
654pub trait SpecificDefId<I: Interner>:
655 DefId<I> + Into<I::DefId> + TryFrom<I::DefId, Error: std::fmt::Debug>
656{
657}
658
659impl<I: Interner, T: DefId<I> + Into<I::DefId> + TryFrom<I::DefId, Error: std::fmt::Debug>>
660 SpecificDefId<I> for T
661{
662}
663
664pub trait BoundExistentialPredicates<I: Interner>:
665 Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
666{
667 fn principal_def_id(self) -> Option<I::TraitId>;
668
669 fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
670
671 fn auto_traits(self) -> impl IntoIterator<Item = I::TraitId>;
672
673 fn projection_bounds(
674 self,
675 ) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
676}
677
678pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
679 fn dummy() -> Self;
680}
681
682pub trait OpaqueTypeStorageEntries: Debug + Copy + Default {
683 fn needs_reevaluation(self, canonicalized: usize) -> bool;
687}
688
689pub trait SliceLike: Sized + Copy {
690 type Item: Copy;
691 type IntoIter: Iterator<Item = Self::Item> + DoubleEndedIterator;
692
693 fn iter(self) -> Self::IntoIter;
694
695 fn as_slice(&self) -> &[Self::Item];
696
697 fn get(self, idx: usize) -> Option<Self::Item> {
698 self.as_slice().get(idx).copied()
699 }
700
701 fn len(self) -> usize {
702 self.as_slice().len()
703 }
704
705 fn is_empty(self) -> bool {
706 self.len() == 0
707 }
708
709 fn contains(self, t: &Self::Item) -> bool
710 where
711 Self::Item: PartialEq,
712 {
713 self.as_slice().contains(t)
714 }
715
716 fn to_vec(self) -> Vec<Self::Item> {
717 self.as_slice().to_vec()
718 }
719
720 fn last(self) -> Option<Self::Item> {
721 self.as_slice().last().copied()
722 }
723
724 fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> {
725 self.as_slice().split_last()
726 }
727}
728
729impl<'a, T: Copy> SliceLike for &'a [T] {
730 type Item = T;
731 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
732
733 fn iter(self) -> Self::IntoIter {
734 self.iter().copied()
735 }
736
737 fn as_slice(&self) -> &[Self::Item] {
738 *self
739 }
740}
741
742impl<'a, T: Copy, const N: usize> SliceLike for &'a [T; N] {
743 type Item = T;
744 type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
745
746 fn iter(self) -> Self::IntoIter {
747 self.into_iter().copied()
748 }
749
750 fn as_slice(&self) -> &[Self::Item] {
751 *self
752 }
753}
754
755impl<'a, S: SliceLike> SliceLike for &'a S {
756 type Item = S::Item;
757 type IntoIter = S::IntoIter;
758
759 fn iter(self) -> Self::IntoIter {
760 (*self).iter()
761 }
762
763 fn as_slice(&self) -> &[Self::Item] {
764 (*self).as_slice()
765 }
766}