1 //! Methods for lowering the HIR to types. There are two main cases here:
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.
7 //! This usually involves resolving names, collecting generic arguments etc.
12 Function, Struct, StructField, Enum, EnumVariant, Path, Name,
18 resolve::{Resolver, Resolution},
19 path::{ PathSegment, GenericArg},
20 generics::GenericParams,
23 use super::{Ty, primitive, FnSig, Substs};
26 pub(crate) fn from_hir(db: &impl HirDatabase, resolver: &Resolver, type_ref: &TypeRef) -> Self {
28 TypeRef::Never => Ty::Never,
29 TypeRef::Tuple(inner) => {
31 inner.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
32 Ty::Tuple(inner_tys.into())
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)
39 TypeRef::Array(inner) => {
40 let inner_ty = Ty::from_hir(db, resolver, inner);
41 Ty::Array(Arc::new(inner_ty))
43 TypeRef::Slice(inner) => {
44 let inner_ty = Ty::from_hir(db, resolver, inner);
45 Ty::Slice(Arc::new(inner_ty))
47 TypeRef::Reference(inner, mutability) => {
48 let inner_ty = Ty::from_hir(db, resolver, inner);
49 Ty::Ref(Arc::new(inner_ty), *mutability)
51 TypeRef::Placeholder => Ty::Unknown,
52 TypeRef::Fn(params) => {
54 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
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))
60 TypeRef::Error => Ty::Unknown,
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() {
73 KnownName::Bool => return Ty::Bool,
74 KnownName::Char => return Ty::Char,
75 KnownName::Str => return Ty::Str,
81 // Resolve the path (in type namespace)
82 let resolution = resolver.resolve_path(db, path).take_types();
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");
90 Some(Resolution::GenericParam(idx)) => {
93 // TODO: maybe return name in resolution?
96 .expect("generic param should be single-segment path")
100 Some(Resolution::SelfType(impl_block)) => {
101 return impl_block.target_ty(db);
103 None => return Ty::Unknown,
106 let typable: TypableDef = match def.into() {
107 None => return Ty::Unknown,
110 let ty = db.type_for_def(typable, Namespace::Types);
111 let substs = Ty::substs_from_path(db, resolver, path, typable);
115 pub(super) fn substs_from_path_segment(
116 db: &impl HirDatabase,
118 segment: &PathSegment,
119 resolved: TypableDef,
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::TypeAlias(t) => t.generic_params(db),
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) {
136 GenericArg::Type(type_ref) => {
137 let ty = Ty::from_hir(db, resolver, type_ref);
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);
149 assert_eq!(substs.len(), def_generics.count_params_including_parent());
150 Substs(substs.into())
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,
159 resolved: TypableDef,
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::TypeAlias(_) => 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() {
176 &path.segments[len - 2]
184 Ty::substs_from_path_segment(db, resolver, segment, resolved)
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
192 pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace) -> Ty {
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::TypeAlias(t), Namespace::Types) => type_for_type_alias(db, t),
202 (TypableDef::Function(_), Namespace::Types) => Ty::Unknown,
203 (TypableDef::Enum(_), Namespace::Values) => Ty::Unknown,
204 (TypableDef::EnumVariant(_), Namespace::Types) => Ty::Unknown,
205 (TypableDef::TypeAlias(_), Namespace::Values) => Ty::Unknown,
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),
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)
221 /// Build the declared type of a function. This should not need to look at the
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);
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 }
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
243 let resolver = def.resolver(db);
244 let generics = def.generic_params(db);
245 let name = def.name(db).unwrap_or_else(Name::missing);
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 }
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
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);
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 }
276 fn make_substs(generics: &GenericParams) -> Substs {
279 .params_including_parent()
281 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
287 fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
288 let generics = s.generic_params(db);
291 name: s.name(db).unwrap_or_else(Name::missing),
292 substs: make_substs(&generics),
296 fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
297 let generics = s.generic_params(db);
300 name: s.name(db).unwrap_or_else(Name::missing),
301 substs: make_substs(&generics),
305 fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> 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);
314 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
315 pub enum TypableDef {
319 EnumVariant(EnumVariant),
320 TypeAlias(TypeAlias),
322 impl_froms!(TypableDef: Function, Struct, Enum, EnumVariant, TypeAlias);
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::TypeAlias(t) => t.into(),
333 | ModuleDef::Static(_)
334 | ModuleDef::Module(_)
335 | ModuleDef::Trait(_) => return None,
341 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
342 pub enum CallableDef {
345 EnumVariant(EnumVariant),
347 impl_froms!(CallableDef: Function, Struct, EnumVariant);