rustc_middle/ty/
generic_args.rs

1// Generic arguments.
2
3use core::intrinsics;
4use std::marker::PhantomData;
5use std::num::NonZero;
6use std::ptr::NonNull;
7
8use rustc_data_structures::intern::Interned;
9use rustc_errors::{DiagArgValue, IntoDiagArg};
10use rustc_hir::def_id::DefId;
11use rustc_macros::{HashStable, TyDecodable, TyEncodable, extension};
12use rustc_serialize::{Decodable, Encodable};
13use rustc_type_ir::WithCachedTypeInfo;
14use smallvec::SmallVec;
15
16use crate::ty::codec::{TyDecoder, TyEncoder};
17use crate::ty::{
18    self, ClosureArgs, CoroutineArgs, CoroutineClosureArgs, FallibleTypeFolder, InlineConstArgs,
19    Lift, List, Ty, TyCtxt, TypeFoldable, TypeVisitable, TypeVisitor, VisitorResult,
20    walk_visitable_list,
21};
22
23pub type GenericArgKind<'tcx> = rustc_type_ir::GenericArgKind<TyCtxt<'tcx>>;
24pub type TermKind<'tcx> = rustc_type_ir::TermKind<TyCtxt<'tcx>>;
25
26/// An entity in the Rust type system, which can be one of
27/// several kinds (types, lifetimes, and consts).
28/// To reduce memory usage, a `GenericArg` is an interned pointer,
29/// with the lowest 2 bits being reserved for a tag to
30/// indicate the type (`Ty`, `Region`, or `Const`) it points to.
31///
32/// Note: the `PartialEq`, `Eq` and `Hash` derives are only valid because `Ty`,
33/// `Region` and `Const` are all interned.
34#[derive(Copy, Clone, PartialEq, Eq, Hash)]
35pub struct GenericArg<'tcx> {
36    ptr: NonNull<()>,
37    marker: PhantomData<(Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>)>,
38}
39
40impl<'tcx> rustc_type_ir::inherent::GenericArg<TyCtxt<'tcx>> for GenericArg<'tcx> {}
41
42impl<'tcx> rustc_type_ir::inherent::GenericArgs<TyCtxt<'tcx>> for ty::GenericArgsRef<'tcx> {
43    fn rebase_onto(
44        self,
45        tcx: TyCtxt<'tcx>,
46        source_ancestor: DefId,
47        target_args: GenericArgsRef<'tcx>,
48    ) -> GenericArgsRef<'tcx> {
49        self.rebase_onto(tcx, source_ancestor, target_args)
50    }
51
52    fn type_at(self, i: usize) -> Ty<'tcx> {
53        self.type_at(i)
54    }
55
56    fn region_at(self, i: usize) -> ty::Region<'tcx> {
57        self.region_at(i)
58    }
59
60    fn const_at(self, i: usize) -> ty::Const<'tcx> {
61        self.const_at(i)
62    }
63
64    fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: DefId) -> ty::GenericArgsRef<'tcx> {
65        GenericArgs::identity_for_item(tcx, def_id)
66    }
67
68    fn extend_with_error(
69        tcx: TyCtxt<'tcx>,
70        def_id: DefId,
71        original_args: &[ty::GenericArg<'tcx>],
72    ) -> ty::GenericArgsRef<'tcx> {
73        ty::GenericArgs::extend_with_error(tcx, def_id, original_args)
74    }
75
76    fn split_closure_args(self) -> ty::ClosureArgsParts<TyCtxt<'tcx>> {
77        match self[..] {
78            [ref parent_args @ .., closure_kind_ty, closure_sig_as_fn_ptr_ty, tupled_upvars_ty] => {
79                ty::ClosureArgsParts {
80                    parent_args,
81                    closure_kind_ty: closure_kind_ty.expect_ty(),
82                    closure_sig_as_fn_ptr_ty: closure_sig_as_fn_ptr_ty.expect_ty(),
83                    tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
84                }
85            }
86            _ => bug!("closure args missing synthetics"),
87        }
88    }
89
90    fn split_coroutine_closure_args(self) -> ty::CoroutineClosureArgsParts<TyCtxt<'tcx>> {
91        match self[..] {
92            [
93                ref parent_args @ ..,
94                closure_kind_ty,
95                signature_parts_ty,
96                tupled_upvars_ty,
97                coroutine_captures_by_ref_ty,
98                coroutine_witness_ty,
99            ] => ty::CoroutineClosureArgsParts {
100                parent_args,
101                closure_kind_ty: closure_kind_ty.expect_ty(),
102                signature_parts_ty: signature_parts_ty.expect_ty(),
103                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
104                coroutine_captures_by_ref_ty: coroutine_captures_by_ref_ty.expect_ty(),
105                coroutine_witness_ty: coroutine_witness_ty.expect_ty(),
106            },
107            _ => bug!("closure args missing synthetics"),
108        }
109    }
110
111    fn split_coroutine_args(self) -> ty::CoroutineArgsParts<TyCtxt<'tcx>> {
112        match self[..] {
113            [
114                ref parent_args @ ..,
115                kind_ty,
116                resume_ty,
117                yield_ty,
118                return_ty,
119                witness,
120                tupled_upvars_ty,
121            ] => ty::CoroutineArgsParts {
122                parent_args,
123                kind_ty: kind_ty.expect_ty(),
124                resume_ty: resume_ty.expect_ty(),
125                yield_ty: yield_ty.expect_ty(),
126                return_ty: return_ty.expect_ty(),
127                witness: witness.expect_ty(),
128                tupled_upvars_ty: tupled_upvars_ty.expect_ty(),
129            },
130            _ => bug!("coroutine args missing synthetics"),
131        }
132    }
133}
134
135impl<'tcx> rustc_type_ir::inherent::IntoKind for GenericArg<'tcx> {
136    type Kind = GenericArgKind<'tcx>;
137
138    fn kind(self) -> Self::Kind {
139        self.unpack()
140    }
141}
142
143unsafe impl<'tcx> rustc_data_structures::sync::DynSend for GenericArg<'tcx> where
144    &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSend
145{
146}
147unsafe impl<'tcx> rustc_data_structures::sync::DynSync for GenericArg<'tcx> where
148    &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): rustc_data_structures::sync::DynSync
149{
150}
151unsafe impl<'tcx> Send for GenericArg<'tcx> where
152    &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Send
153{
154}
155unsafe impl<'tcx> Sync for GenericArg<'tcx> where
156    &'tcx (Ty<'tcx>, ty::Region<'tcx>, ty::Const<'tcx>): Sync
157{
158}
159
160impl<'tcx> IntoDiagArg for GenericArg<'tcx> {
161    fn into_diag_arg(self, _: &mut Option<std::path::PathBuf>) -> DiagArgValue {
162        self.to_string().into_diag_arg(&mut None)
163    }
164}
165
166const TAG_MASK: usize = 0b11;
167const TYPE_TAG: usize = 0b00;
168const REGION_TAG: usize = 0b01;
169const CONST_TAG: usize = 0b10;
170
171#[extension(trait GenericArgPackExt<'tcx>)]
172impl<'tcx> GenericArgKind<'tcx> {
173    #[inline]
174    fn pack(self) -> GenericArg<'tcx> {
175        let (tag, ptr) = match self {
176            GenericArgKind::Lifetime(lt) => {
177                // Ensure we can use the tag bits.
178                assert_eq!(align_of_val(&*lt.0.0) & TAG_MASK, 0);
179                (REGION_TAG, NonNull::from(lt.0.0).cast())
180            }
181            GenericArgKind::Type(ty) => {
182                // Ensure we can use the tag bits.
183                assert_eq!(align_of_val(&*ty.0.0) & TAG_MASK, 0);
184                (TYPE_TAG, NonNull::from(ty.0.0).cast())
185            }
186            GenericArgKind::Const(ct) => {
187                // Ensure we can use the tag bits.
188                assert_eq!(align_of_val(&*ct.0.0) & TAG_MASK, 0);
189                (CONST_TAG, NonNull::from(ct.0.0).cast())
190            }
191        };
192
193        GenericArg { ptr: ptr.map_addr(|addr| addr | tag), marker: PhantomData }
194    }
195}
196
197impl<'tcx> From<ty::Region<'tcx>> for GenericArg<'tcx> {
198    #[inline]
199    fn from(r: ty::Region<'tcx>) -> GenericArg<'tcx> {
200        GenericArgKind::Lifetime(r).pack()
201    }
202}
203
204impl<'tcx> From<Ty<'tcx>> for GenericArg<'tcx> {
205    #[inline]
206    fn from(ty: Ty<'tcx>) -> GenericArg<'tcx> {
207        GenericArgKind::Type(ty).pack()
208    }
209}
210
211impl<'tcx> From<ty::Const<'tcx>> for GenericArg<'tcx> {
212    #[inline]
213    fn from(c: ty::Const<'tcx>) -> GenericArg<'tcx> {
214        GenericArgKind::Const(c).pack()
215    }
216}
217
218impl<'tcx> From<ty::Term<'tcx>> for GenericArg<'tcx> {
219    fn from(value: ty::Term<'tcx>) -> Self {
220        match value.unpack() {
221            ty::TermKind::Ty(t) => t.into(),
222            ty::TermKind::Const(c) => c.into(),
223        }
224    }
225}
226
227impl<'tcx> GenericArg<'tcx> {
228    #[inline]
229    pub fn unpack(self) -> GenericArgKind<'tcx> {
230        let ptr =
231            unsafe { self.ptr.map_addr(|addr| NonZero::new_unchecked(addr.get() & !TAG_MASK)) };
232        // SAFETY: use of `Interned::new_unchecked` here is ok because these
233        // pointers were originally created from `Interned` types in `pack()`,
234        // and this is just going in the other direction.
235        unsafe {
236            match self.ptr.addr().get() & TAG_MASK {
237                REGION_TAG => GenericArgKind::Lifetime(ty::Region(Interned::new_unchecked(
238                    ptr.cast::<ty::RegionKind<'tcx>>().as_ref(),
239                ))),
240                TYPE_TAG => GenericArgKind::Type(Ty(Interned::new_unchecked(
241                    ptr.cast::<WithCachedTypeInfo<ty::TyKind<'tcx>>>().as_ref(),
242                ))),
243                CONST_TAG => GenericArgKind::Const(ty::Const(Interned::new_unchecked(
244                    ptr.cast::<WithCachedTypeInfo<ty::ConstKind<'tcx>>>().as_ref(),
245                ))),
246                _ => intrinsics::unreachable(),
247            }
248        }
249    }
250
251    #[inline]
252    pub fn as_type(self) -> Option<Ty<'tcx>> {
253        match self.unpack() {
254            GenericArgKind::Type(ty) => Some(ty),
255            _ => None,
256        }
257    }
258
259    #[inline]
260    pub fn as_region(self) -> Option<ty::Region<'tcx>> {
261        match self.unpack() {
262            GenericArgKind::Lifetime(re) => Some(re),
263            _ => None,
264        }
265    }
266
267    #[inline]
268    pub fn as_const(self) -> Option<ty::Const<'tcx>> {
269        match self.unpack() {
270            GenericArgKind::Const(ct) => Some(ct),
271            _ => None,
272        }
273    }
274
275    /// Unpack the `GenericArg` as a region when it is known certainly to be a region.
276    pub fn expect_region(self) -> ty::Region<'tcx> {
277        self.as_region().unwrap_or_else(|| bug!("expected a region, but found another kind"))
278    }
279
280    /// Unpack the `GenericArg` as a type when it is known certainly to be a type.
281    /// This is true in cases where `GenericArgs` is used in places where the kinds are known
282    /// to be limited (e.g. in tuples, where the only parameters are type parameters).
283    pub fn expect_ty(self) -> Ty<'tcx> {
284        self.as_type().unwrap_or_else(|| bug!("expected a type, but found another kind"))
285    }
286
287    /// Unpack the `GenericArg` as a const when it is known certainly to be a const.
288    pub fn expect_const(self) -> ty::Const<'tcx> {
289        self.as_const().unwrap_or_else(|| bug!("expected a const, but found another kind"))
290    }
291
292    pub fn is_non_region_infer(self) -> bool {
293        match self.unpack() {
294            GenericArgKind::Lifetime(_) => false,
295            // FIXME: This shouldn't return numerical/float.
296            GenericArgKind::Type(ty) => ty.is_ty_or_numeric_infer(),
297            GenericArgKind::Const(ct) => ct.is_ct_infer(),
298        }
299    }
300}
301
302impl<'a, 'tcx> Lift<TyCtxt<'tcx>> for GenericArg<'a> {
303    type Lifted = GenericArg<'tcx>;
304
305    fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Option<Self::Lifted> {
306        match self.unpack() {
307            GenericArgKind::Lifetime(lt) => tcx.lift(lt).map(|lt| lt.into()),
308            GenericArgKind::Type(ty) => tcx.lift(ty).map(|ty| ty.into()),
309            GenericArgKind::Const(ct) => tcx.lift(ct).map(|ct| ct.into()),
310        }
311    }
312}
313
314impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArg<'tcx> {
315    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
316        self,
317        folder: &mut F,
318    ) -> Result<Self, F::Error> {
319        match self.unpack() {
320            GenericArgKind::Lifetime(lt) => lt.try_fold_with(folder).map(Into::into),
321            GenericArgKind::Type(ty) => ty.try_fold_with(folder).map(Into::into),
322            GenericArgKind::Const(ct) => ct.try_fold_with(folder).map(Into::into),
323        }
324    }
325}
326
327impl<'tcx> TypeVisitable<TyCtxt<'tcx>> for GenericArg<'tcx> {
328    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
329        match self.unpack() {
330            GenericArgKind::Lifetime(lt) => lt.visit_with(visitor),
331            GenericArgKind::Type(ty) => ty.visit_with(visitor),
332            GenericArgKind::Const(ct) => ct.visit_with(visitor),
333        }
334    }
335}
336
337impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for GenericArg<'tcx> {
338    fn encode(&self, e: &mut E) {
339        self.unpack().encode(e)
340    }
341}
342
343impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArg<'tcx> {
344    fn decode(d: &mut D) -> GenericArg<'tcx> {
345        GenericArgKind::decode(d).pack()
346    }
347}
348
349/// List of generic arguments that are gonna be used to replace generic parameters.
350pub type GenericArgs<'tcx> = List<GenericArg<'tcx>>;
351
352pub type GenericArgsRef<'tcx> = &'tcx GenericArgs<'tcx>;
353
354impl<'tcx> GenericArgs<'tcx> {
355    /// Converts generic args to a type list.
356    ///
357    /// # Panics
358    ///
359    /// If any of the generic arguments are not types.
360    pub fn into_type_list(&self, tcx: TyCtxt<'tcx>) -> &'tcx List<Ty<'tcx>> {
361        tcx.mk_type_list_from_iter(self.iter().map(|arg| match arg.unpack() {
362            GenericArgKind::Type(ty) => ty,
363            _ => bug!("`into_type_list` called on generic arg with non-types"),
364        }))
365    }
366
367    /// Interpret these generic args as the args of a closure type.
368    /// Closure args have a particular structure controlled by the
369    /// compiler that encodes information like the signature and closure kind;
370    /// see `ty::ClosureArgs` struct for more comments.
371    pub fn as_closure(&'tcx self) -> ClosureArgs<TyCtxt<'tcx>> {
372        ClosureArgs { args: self }
373    }
374
375    /// Interpret these generic args as the args of a coroutine-closure type.
376    /// Coroutine-closure args have a particular structure controlled by the
377    /// compiler that encodes information like the signature and closure kind;
378    /// see `ty::CoroutineClosureArgs` struct for more comments.
379    pub fn as_coroutine_closure(&'tcx self) -> CoroutineClosureArgs<TyCtxt<'tcx>> {
380        CoroutineClosureArgs { args: self }
381    }
382
383    /// Interpret these generic args as the args of a coroutine type.
384    /// Coroutine args have a particular structure controlled by the
385    /// compiler that encodes information like the signature and coroutine kind;
386    /// see `ty::CoroutineArgs` struct for more comments.
387    pub fn as_coroutine(&'tcx self) -> CoroutineArgs<TyCtxt<'tcx>> {
388        CoroutineArgs { args: self }
389    }
390
391    /// Interpret these generic args as the args of an inline const.
392    /// Inline const args have a particular structure controlled by the
393    /// compiler that encodes information like the inferred type;
394    /// see `ty::InlineConstArgs` struct for more comments.
395    pub fn as_inline_const(&'tcx self) -> InlineConstArgs<'tcx> {
396        InlineConstArgs { args: self }
397    }
398
399    /// Creates an `GenericArgs` that maps each generic parameter to itself.
400    pub fn identity_for_item(tcx: TyCtxt<'tcx>, def_id: impl Into<DefId>) -> GenericArgsRef<'tcx> {
401        Self::for_item(tcx, def_id.into(), |param, _| tcx.mk_param_from_def(param))
402    }
403
404    /// Creates an `GenericArgs` for generic parameter definitions,
405    /// by calling closures to obtain each kind.
406    /// The closures get to observe the `GenericArgs` as they're
407    /// being built, which can be used to correctly
408    /// replace defaults of generic parameters.
409    pub fn for_item<F>(tcx: TyCtxt<'tcx>, def_id: DefId, mut mk_kind: F) -> GenericArgsRef<'tcx>
410    where
411        F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
412    {
413        let defs = tcx.generics_of(def_id);
414        let count = defs.count();
415        let mut args = SmallVec::with_capacity(count);
416        Self::fill_item(&mut args, tcx, defs, &mut mk_kind);
417        tcx.mk_args(&args)
418    }
419
420    pub fn extend_to<F>(
421        &self,
422        tcx: TyCtxt<'tcx>,
423        def_id: DefId,
424        mut mk_kind: F,
425    ) -> GenericArgsRef<'tcx>
426    where
427        F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
428    {
429        Self::for_item(tcx, def_id, |param, args| {
430            self.get(param.index as usize).cloned().unwrap_or_else(|| mk_kind(param, args))
431        })
432    }
433
434    pub fn fill_item<F>(
435        args: &mut SmallVec<[GenericArg<'tcx>; 8]>,
436        tcx: TyCtxt<'tcx>,
437        defs: &ty::Generics,
438        mk_kind: &mut F,
439    ) where
440        F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
441    {
442        if let Some(def_id) = defs.parent {
443            let parent_defs = tcx.generics_of(def_id);
444            Self::fill_item(args, tcx, parent_defs, mk_kind);
445        }
446        Self::fill_single(args, defs, mk_kind)
447    }
448
449    pub fn fill_single<F>(
450        args: &mut SmallVec<[GenericArg<'tcx>; 8]>,
451        defs: &ty::Generics,
452        mk_kind: &mut F,
453    ) where
454        F: FnMut(&ty::GenericParamDef, &[GenericArg<'tcx>]) -> GenericArg<'tcx>,
455    {
456        args.reserve(defs.own_params.len());
457        for param in &defs.own_params {
458            let kind = mk_kind(param, args);
459            assert_eq!(param.index as usize, args.len(), "{args:#?}, {defs:#?}");
460            args.push(kind);
461        }
462    }
463
464    // Extend an `original_args` list to the full number of args expected by `def_id`,
465    // filling in the missing parameters with error ty/ct or 'static regions.
466    pub fn extend_with_error(
467        tcx: TyCtxt<'tcx>,
468        def_id: DefId,
469        original_args: &[GenericArg<'tcx>],
470    ) -> GenericArgsRef<'tcx> {
471        ty::GenericArgs::for_item(tcx, def_id, |def, _| {
472            if let Some(arg) = original_args.get(def.index as usize) {
473                *arg
474            } else {
475                def.to_error(tcx)
476            }
477        })
478    }
479
480    #[inline]
481    pub fn types(&self) -> impl DoubleEndedIterator<Item = Ty<'tcx>> {
482        self.iter().filter_map(|k| k.as_type())
483    }
484
485    #[inline]
486    pub fn regions(&self) -> impl DoubleEndedIterator<Item = ty::Region<'tcx>> {
487        self.iter().filter_map(|k| k.as_region())
488    }
489
490    #[inline]
491    pub fn consts(&self) -> impl DoubleEndedIterator<Item = ty::Const<'tcx>> {
492        self.iter().filter_map(|k| k.as_const())
493    }
494
495    /// Returns generic arguments that are not lifetimes.
496    #[inline]
497    pub fn non_erasable_generics(&self) -> impl DoubleEndedIterator<Item = GenericArgKind<'tcx>> {
498        self.iter().filter_map(|k| match k.unpack() {
499            ty::GenericArgKind::Lifetime(_) => None,
500            generic => Some(generic),
501        })
502    }
503
504    #[inline]
505    #[track_caller]
506    pub fn type_at(&self, i: usize) -> Ty<'tcx> {
507        self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
508    }
509
510    #[inline]
511    #[track_caller]
512    pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
513        self[i]
514            .as_region()
515            .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
516    }
517
518    #[inline]
519    #[track_caller]
520    pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
521        self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
522    }
523
524    #[inline]
525    #[track_caller]
526    pub fn type_for_def(&self, def: &ty::GenericParamDef) -> GenericArg<'tcx> {
527        self.type_at(def.index as usize).into()
528    }
529
530    /// Transform from generic args for a child of `source_ancestor`
531    /// (e.g., a trait or impl) to args for the same child
532    /// in a different item, with `target_args` as the base for
533    /// the target impl/trait, with the source child-specific
534    /// parameters (e.g., method parameters) on top of that base.
535    ///
536    /// For example given:
537    ///
538    /// ```no_run
539    /// trait X<S> { fn f<T>(); }
540    /// impl<U> X<U> for U { fn f<V>() {} }
541    /// ```
542    ///
543    /// * If `self` is `[Self, S, T]`: the identity args of `f` in the trait.
544    /// * If `source_ancestor` is the def_id of the trait.
545    /// * If `target_args` is `[U]`, the args for the impl.
546    /// * Then we will return `[U, T]`, the arg for `f` in the impl that
547    ///   are needed for it to match the trait.
548    pub fn rebase_onto(
549        &self,
550        tcx: TyCtxt<'tcx>,
551        source_ancestor: DefId,
552        target_args: GenericArgsRef<'tcx>,
553    ) -> GenericArgsRef<'tcx> {
554        let defs = tcx.generics_of(source_ancestor);
555        tcx.mk_args_from_iter(target_args.iter().chain(self.iter().skip(defs.count())))
556    }
557
558    pub fn truncate_to(&self, tcx: TyCtxt<'tcx>, generics: &ty::Generics) -> GenericArgsRef<'tcx> {
559        tcx.mk_args_from_iter(self.iter().take(generics.count()))
560    }
561
562    pub fn print_as_list(&self) -> String {
563        let v = self.iter().map(|arg| arg.to_string()).collect::<Vec<_>>();
564        format!("[{}]", v.join(", "))
565    }
566}
567
568impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for GenericArgsRef<'tcx> {
569    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
570        self,
571        folder: &mut F,
572    ) -> Result<Self, F::Error> {
573        // This code is hot enough that it's worth specializing for the most
574        // common length lists, to avoid the overhead of `SmallVec` creation.
575        // The match arms are in order of frequency. The 1, 2, and 0 cases are
576        // typically hit in 90--99.99% of cases. When folding doesn't change
577        // the args, it's faster to reuse the existing args rather than
578        // calling `mk_args`.
579        match self.len() {
580            1 => {
581                let param0 = self[0].try_fold_with(folder)?;
582                if param0 == self[0] { Ok(self) } else { Ok(folder.cx().mk_args(&[param0])) }
583            }
584            2 => {
585                let param0 = self[0].try_fold_with(folder)?;
586                let param1 = self[1].try_fold_with(folder)?;
587                if param0 == self[0] && param1 == self[1] {
588                    Ok(self)
589                } else {
590                    Ok(folder.cx().mk_args(&[param0, param1]))
591                }
592            }
593            0 => Ok(self),
594            _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_args(v)),
595        }
596    }
597}
598
599impl<'tcx> TypeFoldable<TyCtxt<'tcx>> for &'tcx ty::List<Ty<'tcx>> {
600    fn try_fold_with<F: FallibleTypeFolder<TyCtxt<'tcx>>>(
601        self,
602        folder: &mut F,
603    ) -> Result<Self, F::Error> {
604        // This code is fairly hot, though not as hot as `GenericArgsRef`.
605        //
606        // When compiling stage 2, I get the following results:
607        //
608        // len |   total   |   %
609        // --- | --------- | -----
610        //  2  |  15083590 |  48.1
611        //  3  |   7540067 |  24.0
612        //  1  |   5300377 |  16.9
613        //  4  |   1351897 |   4.3
614        //  0  |   1256849 |   4.0
615        //
616        // I've tried it with some private repositories and got
617        // close to the same result, with 4 and 0 swapping places
618        // sometimes.
619        match self.len() {
620            2 => {
621                let param0 = self[0].try_fold_with(folder)?;
622                let param1 = self[1].try_fold_with(folder)?;
623                if param0 == self[0] && param1 == self[1] {
624                    Ok(self)
625                } else {
626                    Ok(folder.cx().mk_type_list(&[param0, param1]))
627                }
628            }
629            _ => ty::util::fold_list(self, folder, |tcx, v| tcx.mk_type_list(v)),
630        }
631    }
632}
633
634impl<'tcx, T: TypeVisitable<TyCtxt<'tcx>>> TypeVisitable<TyCtxt<'tcx>> for &'tcx ty::List<T> {
635    #[inline]
636    fn visit_with<V: TypeVisitor<TyCtxt<'tcx>>>(&self, visitor: &mut V) -> V::Result {
637        walk_visitable_list!(visitor, self.iter());
638        V::Result::output()
639    }
640}
641
642/// Stores the user-given args to reach some fully qualified path
643/// (e.g., `<T>::Item` or `<T as Trait>::Item`).
644#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
645#[derive(HashStable, TypeFoldable, TypeVisitable)]
646pub struct UserArgs<'tcx> {
647    /// The args for the item as given by the user.
648    pub args: GenericArgsRef<'tcx>,
649
650    /// The self type, in the case of a `<T>::Item` path (when applied
651    /// to an inherent impl). See `UserSelfTy` below.
652    pub user_self_ty: Option<UserSelfTy<'tcx>>,
653}
654
655/// Specifies the user-given self type. In the case of a path that
656/// refers to a member in an inherent impl, this self type is
657/// sometimes needed to constrain the type parameters on the impl. For
658/// example, in this code:
659///
660/// ```ignore (illustrative)
661/// struct Foo<T> { }
662/// impl<A> Foo<A> { fn method() { } }
663/// ```
664///
665/// when you then have a path like `<Foo<&'static u32>>::method`,
666/// this struct would carry the `DefId` of the impl along with the
667/// self type `Foo<u32>`. Then we can instantiate the parameters of
668/// the impl (with the args from `UserArgs`) and apply those to
669/// the self type, giving `Foo<?A>`. Finally, we unify that with
670/// the self type here, which contains `?A` to be `&'static u32`
671#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, TyEncodable, TyDecodable)]
672#[derive(HashStable, TypeFoldable, TypeVisitable)]
673pub struct UserSelfTy<'tcx> {
674    pub impl_def_id: DefId,
675    pub self_ty: Ty<'tcx>,
676}