diff options
author | Marcus Klaas de Vries <[email protected]> | 2019-01-25 21:18:13 +0000 |
---|---|---|
committer | Marcus Klaas de Vries <[email protected]> | 2019-01-27 16:59:21 +0000 |
commit | 67e40e431aa966a76b6a247b19505e22b620a0c7 (patch) | |
tree | 057224378bf9dde5aca4c15194d1399cffef1d38 /crates/ra_hir | |
parent | 3bd47c0285433b5eb258196a81b95141d2a70505 (diff) |
Initial implementation of generics for method calls
Diffstat (limited to 'crates/ra_hir')
-rw-r--r-- | crates/ra_hir/src/code_model_api.rs | 4 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 81 |
2 files changed, 72 insertions, 13 deletions
diff --git a/crates/ra_hir/src/code_model_api.rs b/crates/ra_hir/src/code_model_api.rs index 82ebb275a..defb9fd0a 100644 --- a/crates/ra_hir/src/code_model_api.rs +++ b/crates/ra_hir/src/code_model_api.rs | |||
@@ -424,6 +424,10 @@ impl Function { | |||
424 | self.id.module(db) | 424 | self.id.module(db) |
425 | } | 425 | } |
426 | 426 | ||
427 | pub fn name(&self, db: &impl HirDatabase) -> Name { | ||
428 | self.signature(db).name.clone() | ||
429 | } | ||
430 | |||
427 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { | 431 | pub fn body_syntax_mapping(&self, db: &impl HirDatabase) -> Arc<BodySyntaxMapping> { |
428 | db.body_syntax_mapping(*self) | 432 | db.body_syntax_mapping(*self) |
429 | } | 433 | } |
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 95de916ee..9b08b9c97 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -185,7 +185,7 @@ pub enum Ty { | |||
185 | 185 | ||
186 | /// Structures, enumerations and unions. | 186 | /// Structures, enumerations and unions. |
187 | Adt { | 187 | Adt { |
188 | /// The DefId of the struct/enum. | 188 | /// The definition of the struct/enum. |
189 | def_id: AdtDef, | 189 | def_id: AdtDef, |
190 | /// The name, for displaying. | 190 | /// The name, for displaying. |
191 | name: Name, | 191 | name: Name, |
@@ -219,7 +219,14 @@ pub enum Ty { | |||
219 | /// fn foo() -> i32 { 1 } | 219 | /// fn foo() -> i32 { 1 } |
220 | /// let bar = foo; // bar: fn() -> i32 {foo} | 220 | /// let bar = foo; // bar: fn() -> i32 {foo} |
221 | /// ``` | 221 | /// ``` |
222 | FnDef(Function, Substs), | 222 | FnDef { |
223 | // Function definition | ||
224 | def: Function, | ||
225 | /// For display | ||
226 | name: Name, | ||
227 | /// Substitutions for the generic parameters of the type | ||
228 | substs: Substs | ||
229 | }, | ||
223 | 230 | ||
224 | /// A pointer to a function. Written as `fn() -> i32`. | 231 | /// A pointer to a function. Written as `fn() -> i32`. |
225 | /// | 232 | /// |
@@ -497,7 +504,7 @@ impl Ty { | |||
497 | } | 504 | } |
498 | sig_mut.output.walk_mut(f); | 505 | sig_mut.output.walk_mut(f); |
499 | } | 506 | } |
500 | Ty::FnDef(_, substs) | Ty::Adt { substs, .. } => { | 507 | Ty::FnDef { substs, .. } | Ty::Adt { substs, .. } => { |
501 | // Without an Arc::make_mut_slice, we can't avoid the clone here: | 508 | // Without an Arc::make_mut_slice, we can't avoid the clone here: |
502 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); | 509 | let mut v: Vec<_> = substs.0.iter().cloned().collect(); |
503 | for t in &mut v { | 510 | for t in &mut v { |
@@ -536,7 +543,11 @@ impl Ty { | |||
536 | name, | 543 | name, |
537 | substs, | 544 | substs, |
538 | }, | 545 | }, |
539 | Ty::FnDef(func, _) => Ty::FnDef(func, substs), | 546 | Ty::FnDef { def, name, .. } => Ty::FnDef { |
547 | def, | ||
548 | name, | ||
549 | substs, | ||
550 | }, | ||
540 | _ => self, | 551 | _ => self, |
541 | } | 552 | } |
542 | } | 553 | } |
@@ -592,7 +603,6 @@ impl fmt::Display for Ty { | |||
592 | .to_fmt(f) | 603 | .to_fmt(f) |
593 | } | 604 | } |
594 | } | 605 | } |
595 | Ty::FnDef(_func, _substs) => write!(f, "FNDEF-IMPLEMENT-ME"), | ||
596 | Ty::FnPtr(sig) => { | 606 | Ty::FnPtr(sig) => { |
597 | join(sig.input.iter()) | 607 | join(sig.input.iter()) |
598 | .surround_with("fn(", ")") | 608 | .surround_with("fn(", ")") |
@@ -600,6 +610,19 @@ impl fmt::Display for Ty { | |||
600 | .to_fmt(f)?; | 610 | .to_fmt(f)?; |
601 | write!(f, " -> {}", sig.output) | 611 | write!(f, " -> {}", sig.output) |
602 | } | 612 | } |
613 | Ty::FnDef { name, substs, .. } => { | ||
614 | // don't have access to the param types here :-( | ||
615 | // we could store them in the def, but not sure if it | ||
616 | // is worth it | ||
617 | write!(f, "fn {}", name)?; | ||
618 | if substs.0.len() > 0 { | ||
619 | join(substs.0.iter()) | ||
620 | .surround_with("<", ">") | ||
621 | .separator(", ") | ||
622 | .to_fmt(f)?; | ||
623 | } | ||
624 | Ok(()) | ||
625 | } | ||
603 | Ty::Adt { name, substs, .. } => { | 626 | Ty::Adt { name, substs, .. } => { |
604 | write!(f, "{}", name)?; | 627 | write!(f, "{}", name)?; |
605 | if substs.0.len() > 0 { | 628 | if substs.0.len() > 0 { |
@@ -624,7 +647,12 @@ impl fmt::Display for Ty { | |||
624 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { | 647 | fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { |
625 | let generics = f.generic_params(db); | 648 | let generics = f.generic_params(db); |
626 | let substs = make_substs(&generics); | 649 | let substs = make_substs(&generics); |
627 | Ty::FnDef(f.into(), substs) | 650 | let name = f.name(db); |
651 | Ty::FnDef { | ||
652 | def: f.into(), | ||
653 | name, | ||
654 | substs | ||
655 | } | ||
628 | } | 656 | } |
629 | 657 | ||
630 | fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { | 658 | fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { |
@@ -1355,16 +1383,18 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1355 | Ty::Unknown | 1383 | Ty::Unknown |
1356 | } | 1384 | } |
1357 | Expr::Call { callee, args } => { | 1385 | Expr::Call { callee, args } => { |
1386 | // TODO: we should use turbofish hints like this: | ||
1387 | // f::<u32>(x) | ||
1358 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); | 1388 | let callee_ty = self.infer_expr(*callee, &Expectation::none()); |
1359 | // FIXME: so manu unnecessary clones | 1389 | // FIXME: so manu unnecessary clones |
1360 | let (param_tys, ret_ty) = match &callee_ty { | 1390 | let (param_tys, ret_ty) = match &callee_ty { |
1361 | Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), | 1391 | Ty::FnPtr(sig) => (sig.input.clone(), sig.output.clone()), |
1362 | Ty::FnDef(func, substs) => { | 1392 | Ty::FnDef { def, substs, .. } => { |
1363 | let fn_sig = func.signature(self.db); | 1393 | let fn_sig = def.signature(self.db); |
1364 | // TODO: get input and return types from the fn_sig. | 1394 | // TODO: get input and return types from the fn_sig. |
1365 | // it contains typerefs which we can make into proper tys | 1395 | // it contains typerefs which we can make into proper tys |
1366 | 1396 | ||
1367 | let sig = get_func_sig(self.db, *func); | 1397 | let sig = get_func_sig(self.db, *def); |
1368 | ( | 1398 | ( |
1369 | sig.input | 1399 | sig.input |
1370 | .iter() | 1400 | .iter() |
@@ -1405,16 +1435,41 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1405 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 1435 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
1406 | Ty::FnPtr(sig) => { | 1436 | Ty::FnPtr(sig) => { |
1407 | if sig.input.len() > 0 { | 1437 | if sig.input.len() > 0 { |
1408 | (&sig.input[0], &sig.input[1..], sig.output.clone()) | 1438 | (sig.input[0].clone(), sig.input[1..].iter().cloned().collect(), sig.output.clone()) |
1439 | } else { | ||
1440 | (Ty::Unknown, Vec::new(), sig.output.clone()) | ||
1441 | } | ||
1442 | } | ||
1443 | Ty::FnDef { def, substs, .. } => { | ||
1444 | // TODO: fix deduplication with Expr::Call block above | ||
1445 | // TODO: fix the ridiculous number of clones | ||
1446 | let fn_sig = def.signature(self.db); | ||
1447 | // TODO: get input and return types from the fn_sig. | ||
1448 | // it contains typerefs which we can make into proper tys | ||
1449 | |||
1450 | // check that len > 0 | ||
1451 | let sig = get_func_sig(self.db, *def); | ||
1452 | if sig.input.len() > 0 { | ||
1453 | ( | ||
1454 | sig.input[0].clone().subst(&substs), | ||
1455 | sig.input[1..] | ||
1456 | .iter() | ||
1457 | .map(|ty| ty.clone().subst(&substs)) | ||
1458 | .collect(), | ||
1459 | sig.output.clone().subst(&substs), | ||
1460 | ) | ||
1409 | } else { | 1461 | } else { |
1410 | (&Ty::Unknown, &[][..], sig.output.clone()) | 1462 | (Ty::Unknown, Vec::new(), sig.output.clone()) |
1411 | } | 1463 | } |
1412 | } | 1464 | } |
1413 | _ => (&Ty::Unknown, &[][..], Ty::Unknown), | 1465 | _ => (Ty::Unknown, Vec::new(), Ty::Unknown), |
1414 | }; | 1466 | }; |
1415 | // TODO we would have to apply the autoderef/autoref steps here | 1467 | // TODO we would have to apply the autoderef/autoref steps here |
1416 | // to get the correct receiver type to unify... | 1468 | // to get the correct receiver type to unify... |
1417 | self.unify(expected_receiver_ty, &receiver_ty); | 1469 | // |
1470 | // TODO: zip param_tys.chain(iter::repeat(Ty::Unknown)) above then its not so bad | ||
1471 | // that we clone | ||
1472 | self.unify(&expected_receiver_ty, &receiver_ty); | ||
1418 | for (i, arg) in args.iter().enumerate() { | 1473 | for (i, arg) in args.iter().enumerate() { |
1419 | self.infer_expr( | 1474 | self.infer_expr( |
1420 | *arg, | 1475 | *arg, |