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;
15use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable};
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        match self.kind() {
150            ty::FnPtr(sig_tys, hdr) => sig_tys.with(hdr),
151            ty::FnDef(def_id, args) => interner.fn_sig(def_id).instantiate(interner, args),
152            ty::Error(_) => {
153                // ignore errors (#54954)
154                ty::Binder::dummy(ty::FnSig {
155                    inputs_and_output: Default::default(),
156                    c_variadic: false,
157                    safety: I::Safety::safe(),
158                    abi: I::Abi::rust(),
159                })
160            }
161            ty::Closure(..) => panic!(
162                "to get the signature of a closure, use `args.as_closure().sig()` not `fn_sig()`",
163            ),
164            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self),
165        }
166    }
167
168    fn discriminant_ty(self, interner: I) -> I::Ty;
169
170    fn async_destructor_ty(self, interner: I) -> I::Ty;
171
172    /// Returns `true` when the outermost type cannot be further normalized,
173    /// resolved, or instantiated. This includes all primitive types, but also
174    /// things like ADTs and trait objects, since even if their arguments or
175    /// nested types may be further simplified, the outermost [`ty::TyKind`] or
176    /// type constructor remains the same.
177    fn is_known_rigid(self) -> bool {
178        match self.kind() {
179            ty::Bool
180            | ty::Char
181            | ty::Int(_)
182            | ty::Uint(_)
183            | ty::Float(_)
184            | ty::Adt(_, _)
185            | ty::Foreign(_)
186            | ty::Str
187            | ty::Array(_, _)
188            | ty::Pat(_, _)
189            | ty::Slice(_)
190            | ty::RawPtr(_, _)
191            | ty::Ref(_, _, _)
192            | ty::FnDef(_, _)
193            | ty::FnPtr(..)
194            | ty::UnsafeBinder(_)
195            | ty::Dynamic(_, _, _)
196            | ty::Closure(_, _)
197            | ty::CoroutineClosure(_, _)
198            | ty::Coroutine(_, _)
199            | ty::CoroutineWitness(..)
200            | ty::Never
201            | ty::Tuple(_) => true,
202
203            ty::Error(_)
204            | ty::Infer(_)
205            | ty::Alias(_, _)
206            | ty::Param(_)
207            | ty::Bound(_, _)
208            | ty::Placeholder(_) => false,
209        }
210    }
211}
212
213pub trait Tys<I: Interner<Tys = Self>>:
214    Copy + Debug + Hash + Eq + SliceLike<Item = I::Ty> + TypeFoldable<I> + Default
215{
216    fn inputs(self) -> I::FnInputTys;
217
218    fn output(self) -> I::Ty;
219}
220
221pub trait Abi<I: Interner<Abi = Self>>: Copy + Debug + Hash + Eq {
222    fn rust() -> Self;
223
224    /// Whether this ABI is `extern "Rust"`.
225    fn is_rust(self) -> bool;
226}
227
228pub trait Safety<I: Interner<Safety = Self>>: Copy + Debug + Hash + Eq {
229    fn safe() -> Self;
230
231    fn is_safe(self) -> bool;
232
233    fn prefix_str(self) -> &'static str;
234}
235
236pub trait Region<I: Interner<Region = Self>>:
237    Copy
238    + Debug
239    + Hash
240    + Eq
241    + Into<I::GenericArg>
242    + IntoKind<Kind = ty::RegionKind<I>>
243    + Flags
244    + Relate<I>
245{
246    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundRegion) -> Self;
247
248    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
249
250    fn new_static(interner: I) -> Self;
251
252    fn is_bound(self) -> bool {
253        matches!(self.kind(), ty::ReBound(..))
254    }
255}
256
257pub trait Const<I: Interner<Const = Self>>:
258    Copy
259    + Debug
260    + Hash
261    + Eq
262    + Into<I::GenericArg>
263    + Into<I::Term>
264    + IntoKind<Kind = ty::ConstKind<I>>
265    + TypeSuperVisitable<I>
266    + TypeSuperFoldable<I>
267    + Relate<I>
268    + Flags
269{
270    fn new_infer(interner: I, var: ty::InferConst) -> Self;
271
272    fn new_var(interner: I, var: ty::ConstVid) -> Self;
273
274    fn new_bound(interner: I, debruijn: ty::DebruijnIndex, var: I::BoundConst) -> Self;
275
276    fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self;
277
278    fn new_unevaluated(interner: I, uv: ty::UnevaluatedConst<I>) -> Self;
279
280    fn new_expr(interner: I, expr: I::ExprConst) -> Self;
281
282    fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self;
283
284    fn new_error_with_message(interner: I, msg: impl ToString) -> Self {
285        Self::new_error(interner, interner.delay_bug(msg))
286    }
287
288    fn is_ct_var(self) -> bool {
289        matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_)))
290    }
291
292    fn is_ct_error(self) -> bool {
293        matches!(self.kind(), ty::ConstKind::Error(_))
294    }
295}
296
297pub trait ValueConst<I: Interner<ValueConst = Self>>: Copy + Debug + Hash + Eq {
298    fn ty(self) -> I::Ty;
299    fn valtree(self) -> I::ValTree;
300}
301
302pub trait ExprConst<I: Interner<ExprConst = Self>>: Copy + Debug + Hash + Eq + Relate<I> {
303    fn args(self) -> I::GenericArgs;
304}
305
306pub trait GenericsOf<I: Interner<GenericsOf = Self>> {
307    fn count(&self) -> usize;
308}
309
310pub trait GenericArg<I: Interner<GenericArg = Self>>:
311    Copy
312    + Debug
313    + Hash
314    + Eq
315    + IntoKind<Kind = ty::GenericArgKind<I>>
316    + TypeVisitable<I>
317    + Relate<I>
318    + From<I::Ty>
319    + From<I::Region>
320    + From<I::Const>
321{
322    fn as_type(&self) -> Option<I::Ty> {
323        if let ty::GenericArgKind::Type(ty) = self.kind() { Some(ty) } else { None }
324    }
325
326    fn expect_ty(&self) -> I::Ty {
327        self.as_type().expect("expected a type")
328    }
329
330    fn as_const(&self) -> Option<I::Const> {
331        if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None }
332    }
333
334    fn expect_const(&self) -> I::Const {
335        self.as_const().expect("expected a const")
336    }
337
338    fn as_region(&self) -> Option<I::Region> {
339        if let ty::GenericArgKind::Lifetime(c) = self.kind() { Some(c) } else { None }
340    }
341
342    fn expect_region(&self) -> I::Region {
343        self.as_region().expect("expected a const")
344    }
345
346    fn is_non_region_infer(self) -> bool {
347        match self.kind() {
348            ty::GenericArgKind::Lifetime(_) => false,
349            ty::GenericArgKind::Type(ty) => ty.is_ty_var(),
350            ty::GenericArgKind::Const(ct) => ct.is_ct_var(),
351        }
352    }
353}
354
355pub trait Term<I: Interner<Term = Self>>:
356    Copy + Debug + Hash + Eq + IntoKind<Kind = ty::TermKind<I>> + TypeFoldable<I> + Relate<I>
357{
358    fn as_type(&self) -> Option<I::Ty> {
359        if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None }
360    }
361
362    fn expect_ty(&self) -> I::Ty {
363        self.as_type().expect("expected a type, but found a const")
364    }
365
366    fn as_const(&self) -> Option<I::Const> {
367        if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None }
368    }
369
370    fn expect_const(&self) -> I::Const {
371        self.as_const().expect("expected a const, but found a type")
372    }
373
374    fn is_infer(self) -> bool {
375        match self.kind() {
376            ty::TermKind::Ty(ty) => ty.is_ty_var(),
377            ty::TermKind::Const(ct) => ct.is_ct_var(),
378        }
379    }
380
381    fn is_error(self) -> bool {
382        match self.kind() {
383            ty::TermKind::Ty(ty) => ty.is_ty_error(),
384            ty::TermKind::Const(ct) => ct.is_ct_error(),
385        }
386    }
387
388    fn to_alias_term(self) -> Option<ty::AliasTerm<I>> {
389        match self.kind() {
390            ty::TermKind::Ty(ty) => match ty.kind() {
391                ty::Alias(_kind, alias_ty) => Some(alias_ty.into()),
392                _ => None,
393            },
394            ty::TermKind::Const(ct) => match ct.kind() {
395                ty::ConstKind::Unevaluated(uv) => Some(uv.into()),
396                _ => None,
397            },
398        }
399    }
400}
401
402pub trait GenericArgs<I: Interner<GenericArgs = Self>>:
403    Copy + Debug + Hash + Eq + SliceLike<Item = I::GenericArg> + Default + Relate<I>
404{
405    fn rebase_onto(
406        self,
407        interner: I,
408        source_def_id: I::DefId,
409        target: I::GenericArgs,
410    ) -> I::GenericArgs;
411
412    fn type_at(self, i: usize) -> I::Ty;
413
414    fn region_at(self, i: usize) -> I::Region;
415
416    fn const_at(self, i: usize) -> I::Const;
417
418    fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs;
419
420    fn extend_with_error(
421        interner: I,
422        def_id: I::DefId,
423        original_args: &[I::GenericArg],
424    ) -> I::GenericArgs;
425
426    fn split_closure_args(self) -> ty::ClosureArgsParts<I>;
427    fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<I>;
428    fn split_coroutine_args(self) -> ty::CoroutineArgsParts<I>;
429
430    fn as_closure(self) -> ty::ClosureArgs<I> {
431        ty::ClosureArgs { args: self }
432    }
433    fn as_coroutine_closure(self) -> ty::CoroutineClosureArgs<I> {
434        ty::CoroutineClosureArgs { args: self }
435    }
436    fn as_coroutine(self) -> ty::CoroutineArgs<I> {
437        ty::CoroutineArgs { args: self }
438    }
439}
440
441pub trait Predicate<I: Interner<Predicate = Self>>:
442    Copy
443    + Debug
444    + Hash
445    + Eq
446    + TypeSuperVisitable<I>
447    + TypeSuperFoldable<I>
448    + Flags
449    + UpcastFrom<I, ty::PredicateKind<I>>
450    + UpcastFrom<I, ty::Binder<I, ty::PredicateKind<I>>>
451    + UpcastFrom<I, ty::ClauseKind<I>>
452    + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
453    + UpcastFrom<I, I::Clause>
454    + UpcastFrom<I, ty::NormalizesTo<I>>
455    + UpcastFrom<I, ty::TraitRef<I>>
456    + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
457    + UpcastFrom<I, ty::TraitPredicate<I>>
458    + UpcastFrom<I, ty::OutlivesPredicate<I, I::Ty>>
459    + UpcastFrom<I, ty::OutlivesPredicate<I, I::Region>>
460    + IntoKind<Kind = ty::Binder<I, ty::PredicateKind<I>>>
461    + Elaboratable<I>
462{
463    fn as_clause(self) -> Option<I::Clause>;
464
465    // FIXME: Eventually uplift the impl out of rustc and make this defaulted.
466    fn allow_normalization(self) -> bool;
467}
468
469pub trait Clause<I: Interner<Clause = Self>>:
470    Copy
471    + Debug
472    + Hash
473    + Eq
474    + TypeFoldable<I>
475    + UpcastFrom<I, ty::Binder<I, ty::ClauseKind<I>>>
476    + UpcastFrom<I, ty::TraitRef<I>>
477    + UpcastFrom<I, ty::Binder<I, ty::TraitRef<I>>>
478    + UpcastFrom<I, ty::TraitPredicate<I>>
479    + UpcastFrom<I, ty::Binder<I, ty::TraitPredicate<I>>>
480    + UpcastFrom<I, ty::ProjectionPredicate<I>>
481    + UpcastFrom<I, ty::Binder<I, ty::ProjectionPredicate<I>>>
482    + IntoKind<Kind = ty::Binder<I, ty::ClauseKind<I>>>
483    + Elaboratable<I>
484{
485    fn as_predicate(self) -> I::Predicate;
486
487    fn as_trait_clause(self) -> Option<ty::Binder<I, ty::TraitPredicate<I>>> {
488        self.kind()
489            .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None })
490            .transpose()
491    }
492
493    fn as_host_effect_clause(self) -> Option<ty::Binder<I, ty::HostEffectPredicate<I>>> {
494        self.kind()
495            .map_bound(
496                |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None },
497            )
498            .transpose()
499    }
500
501    fn as_projection_clause(self) -> Option<ty::Binder<I, ty::ProjectionPredicate<I>>> {
502        self.kind()
503            .map_bound(
504                |clause| {
505                    if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None }
506                },
507            )
508            .transpose()
509    }
510
511    /// Performs a instantiation suitable for going from a
512    /// poly-trait-ref to supertraits that must hold if that
513    /// poly-trait-ref holds. This is slightly different from a normal
514    /// instantiation in terms of what happens with bound regions.
515    fn instantiate_supertrait(self, cx: I, trait_ref: ty::Binder<I, ty::TraitRef<I>>) -> Self;
516}
517
518/// Common capabilities of placeholder kinds
519pub trait PlaceholderLike: Copy + Debug + Hash + Eq {
520    fn universe(self) -> ty::UniverseIndex;
521    fn var(self) -> ty::BoundVar;
522
523    fn with_updated_universe(self, ui: ty::UniverseIndex) -> Self;
524
525    fn new(ui: ty::UniverseIndex, var: ty::BoundVar) -> Self;
526}
527
528pub trait IntoKind {
529    type Kind;
530
531    fn kind(self) -> Self::Kind;
532}
533
534pub trait BoundVarLike<I: Interner> {
535    fn var(self) -> ty::BoundVar;
536
537    fn assert_eq(self, var: I::BoundVarKind);
538}
539
540pub trait ParamLike {
541    fn index(self) -> u32;
542}
543
544pub trait AdtDef<I: Interner>: Copy + Debug + Hash + Eq {
545    fn def_id(self) -> I::DefId;
546
547    fn is_struct(self) -> bool;
548
549    /// Returns the type of the struct tail.
550    ///
551    /// Expects the `AdtDef` to be a struct. If it is not, then this will panic.
552    fn struct_tail_ty(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
553
554    fn is_phantom_data(self) -> bool;
555
556    fn is_manually_drop(self) -> bool;
557
558    // FIXME: perhaps use `all_fields` and expose `FieldDef`.
559    fn all_field_tys(self, interner: I) -> ty::EarlyBinder<I, impl IntoIterator<Item = I::Ty>>;
560
561    fn sized_constraint(self, interner: I) -> Option<ty::EarlyBinder<I, I::Ty>>;
562
563    fn is_fundamental(self) -> bool;
564
565    fn destructor(self, interner: I) -> Option<AdtDestructorKind>;
566}
567
568pub trait ParamEnv<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
569    fn caller_bounds(self) -> impl SliceLike<Item = I::Clause>;
570}
571
572pub trait Features<I: Interner>: Copy {
573    fn generic_const_exprs(self) -> bool;
574
575    fn coroutine_clone(self) -> bool;
576
577    fn associated_const_equality(self) -> bool;
578}
579
580pub trait DefId<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
581    fn is_local(self) -> bool;
582
583    fn as_local(self) -> Option<I::LocalDefId>;
584}
585
586pub trait BoundExistentialPredicates<I: Interner>:
587    Copy + Debug + Hash + Eq + Relate<I> + SliceLike<Item = ty::Binder<I, ty::ExistentialPredicate<I>>>
588{
589    fn principal_def_id(self) -> Option<I::DefId>;
590
591    fn principal(self) -> Option<ty::Binder<I, ty::ExistentialTraitRef<I>>>;
592
593    fn auto_traits(self) -> impl IntoIterator<Item = I::DefId>;
594
595    fn projection_bounds(
596        self,
597    ) -> impl IntoIterator<Item = ty::Binder<I, ty::ExistentialProjection<I>>>;
598}
599
600pub trait Span<I: Interner>: Copy + Debug + Hash + Eq + TypeFoldable<I> {
601    fn dummy() -> Self;
602}
603
604pub trait SliceLike: Sized + Copy {
605    type Item: Copy;
606    type IntoIter: Iterator<Item = Self::Item>;
607
608    fn iter(self) -> Self::IntoIter;
609
610    fn as_slice(&self) -> &[Self::Item];
611
612    fn get(self, idx: usize) -> Option<Self::Item> {
613        self.as_slice().get(idx).copied()
614    }
615
616    fn len(self) -> usize {
617        self.as_slice().len()
618    }
619
620    fn is_empty(self) -> bool {
621        self.len() == 0
622    }
623
624    fn contains(self, t: &Self::Item) -> bool
625    where
626        Self::Item: PartialEq,
627    {
628        self.as_slice().contains(t)
629    }
630
631    fn to_vec(self) -> Vec<Self::Item> {
632        self.as_slice().to_vec()
633    }
634
635    fn last(self) -> Option<Self::Item> {
636        self.as_slice().last().copied()
637    }
638
639    fn split_last(&self) -> Option<(&Self::Item, &[Self::Item])> {
640        self.as_slice().split_last()
641    }
642}
643
644impl<'a, T: Copy> SliceLike for &'a [T] {
645    type Item = T;
646    type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
647
648    fn iter(self) -> Self::IntoIter {
649        self.iter().copied()
650    }
651
652    fn as_slice(&self) -> &[Self::Item] {
653        *self
654    }
655}
656
657impl<'a, T: Copy, const N: usize> SliceLike for &'a [T; N] {
658    type Item = T;
659    type IntoIter = std::iter::Copied<std::slice::Iter<'a, T>>;
660
661    fn iter(self) -> Self::IntoIter {
662        self.into_iter().copied()
663    }
664
665    fn as_slice(&self) -> &[Self::Item] {
666        *self
667    }
668}
669
670impl<'a, S: SliceLike> SliceLike for &'a S {
671    type Item = S::Item;
672    type IntoIter = S::IntoIter;
673
674    fn iter(self) -> Self::IntoIter {
675        (*self).iter()
676    }
677
678    fn as_slice(&self) -> &[Self::Item] {
679        (*self).as_slice()
680    }
681}