aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/lower.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r--crates/ra_hir/src/ty/lower.rs82
1 files changed, 54 insertions, 28 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index ee4508bb2..278f592d3 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -51,12 +51,10 @@ impl Ty {
51 } 51 }
52 TypeRef::Placeholder => Ty::Unknown, 52 TypeRef::Placeholder => Ty::Unknown,
53 TypeRef::Fn(params) => { 53 TypeRef::Fn(params) => {
54 let mut inner_tys = 54 let inner_tys =
55 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>(); 55 params.iter().map(|tr| Ty::from_hir(db, resolver, tr)).collect::<Vec<_>>();
56 let return_ty = 56 let sig = FnSig { params_and_return: inner_tys.into() };
57 inner_tys.pop().expect("TypeRef::Fn should always have at least return type"); 57 Ty::FnPtr(sig)
58 let sig = FnSig { input: inner_tys, output: return_ty };
59 Ty::FnPtr(Arc::new(sig))
60 } 58 }
61 TypeRef::Error => Ty::Unknown, 59 TypeRef::Error => Ty::Unknown,
62 } 60 }
@@ -214,6 +212,15 @@ pub(crate) fn type_for_def(db: &impl HirDatabase, def: TypableDef, ns: Namespace
214 } 212 }
215} 213}
216 214
215/// Build the signature of a callable item (function, struct or enum variant).
216pub(crate) fn callable_item_sig(db: &impl HirDatabase, def: CallableDef) -> FnSig {
217 match def {
218 CallableDef::Function(f) => fn_sig_for_fn(db, f),
219 CallableDef::Struct(s) => fn_sig_for_struct_constructor(db, s),
220 CallableDef::EnumVariant(e) => fn_sig_for_enum_variant_constructor(db, e),
221 }
222}
223
217/// Build the type of a specific field of a struct or enum variant. 224/// Build the type of a specific field of a struct or enum variant.
218pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { 225pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
219 let parent_def = field.parent_def(db); 226 let parent_def = field.parent_def(db);
@@ -226,18 +233,21 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty {
226 Ty::from_hir(db, &resolver, type_ref) 233 Ty::from_hir(db, &resolver, type_ref)
227} 234}
228 235
236fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig {
237 let signature = def.signature(db);
238 let resolver = def.resolver(db);
239 let params =
240 signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
241 let ret = Ty::from_hir(db, &resolver, signature.ret_type());
242 FnSig::from_params_and_return(params, ret)
243}
244
229/// Build the declared type of a function. This should not need to look at the 245/// Build the declared type of a function. This should not need to look at the
230/// function body. 246/// function body.
231fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { 247fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty {
232 let signature = def.signature(db);
233 let resolver = def.resolver(db);
234 let generics = def.generic_params(db); 248 let generics = def.generic_params(db);
235 let input =
236 signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>();
237 let output = Ty::from_hir(db, &resolver, signature.ret_type());
238 let sig = Arc::new(FnSig { input, output });
239 let substs = make_substs(&generics); 249 let substs = make_substs(&generics);
240 Ty::FnDef { def: def.into(), sig, substs } 250 Ty::FnDef { def: def.into(), substs }
241} 251}
242 252
243/// Build the declared type of a const. 253/// Build the declared type of a const.
@@ -256,42 +266,58 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty {
256 Ty::from_hir(db, &resolver, signature.type_ref()) 266 Ty::from_hir(db, &resolver, signature.type_ref())
257} 267}
258 268
259/// Build the type of a tuple struct constructor. 269fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig {
260fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
261 let var_data = def.variant_data(db); 270 let var_data = def.variant_data(db);
262 let fields = match var_data.fields() { 271 let fields = match var_data.fields() {
263 Some(fields) => fields, 272 Some(fields) => fields,
264 None => return type_for_struct(db, def), // Unit struct 273 None => panic!("fn_sig_for_struct_constructor called on unit struct"),
265 }; 274 };
266 let resolver = def.resolver(db); 275 let resolver = def.resolver(db);
267 let generics = def.generic_params(db); 276 let params = fields
268 let input = fields
269 .iter() 277 .iter()
270 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 278 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
271 .collect::<Vec<_>>(); 279 .collect::<Vec<_>>();
272 let output = type_for_struct(db, def); 280 let ret = type_for_struct(db, def);
273 let sig = Arc::new(FnSig { input, output }); 281 FnSig::from_params_and_return(params, ret)
282}
283
284/// Build the type of a tuple struct constructor.
285fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty {
286 let var_data = def.variant_data(db);
287 if var_data.fields().is_none() {
288 return type_for_struct(db, def); // Unit struct
289 }
290 let generics = def.generic_params(db);
274 let substs = make_substs(&generics); 291 let substs = make_substs(&generics);
275 Ty::FnDef { def: def.into(), sig, substs } 292 Ty::FnDef { def: def.into(), substs }
276} 293}
277 294
278/// Build the type of a tuple enum variant constructor. 295fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig {
279fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
280 let var_data = def.variant_data(db); 296 let var_data = def.variant_data(db);
281 let fields = match var_data.fields() { 297 let fields = match var_data.fields() {
282 Some(fields) => fields, 298 Some(fields) => fields,
283 None => return type_for_enum(db, def.parent_enum(db)), // Unit variant 299 None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"),
284 }; 300 };
285 let resolver = def.parent_enum(db).resolver(db); 301 let resolver = def.parent_enum(db).resolver(db);
286 let generics = def.parent_enum(db).generic_params(db); 302 let params = fields
287 let input = fields
288 .iter() 303 .iter()
289 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 304 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
290 .collect::<Vec<_>>(); 305 .collect::<Vec<_>>();
306 let generics = def.parent_enum(db).generic_params(db);
307 let substs = make_substs(&generics);
308 let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs);
309 FnSig::from_params_and_return(params, ret)
310}
311
312/// Build the type of a tuple enum variant constructor.
313fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty {
314 let var_data = def.variant_data(db);
315 if var_data.fields().is_none() {
316 return type_for_enum(db, def.parent_enum(db)); // Unit variant
317 }
318 let generics = def.parent_enum(db).generic_params(db);
291 let substs = make_substs(&generics); 319 let substs = make_substs(&generics);
292 let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); 320 Ty::FnDef { def: def.into(), substs }
293 let sig = Arc::new(FnSig { input, output });
294 Ty::FnDef { def: def.into(), sig, substs }
295} 321}
296 322
297fn make_substs(generics: &GenericParams) -> Substs { 323fn make_substs(generics: &GenericParams) -> Substs {