diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 162 |
1 files changed, 126 insertions, 36 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 31ea45706..37715a903 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -20,6 +20,7 @@ mod tests; | |||
20 | pub(crate) mod method_resolution; | 20 | pub(crate) mod method_resolution; |
21 | 21 | ||
22 | use std::borrow::Cow; | 22 | use std::borrow::Cow; |
23 | use std::iter::repeat; | ||
23 | use std::ops::Index; | 24 | use std::ops::Index; |
24 | use std::sync::Arc; | 25 | use std::sync::Arc; |
25 | use std::{fmt, mem}; | 26 | use std::{fmt, mem}; |
@@ -185,7 +186,7 @@ pub enum Ty { | |||
185 | 186 | ||
186 | /// Structures, enumerations and unions. | 187 | /// Structures, enumerations and unions. |
187 | Adt { | 188 | Adt { |
188 | /// The DefId of the struct/enum. | 189 | /// The definition of the struct/enum. |
189 | def_id: AdtDef, | 190 | def_id: AdtDef, |
190 | /// The name, for displaying. | 191 | /// The name, for displaying. |
191 | name: Name, | 192 | name: Name, |
@@ -209,6 +210,27 @@ pub enum Ty { | |||
209 | /// `&'a mut T` or `&'a T`. | 210 | /// `&'a mut T` or `&'a T`. |
210 | Ref(Arc<Ty>, Mutability), | 211 | Ref(Arc<Ty>, Mutability), |
211 | 212 | ||
213 | /// The anonymous type of a function declaration/definition. Each | ||
214 | /// function has a unique type, which is output (for a function | ||
215 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
216 | /// | ||
217 | /// For example the type of `bar` here: | ||
218 | /// | ||
219 | /// ```rust | ||
220 | /// fn foo() -> i32 { 1 } | ||
221 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
222 | /// ``` | ||
223 | FnDef { | ||
224 | // Function definition | ||
225 | def: Function, | ||
226 | /// For display | ||
227 | name: Name, | ||
228 | /// Parameters and return type | ||
229 | sig: Arc<FnSig>, | ||
230 | /// Substitutions for the generic parameters of the type | ||
231 | substs: Substs, | ||
232 | }, | ||
233 | |||
212 | /// A pointer to a function. Written as `fn() -> i32`. | 234 | /// A pointer to a function. Written as `fn() -> i32`. |
213 | /// | 235 | /// |
214 | /// For example the type of `bar` here: | 236 | /// For example the type of `bar` here: |
@@ -448,12 +470,12 @@ impl Ty { | |||
448 | } | 470 | } |
449 | // add placeholders for args that were not provided | 471 | // add placeholders for args that were not provided |
450 | // TODO: handle defaults | 472 | // TODO: handle defaults |
451 | for _ in segment | 473 | let supplied_params = segment |
452 | .args_and_bindings | 474 | .args_and_bindings |
453 | .as_ref() | 475 | .as_ref() |
454 | .map(|ga| ga.args.len()) | 476 | .map(|ga| ga.args.len()) |
455 | .unwrap_or(0)..def_generics.params.len() | 477 | .unwrap_or(0); |
456 | { | 478 | for _ in supplied_params..def_generics.params.len() { |
457 | substs.push(Ty::Unknown); | 479 | substs.push(Ty::Unknown); |
458 | } | 480 | } |
459 | assert_eq!(substs.len(), def_generics.params.len()); | 481 | assert_eq!(substs.len(), def_generics.params.len()); |
@@ -485,6 +507,19 @@ impl Ty { | |||
485 | } | 507 | } |
486 | sig_mut.output.walk_mut(f); | 508 | sig_mut.output.walk_mut(f); |
487 | } | 509 | } |
510 | Ty::FnDef { substs, sig, .. } => { | ||
511 | let sig_mut = Arc::make_mut(sig); | ||
512 | for input in &mut sig_mut.input { | ||
513 | input.walk_mut(f); | ||
514 | } | ||
515 | sig_mut.output.walk_mut(f); | ||
516 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | ||
517 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | ||
518 | for t in &mut v { | ||
519 | t.walk_mut(f); | ||
520 | } | ||
521 | substs.0 = v.into(); | ||
522 | } | ||
488 | Ty::Adt { substs, .. } => { | 523 | Ty::Adt { substs, .. } => { |
489 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 524 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
490 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | 525 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); |
@@ -524,6 +559,12 @@ impl Ty { | |||
524 | name, | 559 | name, |
525 | substs, | 560 | substs, |
526 | }, | 561 | }, |
562 | Ty::FnDef { def, name, sig, .. } => Ty::FnDef { | ||
563 | def, | ||
564 | name, | ||
565 | sig, | ||
566 | substs, | ||
567 | }, | ||
527 | _ => self, | 568 | _ => self, |
528 | } | 569 | } |
529 | } | 570 | } |
@@ -551,7 +592,7 @@ impl Ty { | |||
551 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. | 592 | /// or function); so if `self` is `Option<u32>`, this returns the `u32`. |
552 | fn substs(&self) -> Option<Substs> { | 593 | fn substs(&self) -> Option<Substs> { |
553 | match self { | 594 | match self { |
554 | Ty::Adt { substs, .. } => Some(substs.clone()), | 595 | Ty::Adt { substs, .. } | Ty::FnDef { substs, .. } => Some(substs.clone()), |
555 | _ => None, | 596 | _ => None, |
556 | } | 597 | } |
557 | } | 598 | } |
@@ -586,6 +627,22 @@ impl fmt::Display for Ty { | |||
586 | .to_fmt(f)?; | 627 | .to_fmt(f)?; |
587 | write!(f, " -> {}", sig.output) | 628 | write!(f, " -> {}", sig.output) |
588 | } | 629 | } |
630 | Ty::FnDef { | ||
631 | name, substs, sig, .. | ||
632 | } => { | ||
633 | write!(f, "fn {}", name)?; | ||
634 | if substs.0.len() > 0 { | ||
635 | join(substs.0.iter()) | ||
636 | .surround_with("<", ">") | ||
637 | .separator(", ") | ||
638 | .to_fmt(f)?; | ||
639 | } | ||
640 | join(sig.input.iter()) | ||
641 | .surround_with("(", ")") | ||
642 | .separator(", ") | ||
643 | .to_fmt(f)?; | ||
644 | write!(f, " -> {}", sig.output) | ||
645 | } | ||
589 | Ty::Adt { name, substs, .. } => { | 646 | Ty::Adt { name, substs, .. } => { |
590 | write!(f, "{}", name)?; | 647 | write!(f, "{}", name)?; |
591 | if substs.0.len() > 0 { | 648 | if substs.0.len() > 0 { |
@@ -607,11 +664,11 @@ impl fmt::Display for Ty { | |||
607 | 664 | ||
608 | /// Compute the declared type of a function. This should not need to look at the | 665 | /// Compute the declared type of a function. This should not need to look at the |
609 | /// function body. | 666 | /// function body. |
610 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | 667 | fn type_for_fn(db: &impl HirDatabase, def: Function) -> Ty { |
611 | let signature = f.signature(db); | 668 | let signature = def.signature(db); |
612 | let module = f.module(db); | 669 | let module = def.module(db); |
613 | let impl_block = f.impl_block(db); | 670 | let impl_block = def.impl_block(db); |
614 | let generics = f.generic_params(db); | 671 | let generics = def.generic_params(db); |
615 | let input = signature | 672 | let input = signature |
616 | .params() | 673 | .params() |
617 | .iter() | 674 | .iter() |
@@ -624,8 +681,15 @@ fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | |||
624 | &generics, | 681 | &generics, |
625 | signature.ret_type(), | 682 | signature.ret_type(), |
626 | ); | 683 | ); |
627 | let sig = FnSig { input, output }; | 684 | let sig = Arc::new(FnSig { input, output }); |
628 | Ty::FnPtr(Arc::new(sig)) | 685 | let substs = make_substs(&generics); |
686 | let name = def.name(db); | ||
687 | Ty::FnDef { | ||
688 | def, | ||
689 | sig, | ||
690 | name, | ||
691 | substs, | ||
692 | } | ||
629 | } | 693 | } |
630 | 694 | ||
631 | fn make_substs(generics: &GenericParams) -> Substs { | 695 | fn make_substs(generics: &GenericParams) -> Substs { |
@@ -1102,7 +1166,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1102 | .into(); | 1166 | .into(); |
1103 | let typable = typable?; | 1167 | let typable = typable?; |
1104 | let ty = self.db.type_for_def(typable); | 1168 | let ty = self.db.type_for_def(typable); |
1169 | let generics = GenericParams::default(); | ||
1170 | let substs = Ty::substs_from_path( | ||
1171 | self.db, | ||
1172 | &self.module, | ||
1173 | self.impl_block.as_ref(), | ||
1174 | &generics, | ||
1175 | path, | ||
1176 | typable, | ||
1177 | ); | ||
1178 | let ty = ty.apply_substs(substs); | ||
1105 | let ty = self.insert_type_vars(ty); | 1179 | let ty = self.insert_type_vars(ty); |
1180 | |||
1106 | Some(ty) | 1181 | Some(ty) |
1107 | } | 1182 | } |
1108 | 1183 | ||
@@ -1142,7 +1217,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1142 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1217 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1143 | (ty, Some(var.into())) | 1218 | (ty, Some(var.into())) |
1144 | } | 1219 | } |
1145 | TypableDef::Enum(_) | TypableDef::Function(_) => (Ty::Unknown, None), | 1220 | TypableDef::Function(_) | TypableDef::Enum(_) => (Ty::Unknown, None), |
1146 | } | 1221 | } |
1147 | } | 1222 | } |
1148 | 1223 | ||
@@ -1196,9 +1271,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1196 | Ty::Tuple(ref tuple_args) => &**tuple_args, | 1271 | Ty::Tuple(ref tuple_args) => &**tuple_args, |
1197 | _ => &[], | 1272 | _ => &[], |
1198 | }; | 1273 | }; |
1199 | let expectations_iter = expectations | 1274 | let expectations_iter = expectations.into_iter().chain(repeat(&Ty::Unknown)); |
1200 | .into_iter() | ||
1201 | .chain(std::iter::repeat(&Ty::Unknown)); | ||
1202 | 1275 | ||
1203 | let inner_tys = args | 1276 | let inner_tys = args |
1204 | .iter() | 1277 | .iter() |
@@ -1332,18 +1405,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1332 | Expr::Call { callee, args } => { | 1405 | Expr::Call { callee, args } => { |
1333 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 1406 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
1334 | let (param_tys, ret_ty) = match &callee_ty { | 1407 | let (param_tys, ret_ty) = match &callee_ty { |
1335 | Ty::FnPtr(sig) => (&sig.input[..], sig.output.clone()), | 1408 | Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), |
1409 | Ty::FnDef { substs, sig, .. } => { | ||
1410 | let ret_ty = sig.output.clone().subst(&substs); | ||
1411 | let param_tys = sig | ||
1412 | .input | ||
1413 | .iter() | ||
1414 | .map(|ty| ty.clone().subst(&substs)) | ||
1415 | .collect(); | ||
1416 | (param_tys, ret_ty) | ||
1417 | } | ||
1336 | _ => { | 1418 | _ => { |
1337 | // not callable | 1419 | // not callable |
1338 | // TODO report an error? | 1420 | // TODO report an error? |
1339 | (&[][..], Ty::Unknown) | 1421 | (Vec::new(), Ty::Unknown) |
1340 | } | 1422 | } |
1341 | }; | 1423 | }; |
1342 | for (i, arg) in args.iter().enumerate() { | 1424 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
1343 | self.infer_expr( | 1425 | for (arg, param) in args.iter().zip(param_iter) { |
1344 | *arg, | 1426 | self.infer_expr(*arg, &Expectation::has_type(param)); |
1345 | &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), | ||
1346 | ); | ||
1347 | } | 1427 | } |
1348 | ret_ty | 1428 | ret_ty |
1349 | } | 1429 | } |
@@ -1365,21 +1445,34 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1365 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 1445 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
1366 | Ty::FnPtr(sig) => { | 1446 | Ty::FnPtr(sig) => { |
1367 | if sig.input.len() > 0 { | 1447 | if sig.input.len() > 0 { |
1368 | (&sig.input[0], &sig.input[1..], sig.output.clone()) | 1448 | ( |
1449 | sig.input[0].clone(), | ||
1450 | sig.input[1..].iter().cloned().collect(), | ||
1451 | sig.output.clone(), | ||
1452 | ) | ||
1369 | } else { | 1453 | } else { |
1370 | (&Ty::Unknown, &[][..], sig.output.clone()) | 1454 | (Ty::Unknown, Vec::new(), sig.output.clone()) |
1371 | } | 1455 | } |
1372 | } | 1456 | } |
1373 | _ => (&Ty::Unknown, &[][..], Ty::Unknown), | 1457 | Ty::FnDef { substs, sig, .. } => { |
1458 | let ret_ty = sig.output.clone().subst(&substs); | ||
1459 | |||
1460 | if sig.input.len() > 0 { | ||
1461 | let mut arg_iter = sig.input.iter().map(|ty| ty.clone().subst(&substs)); | ||
1462 | let receiver_ty = arg_iter.next().unwrap(); | ||
1463 | (receiver_ty, arg_iter.collect(), ret_ty) | ||
1464 | } else { | ||
1465 | (Ty::Unknown, Vec::new(), ret_ty) | ||
1466 | } | ||
1467 | } | ||
1468 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), | ||
1374 | }; | 1469 | }; |
1375 | // TODO we would have to apply the autoderef/autoref steps here | 1470 | // TODO we would have to apply the autoderef/autoref steps here |
1376 | // to get the correct receiver type to unify... | 1471 | // to get the correct receiver type to unify... |
1377 | self.unify(expected_receiver_ty, &receiver_ty); | 1472 | self.unify(&expected_receiver_ty, &receiver_ty); |
1378 | for (i, arg) in args.iter().enumerate() { | 1473 | let param_iter = param_tys.into_iter().chain(repeat(Ty::Unknown)); |
1379 | self.infer_expr( | 1474 | for (arg, param) in args.iter().zip(param_iter) { |
1380 | *arg, | 1475 | self.infer_expr(*arg, &Expectation::has_type(param)); |
1381 | &Expectation::has_type(param_tys.get(i).cloned().unwrap_or(Ty::Unknown)), | ||
1382 | ); | ||
1383 | } | 1476 | } |
1384 | ret_ty | 1477 | ret_ty |
1385 | } | 1478 | } |
@@ -1609,10 +1702,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1609 | 1702 | ||
1610 | self.infer_pat(*pat, &ty); | 1703 | self.infer_pat(*pat, &ty); |
1611 | } | 1704 | } |
1612 | self.return_ty = { | 1705 | self.return_ty = self.make_ty(signature.ret_type()); |
1613 | let ty = self.make_ty(signature.ret_type()); | ||
1614 | ty | ||
1615 | }; | ||
1616 | } | 1706 | } |
1617 | 1707 | ||
1618 | fn infer_body(&mut self) { | 1708 | fn infer_body(&mut self) { |