]> git.lizzy.rs Git - rust.git/blob - crates/ra_hir/src/ty/lower.rs
a11d964c8cbe161b5d760935285a90a6029d856d
[rust.git] / crates / ra_hir / src / ty / lower.rs
1 //! Methods for lowering the HIR to types. There are two main cases here:
2 //!
3 //!  - Lowering a type reference like `&usize` or `Option<foo::bar::Baz>` to a
4 //!    type: The entry point for this is `Ty::from_hir`.
5 //!  - Building the type for an item: This happens through the `type_for_def` query.
6 //!
7 //! This usually involves resolving names, collecting generic arguments etc.
8
9 use std::sync::Arc;
10
11 use crate::{
12     Function, Struct, StructField, Enum, EnumVariant, Path, Name,
13     ModuleDef, Type,
14     HirDatabase,
15     type_ref::TypeRef,
16     name::KnownName,
17     nameres::Namespace,
18     resolve::{Resolver, Resolution},
19     path::{ PathSegment, GenericArg},
20     generics::GenericParams,
21     adt::VariantDef,
22 };
23 use super::{Ty, primitive, FnSig, Substs};
24
25 impl Ty {
26     pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
27         match type_ref {
28             TypeRef::Never => Ty::Never,
29             TypeRef::Tuple(inner) => {
30                 let inner_tys =
31                     inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
32                 Ty::Tuple(inner_tys.into())
33             }
34             TypeRef::Path(path) => Ty::from_hir_path(db, resolver, path),
35             TypeRef::RawPtr(inner, mutability) => {
36                 let inner_ty = Ty::from_hir(db, resolver, inner);
37                 Ty::RawPtr(Arc::new(inner_ty), *mutability)
38             }
39             TypeRef::Array(inner) => {
40                 let inner_ty = Ty::from_hir(db, resolver, inner);
41                 Ty::Array(Arc::new(inner_ty))
42             }
43             TypeRef::Slice(inner) => {
44                 let inner_ty = Ty::from_hir(db, resolver, inner);
45                 Ty::Slice(Arc::new(inner_ty))
46             }
47             TypeRef::Reference(inner, mutability) => {
48                 let inner_ty = Ty::from_hir(db, resolver, inner);
49                 Ty::Ref(Arc::new(inner_ty), *mutability)
50             }
51             TypeRef::Placeholder => Ty::Unknown,
52             TypeRef::Fn(params) => {
53                 let mut inner_tys =
54                     params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
55                 let return_ty =
56                     inner_tys.pop().expect("TypeRef::Fn should always have at least return type");
57                 let sig = FnSig { input: inner_tys, output: return_ty };
58                 Ty::FnPtr(Arc::new(sig))
59             }
60             TypeRef::Error => Ty::Unknown,
61         }
62     }
63
64     pub(crate) fn from_hir_path(db: &impl HirDatabase, resolver: &Resolver, path: &Path) -> Self {
65         if let Some(name) = path.as_ident() {
66             // TODO handle primitive type names in resolver as well?
67             if let Some(int_ty) = primitive::UncertainIntTy::from_name(name) {
68                 return Ty::Int(int_ty);
69             } else if let Some(float_ty) = primitive::UncertainFloatTy::from_name(name) {
70                 return Ty::Float(float_ty);
71             } else if let Some(known) = name.as_known_name() {
72                 match known {
73                     KnownName::Bool => return Ty::Bool,
74                     KnownName::Char => return Ty::Char,
75                     KnownName::Str => return Ty::Str,
76                     _ => {}
77                 }
78             }
79         }
80
81         // Resolve the path (in type namespace)
82         let resolution = resolver.resolve_path(db, path).take_types();
83
84         let def = match resolution {
85             Some(Resolution::Def(def)) => def,
86             Some(Resolution::LocalBinding(..)) => {
87                 // this should never happen
88                 panic!("path resolved to local binding in type ns");
89             }
90             Some(Resolution::GenericParam(idx)) => {
91                 return Ty::Param {
92                     idx,
93                     // TODO: maybe return name in resolution?
94                     name: path
95                         .as_ident()
96                         .expect("generic param should be single-segment path")
97                         .clone(),
98                 };
99             }
100             Some(Resolution::SelfType(impl_block)) => {
101                 return impl_block.target_ty(db);
102             }
103             None => return Ty::Unknown,
104         };
105
106         let typable: TypableDef = match def.into() {
107             None => return Ty::Unknown,
108             Some(it) => it,
109         };
110         let ty = db.type_for_def(typable, Namespace::Types);
111         let substs = Ty::substs_from_path(db, resolver, path, typable);
112         ty.subst(&substs)
113     }
114
115     pub(super) fn substs_from_path_segment(
116         db: &impl HirDatabase,
117         resolver: &Resolver,
118         segment: &PathSegment,
119         resolved: TypableDef,
120     ) -> Substs {
121         let mut substs = Vec::new();
122         let def_generics = match resolved {
123             TypableDef::Function(func) => func.generic_params(db),
124             TypableDef::Struct(s) => s.generic_params(db),
125             TypableDef::Enum(e) => e.generic_params(db),
126             TypableDef::EnumVariant(var) => var.parent_enum(db).generic_params(db),
127             TypableDef::Type(t) => t.generic_params(db),
128         };
129         let parent_param_count = def_generics.count_parent_params();
130         substs.extend((0..parent_param_count).map(|_| Ty::Unknown));
131         if let Some(generic_args) = &segment.args_and_bindings {
132             // if args are provided, it should be all of them, but we can't rely on that
133             let param_count = def_generics.params.len();
134             for arg in generic_args.args.iter().take(param_count) {
135                 match arg {
136                     GenericArg::Type(type_ref) => {
137                         let ty = Ty::from_hir(db, resolver, type_ref);
138                         substs.push(ty);
139                     }
140                 }
141             }
142         }
143         // add placeholders for args that were not provided
144         // TODO: handle defaults
145         let supplied_params = substs.len();
146         for _ in supplied_params..def_generics.count_params_including_parent() {
147             substs.push(Ty::Unknown);
148         }
149         assert_eq!(substs.len(), def_generics.count_params_including_parent());
150         Substs(substs.into())
151     }
152
153     /// Collect generic arguments from a path into a `Substs`. See also
154     /// `create_substs_for_ast_path` and `def_to_ty` in rustc.
155     pub(super) fn substs_from_path(
156         db: &impl HirDatabase,
157         resolver: &Resolver,
158         path: &Path,
159         resolved: TypableDef,
160     ) -> Substs {
161         let last = path.segments.last().expect("path should have at least one segment");
162         let segment = match resolved {
163             TypableDef::Function(_)
164             | TypableDef::Struct(_)
165             | TypableDef::Enum(_)
166             | TypableDef::Type(_) => last,
167             TypableDef::EnumVariant(_) => {
168                 // the generic args for an enum variant may be either specified
169                 // on the segment referring to the enum, or on the segment
170                 // referring to the variant. So `Option::<T>::None` and
171                 // `Option::None::<T>` are both allowed (though the former is
172                 // preferred). See also `def_ids_for_path_segments` in rustc.
173                 let len = path.segments.len();
174                 let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() {
175                     // Option::<T>::None
176                     &path.segments[len - 2]
177                 } else {
178                     // Option::None::<T>
179                     last
180                 };
181                 segment
182             }
183         };
184         Ty::substs_from_path_segment(db, resolver, segment, resolved)
185     }
186 }
187
188 /// Build the declared type of an item. This depends on the namespace; e.g. for
189 /// `struct Foo(usize)`, we have two types: The type of the struct itself, and
190 /// the constructor function `(usize) -> Foo` which lives in the values
191 /// namespace.
192 pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
193     match (def, ns) {
194         (TypableDef::Function(f), Namespace::Values) => type_for_fn(db, f),
195         (TypableDef::Struct(s), Namespace::Types) => type_for_struct(db, s),
196         (TypableDef::Struct(s), Namespace::Values) => type_for_struct_constructor(db, s),
197         (TypableDef::Enum(e), Namespace::Types) => type_for_enum(db, e),
198         (TypableDef::EnumVariant(v), Namespace::Values) => type_for_enum_variant_constructor(db, v),
199         (TypableDef::Type(t), Namespace::Types) => type_for_type_alias(db, t),
200
201         // 'error' cases:
202         (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
203         (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown,
204         (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
205         (TypableDef::Type(_), Namespace::Values) => Ty::Unknown,
206     }
207 }
208
209 /// Build the type of a specific field of a struct or enum variant.
210 pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
211     let parent_def = field.parent_def(db);
212     let resolver = match parent_def {
213         VariantDef::Struct(it) => it.resolver(db),
214         VariantDef::EnumVariant(it) => it.parent_enum(db).resolver(db),
215     };
216     let var_data = parent_def.variant_data(db);
217     let type_ref = &var_data.fields().unwrap()[field.id].type_ref;
218     Ty::from_hir(db, &resolver, type_ref)
219 }
220
221 /// Build the declared type of a function. This should not need to look at the
222 /// function body.
223 fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
224     let signature = def.signature(db);
225     let resolver = def.resolver(db);
226     let generics = def.generic_params(db);
227     let name = def.name(db);
228     let input =
229         signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
230     let output = Ty::from_hir(db, &resolver, signature.ret_type());
231     let sig = Arc::new(FnSig { input, output });
232     let substs = make_substs(&generics);
233     Ty::FnDef { def: def.into(), sig, name, substs }
234 }
235
236 /// Build the type of a tuple struct constructor.
237 fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
238     let var_data = def.variant_data(db);
239     let fields = match var_data.fields() {
240         Some(fields) => fields,
241         None => return type_for_struct(db, def), // Unit struct
242     };
243     let resolver = def.resolver(db);
244     let generics = def.generic_params(db);
245     let name = def.name(db).unwrap_or_else(Name::missing);
246     let input = fields
247         .iter()
248         .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
249         .collect::<Vec<_>>();
250     let output = type_for_struct(db, def);
251     let sig = Arc::new(FnSig { input, output });
252     let substs = make_substs(&generics);
253     Ty::FnDef { def: def.into(), sig, name, substs }
254 }
255
256 /// Build the type of a tuple enum variant constructor.
257 fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
258     let var_data = def.variant_data(db);
259     let fields = match var_data.fields() {
260         Some(fields) => fields,
261         None => return type_for_enum(db, def.parent_enum(db)), // Unit variant
262     };
263     let resolver = def.parent_enum(db).resolver(db);
264     let generics = def.parent_enum(db).generic_params(db);
265     let name = def.name(db).unwrap_or_else(Name::missing);
266     let input = fields
267         .iter()
268         .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
269         .collect::<Vec<_>>();
270     let substs = make_substs(&generics);
271     let output = type_for_enum(db, def.parent_enum(db)).subst(&substs);
272     let sig = Arc::new(FnSig { input, output });
273     Ty::FnDef { def: def.into(), sig, name, substs }
274 }
275
276 fn make_substs(generics: &GenericParams) -> Substs {
277     Substs(
278         generics
279             .params_including_parent()
280             .into_iter()
281             .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
282             .collect::<Vec<_>>()
283             .into(),
284     )
285 }
286
287 fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
288     let generics = s.generic_params(db);
289     Ty::Adt {
290         def_id: s.into(),
291         name: s.name(db).unwrap_or_else(Name::missing),
292         substs: make_substs(&generics),
293     }
294 }
295
296 fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
297     let generics = s.generic_params(db);
298     Ty::Adt {
299         def_id: s.into(),
300         name: s.name(db).unwrap_or_else(Name::missing),
301         substs: make_substs(&generics),
302     }
303 }
304
305 fn type_for_type_alias(db: &impl HirDatabase, t: Type) -> Ty {
306     let generics = t.generic_params(db);
307     let resolver = t.resolver(db);
308     let type_ref = t.type_ref(db);
309     let substs = make_substs(&generics);
310     let inner = Ty::from_hir(db, &resolver, &type_ref);
311     inner.subst(&substs)
312 }
313
314 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
315 pub enum TypableDef {
316     Function(Function),
317     Struct(Struct),
318     Enum(Enum),
319     EnumVariant(EnumVariant),
320     Type(Type),
321 }
322 impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, Type);
323
324 impl From<ModuleDef> for Option<TypableDef> {
325     fn from(def: ModuleDef) -> Option<TypableDef> {
326         let res = match def {
327             ModuleDef::Function(f) => f.into(),
328             ModuleDef::Struct(s) => s.into(),
329             ModuleDef::Enum(e) => e.into(),
330             ModuleDef::EnumVariant(v) => v.into(),
331             ModuleDef::Type(t) => t.into(),
332             ModuleDef::Const(_)
333             | ModuleDef::Static(_)
334             | ModuleDef::Module(_)
335             | ModuleDef::Trait(_) => return None,
336         };
337         Some(res)
338     }
339 }
340
341 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
342 pub enum CallableDef {
343     Function(Function),
344     Struct(Struct),
345     EnumVariant(EnumVariant),
346 }
347 impl_froms!(CallableDef: Function, Struct, EnumVariant);