diff options
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 99 |
1 files changed, 57 insertions, 42 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index f4e055feb..278f592d3 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -9,7 +9,7 @@ | |||
9 | use std::sync::Arc; | 9 | use std::sync::Arc; |
10 | 10 | ||
11 | use crate::{ | 11 | use crate::{ |
12 | Function, Struct, StructField, Enum, EnumVariant, Path, Name, | 12 | Function, Struct, StructField, Enum, EnumVariant, Path, |
13 | ModuleDef, TypeAlias, | 13 | ModuleDef, TypeAlias, |
14 | Const, Static, | 14 | Const, Static, |
15 | HirDatabase, | 15 | HirDatabase, |
@@ -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). | ||
216 | pub(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. |
218 | pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | 225 | pub(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,19 +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 | ||
236 | fn 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. |
231 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 247 | fn 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 name = def.name(db); | ||
236 | let input = | ||
237 | signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | ||
238 | let output = Ty::from_hir(db, &resolver, signature.ret_type()); | ||
239 | let sig = Arc::new(FnSig { input, output }); | ||
240 | let substs = make_substs(&generics); | 249 | let substs = make_substs(&generics); |
241 | Ty::FnDef { def: def.into(), sig, name, substs } | 250 | Ty::FnDef { def: def.into(), substs } |
242 | } | 251 | } |
243 | 252 | ||
244 | /// Build the declared type of a const. | 253 | /// Build the declared type of a const. |
@@ -257,44 +266,58 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | |||
257 | Ty::from_hir(db, &resolver, signature.type_ref()) | 266 | Ty::from_hir(db, &resolver, signature.type_ref()) |
258 | } | 267 | } |
259 | 268 | ||
260 | /// Build the type of a tuple struct constructor. | 269 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
261 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | ||
262 | let var_data = def.variant_data(db); | 270 | let var_data = def.variant_data(db); |
263 | let fields = match var_data.fields() { | 271 | let fields = match var_data.fields() { |
264 | Some(fields) => fields, | 272 | Some(fields) => fields, |
265 | None => return type_for_struct(db, def), // Unit struct | 273 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), |
266 | }; | 274 | }; |
267 | let resolver = def.resolver(db); | 275 | let resolver = def.resolver(db); |
268 | let generics = def.generic_params(db); | 276 | let params = fields |
269 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
270 | let input = fields | ||
271 | .iter() | 277 | .iter() |
272 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 278 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
273 | .collect::<Vec<_>>(); | 279 | .collect::<Vec<_>>(); |
274 | let output = type_for_struct(db, def); | 280 | let ret = type_for_struct(db, def); |
275 | 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. | ||
285 | fn 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); | ||
276 | let substs = make_substs(&generics); | 291 | let substs = make_substs(&generics); |
277 | Ty::FnDef { def: def.into(), sig, name, substs } | 292 | Ty::FnDef { def: def.into(), substs } |
278 | } | 293 | } |
279 | 294 | ||
280 | /// Build the type of a tuple enum variant constructor. | 295 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { |
281 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | ||
282 | let var_data = def.variant_data(db); | 296 | let var_data = def.variant_data(db); |
283 | let fields = match var_data.fields() { | 297 | let fields = match var_data.fields() { |
284 | Some(fields) => fields, | 298 | Some(fields) => fields, |
285 | 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"), |
286 | }; | 300 | }; |
287 | let resolver = def.parent_enum(db).resolver(db); | 301 | let resolver = def.parent_enum(db).resolver(db); |
288 | let generics = def.parent_enum(db).generic_params(db); | 302 | let params = fields |
289 | let name = def.name(db).unwrap_or_else(Name::missing); | ||
290 | let input = fields | ||
291 | .iter() | 303 | .iter() |
292 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 304 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
293 | .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. | ||
313 | fn 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); | ||
294 | let substs = make_substs(&generics); | 319 | let substs = make_substs(&generics); |
295 | let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); | 320 | Ty::FnDef { def: def.into(), substs } |
296 | let sig = Arc::new(FnSig { input, output }); | ||
297 | Ty::FnDef { def: def.into(), sig, name, substs } | ||
298 | } | 321 | } |
299 | 322 | ||
300 | fn make_substs(generics: &GenericParams) -> Substs { | 323 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -310,20 +333,12 @@ fn make_substs(generics: &GenericParams) -> Substs { | |||
310 | 333 | ||
311 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { | 334 | fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty { |
312 | let generics = s.generic_params(db); | 335 | let generics = s.generic_params(db); |
313 | Ty::Adt { | 336 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } |
314 | def_id: s.into(), | ||
315 | name: s.name(db).unwrap_or_else(Name::missing), | ||
316 | substs: make_substs(&generics), | ||
317 | } | ||
318 | } | 337 | } |
319 | 338 | ||
320 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 339 | fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { |
321 | let generics = s.generic_params(db); | 340 | let generics = s.generic_params(db); |
322 | Ty::Adt { | 341 | Ty::Adt { def_id: s.into(), substs: make_substs(&generics) } |
323 | def_id: s.into(), | ||
324 | name: s.name(db).unwrap_or_else(Name::missing), | ||
325 | substs: make_substs(&generics), | ||
326 | } | ||
327 | } | 342 | } |
328 | 343 | ||
329 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | 344 | fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { |