Skip to main content

hir_def/hir/
type_ref.rs

1//! HIR for references to types. Paths in these are not yet resolved. They can
2//! be directly created from an ast::TypeRef, without further queries.
3
4use hir_expand::name::Name;
5use la_arena::Idx;
6use rustc_abi::ExternAbi;
7use thin_vec::ThinVec;
8
9use crate::{
10    LifetimeParamId, TypeParamId,
11    expr_store::{ExpressionStore, path::Path},
12    hir::{ExprId, PatId},
13};
14
15#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
16pub enum Mutability {
17    Shared,
18    Mut,
19}
20
21impl Mutability {
22    pub fn from_mutable(mutable: bool) -> Mutability {
23        if mutable { Mutability::Mut } else { Mutability::Shared }
24    }
25
26    pub fn as_keyword_for_ref(self) -> &'static str {
27        match self {
28            Mutability::Shared => "",
29            Mutability::Mut => "mut ",
30        }
31    }
32
33    pub fn as_keyword_for_ptr(self) -> &'static str {
34        match self {
35            Mutability::Shared => "const ",
36            Mutability::Mut => "mut ",
37        }
38    }
39
40    /// Returns `true` if the mutability is [`Mut`].
41    ///
42    /// [`Mut`]: Mutability::Mut
43    #[must_use]
44    pub fn is_mut(&self) -> bool {
45        matches!(self, Self::Mut)
46    }
47
48    /// Returns `true` if the mutability is [`Shared`].
49    ///
50    /// [`Shared`]: Mutability::Shared
51    #[must_use]
52    pub fn is_shared(&self) -> bool {
53        matches!(self, Self::Shared)
54    }
55}
56
57#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
58pub enum Rawness {
59    RawPtr,
60    Ref,
61}
62
63impl Rawness {
64    pub fn from_raw(is_raw: bool) -> Rawness {
65        if is_raw { Rawness::RawPtr } else { Rawness::Ref }
66    }
67
68    pub fn is_raw(&self) -> bool {
69        matches!(self, Self::RawPtr)
70    }
71}
72
73#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
74/// A `TypeRefId` that is guaranteed to always be `TypeRef::Path`. We use this for things like
75/// impl's trait, that are always paths but need to be traced back to source code.
76pub struct PathId(TypeRefId);
77
78impl PathId {
79    #[inline]
80    pub fn from_type_ref_unchecked(type_ref: TypeRefId) -> Self {
81        Self(type_ref)
82    }
83
84    #[inline]
85    pub fn type_ref(self) -> TypeRefId {
86        self.0
87    }
88}
89
90#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
91pub struct TraitRef {
92    pub path: PathId,
93}
94
95#[derive(Clone, PartialEq, Eq, Hash, Debug)]
96pub struct FnType {
97    pub binder: Option<Box<[Name]>>,
98    pub params: Box<[(Option<Name>, TypeRefId)]>,
99    pub is_varargs: bool,
100    pub is_unsafe: bool,
101    pub abi: ExternAbi,
102}
103
104impl FnType {
105    #[inline]
106    pub fn split_params_and_ret(&self) -> (&[(Option<Name>, TypeRefId)], TypeRefId) {
107        let (ret, params) = self.params.split_last().expect("should have at least return type");
108        (params, ret.1)
109    }
110}
111
112#[derive(Clone, PartialEq, Eq, Hash, Debug)]
113pub struct ArrayType {
114    pub ty: TypeRefId,
115    pub len: ConstRef,
116}
117
118#[derive(Clone, PartialEq, Eq, Hash, Debug)]
119pub struct RefType {
120    pub ty: TypeRefId,
121    pub lifetime: Option<LifetimeRefId>,
122    pub mutability: Mutability,
123}
124
125/// Compare ty::Ty
126#[derive(Clone, PartialEq, Eq, Hash, Debug)]
127pub enum TypeRef {
128    Never,
129    Placeholder,
130    Tuple(ThinVec<TypeRefId>),
131    Path(Path),
132    RawPtr(TypeRefId, Mutability),
133    // FIXME: Unbox this once `Idx` has a niche,
134    // as `RefType` should shrink by 4 bytes then
135    Reference(Box<RefType>),
136    Array(ArrayType),
137    Slice(TypeRefId),
138    /// A fn pointer. Last element of the vector is the return type.
139    Fn(Box<FnType>),
140    ImplTrait(ThinVec<TypeBound>),
141    DynTrait(ThinVec<TypeBound>),
142    TypeParam(TypeParamId),
143    PatternType(TypeRefId, PatId),
144    Error,
145}
146
147#[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
148const _: () = assert!(size_of::<TypeRef>() == 24);
149
150pub type TypeRefId = Idx<TypeRef>;
151
152pub type LifetimeRefId = Idx<LifetimeRef>;
153
154#[derive(Clone, PartialEq, Eq, Hash, Debug)]
155pub enum LifetimeRef {
156    Named(Name),
157    Static,
158    Placeholder,
159    Param(LifetimeParamId),
160    Error,
161}
162
163#[derive(Clone, PartialEq, Eq, Hash, Debug)]
164pub enum TypeBound {
165    Path(PathId, TraitBoundModifier),
166    ForLifetime(ThinVec<Name>, PathId),
167    Lifetime(LifetimeRefId),
168    Use(ThinVec<UseArgRef>),
169    Error,
170}
171
172#[cfg(target_pointer_width = "64")]
173const _: [(); 16] = [(); size_of::<TypeBound>()];
174
175#[derive(Clone, PartialEq, Eq, Hash, Debug)]
176pub enum UseArgRef {
177    Name(Name),
178    Lifetime(LifetimeRefId),
179}
180
181/// A modifier on a bound, currently this is only used for `?Sized`, where the
182/// modifier is `Maybe`.
183#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
184pub enum TraitBoundModifier {
185    None,
186    Maybe,
187}
188
189impl TypeRef {
190    pub(crate) fn unit() -> TypeRef {
191        TypeRef::Tuple(ThinVec::new())
192    }
193}
194
195impl TypeBound {
196    pub fn as_path<'a>(&self, map: &'a ExpressionStore) -> Option<(&'a Path, TraitBoundModifier)> {
197        match self {
198            &TypeBound::Path(p, m) => Some((&map[p], m)),
199            &TypeBound::ForLifetime(_, p) => Some((&map[p], TraitBoundModifier::None)),
200            TypeBound::Lifetime(_) | TypeBound::Error | TypeBound::Use(_) => None,
201        }
202    }
203}
204
205#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
206pub struct ConstRef {
207    pub expr: ExprId,
208}