diff options
Diffstat (limited to 'crates/ra_hir/src/ty/lower.rs')
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 70 |
1 files changed, 45 insertions, 25 deletions
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index ee4508bb2..7d065203a 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 | } |
@@ -226,16 +224,20 @@ pub(crate) fn type_for_field(db: &impl HirDatabase, field: StructField) -> Ty { | |||
226 | Ty::from_hir(db, &resolver, type_ref) | 224 | Ty::from_hir(db, &resolver, type_ref) |
227 | } | 225 | } |
228 | 226 | ||
227 | fn fn_sig_for_fn(db: &impl HirDatabase, def: Function) -> FnSig { | ||
228 | let signature = def.signature(db); | ||
229 | let resolver = def.resolver(db); | ||
230 | let params = | ||
231 | signature.params().iter().map(|tr| Ty::from_hir(db, &resolver, tr)).collect::<Vec<_>>(); | ||
232 | let ret = Ty::from_hir(db, &resolver, signature.ret_type()); | ||
233 | FnSig::from_params_and_return(params, ret) | ||
234 | } | ||
235 | |||
229 | /// Build the declared type of a function. This should not need to look at the | 236 | /// Build the declared type of a function. This should not need to look at the |
230 | /// function body. | 237 | /// function body. |
231 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { | 238 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
232 | let signature = def.signature(db); | 239 | let sig = fn_sig_for_fn(db, def); |
233 | let resolver = def.resolver(db); | ||
234 | let generics = def.generic_params(db); | 240 | 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); | 241 | let substs = make_substs(&generics); |
240 | Ty::FnDef { def: def.into(), sig, substs } | 242 | Ty::FnDef { def: def.into(), sig, substs } |
241 | } | 243 | } |
@@ -256,41 +258,59 @@ fn type_for_static(db: &impl HirDatabase, def: Static) -> Ty { | |||
256 | Ty::from_hir(db, &resolver, signature.type_ref()) | 258 | Ty::from_hir(db, &resolver, signature.type_ref()) |
257 | } | 259 | } |
258 | 260 | ||
259 | /// Build the type of a tuple struct constructor. | 261 | fn fn_sig_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> FnSig { |
260 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | ||
261 | let var_data = def.variant_data(db); | 262 | let var_data = def.variant_data(db); |
262 | let fields = match var_data.fields() { | 263 | let fields = match var_data.fields() { |
263 | Some(fields) => fields, | 264 | Some(fields) => fields, |
264 | None => return type_for_struct(db, def), // Unit struct | 265 | None => panic!("fn_sig_for_struct_constructor called on unit struct"), |
265 | }; | 266 | }; |
266 | let resolver = def.resolver(db); | 267 | let resolver = def.resolver(db); |
267 | let generics = def.generic_params(db); | 268 | let params = fields |
268 | let input = fields | ||
269 | .iter() | 269 | .iter() |
270 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 270 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
271 | .collect::<Vec<_>>(); | 271 | .collect::<Vec<_>>(); |
272 | let output = type_for_struct(db, def); | 272 | let ret = type_for_struct(db, def); |
273 | let sig = Arc::new(FnSig { input, output }); | 273 | FnSig::from_params_and_return(params, ret) |
274 | } | ||
275 | |||
276 | /// Build the type of a tuple struct constructor. | ||
277 | fn type_for_struct_constructor(db: &impl HirDatabase, def: Struct) -> Ty { | ||
278 | let var_data = def.variant_data(db); | ||
279 | if var_data.fields().is_none() { | ||
280 | return type_for_struct(db, def); // Unit struct | ||
281 | } | ||
282 | let sig = fn_sig_for_struct_constructor(db, def); | ||
283 | let generics = def.generic_params(db); | ||
274 | let substs = make_substs(&generics); | 284 | let substs = make_substs(&generics); |
275 | Ty::FnDef { def: def.into(), sig, substs } | 285 | Ty::FnDef { def: def.into(), sig, substs } |
276 | } | 286 | } |
277 | 287 | ||
278 | /// Build the type of a tuple enum variant constructor. | 288 | fn fn_sig_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> FnSig { |
279 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | ||
280 | let var_data = def.variant_data(db); | 289 | let var_data = def.variant_data(db); |
281 | let fields = match var_data.fields() { | 290 | let fields = match var_data.fields() { |
282 | Some(fields) => fields, | 291 | Some(fields) => fields, |
283 | None => return type_for_enum(db, def.parent_enum(db)), // Unit variant | 292 | None => panic!("fn_sig_for_enum_variant_constructor called for unit variant"), |
284 | }; | 293 | }; |
285 | let resolver = def.parent_enum(db).resolver(db); | 294 | let resolver = def.parent_enum(db).resolver(db); |
286 | let generics = def.parent_enum(db).generic_params(db); | 295 | let params = fields |
287 | let input = fields | ||
288 | .iter() | 296 | .iter() |
289 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) | 297 | .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) |
290 | .collect::<Vec<_>>(); | 298 | .collect::<Vec<_>>(); |
299 | let generics = def.parent_enum(db).generic_params(db); | ||
300 | let substs = make_substs(&generics); | ||
301 | let ret = type_for_enum(db, def.parent_enum(db)).subst(&substs); | ||
302 | FnSig::from_params_and_return(params, ret) | ||
303 | } | ||
304 | |||
305 | /// Build the type of a tuple enum variant constructor. | ||
306 | fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) -> Ty { | ||
307 | let var_data = def.variant_data(db); | ||
308 | if var_data.fields().is_none() { | ||
309 | return type_for_enum(db, def.parent_enum(db)); // Unit variant | ||
310 | } | ||
311 | let sig = fn_sig_for_enum_variant_constructor(db, def); | ||
312 | let generics = def.parent_enum(db).generic_params(db); | ||
291 | let substs = make_substs(&generics); | 313 | let substs = make_substs(&generics); |
292 | let output = type_for_enum(db, def.parent_enum(db)).subst(&substs); | ||
293 | let sig = Arc::new(FnSig { input, output }); | ||
294 | Ty::FnDef { def: def.into(), sig, substs } | 314 | Ty::FnDef { def: def.into(), sig, substs } |
295 | } | 315 | } |
296 | 316 | ||