aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-25 21:18:13 +0000
committerMarcus Klaas de Vries <[email protected]>2019-01-27 16:59:21 +0000
commit67e40e431aa966a76b6a247b19505e22b620a0c7 (patch)
tree057224378bf9dde5aca4c15194d1399cffef1d38 /crates
parent3bd47c0285433b5eb258196a81b95141d2a70505 (diff)
Initial implementation of generics for method calls
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir/src/code_model_api.rs4
-rw-r--r--crates/ra_hir/src/ty.rs81
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 {
624fn type_for_fn(db: &impl HirDatabase, f: Function) -> Ty { 647fn 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
630fn get_func_sig(db: &impl HirDatabase, f: Function) -> FnSig { 658fn 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,