aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r--crates/ra_hir/src/ty.rs86
1 files changed, 47 insertions, 39 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index d4d896673..1a3e1994f 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -40,7 +40,7 @@ use crate::{
40 name::KnownName, 40 name::KnownName,
41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self}, 41 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat, self},
42 generics::GenericParams, 42 generics::GenericParams,
43 path::GenericArg, 43 path::{ GenericArgs, GenericArg},
44 adt::VariantDef, 44 adt::VariantDef,
45 resolve::{Resolver, Resolution}, nameres::Namespace 45 resolve::{Resolver, Resolution}, nameres::Namespace
46}; 46};
@@ -165,17 +165,6 @@ impl Substs {
165 pub fn empty() -> Substs { 165 pub fn empty() -> Substs {
166 Substs(Arc::new([])) 166 Substs(Arc::new([]))
167 } 167 }
168
169 /// Replaces the end of the substitutions by other ones.
170 pub(crate) fn replace_tail(self, replace_by: Vec<Ty>) -> Substs {
171 // again missing Arc::make_mut_slice...
172 let len = replace_by.len().min(self.0.len());
173 let parent_len = self.0.len() - len;
174 let mut result = Vec::with_capacity(parent_len + len);
175 result.extend(self.0.iter().take(parent_len).cloned());
176 result.extend(replace_by);
177 Substs(result.into())
178 }
179} 168}
180 169
181/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs). 170/// A type. This is based on the `TyKind` enum in rustc (librustc/ty/sty.rs).
@@ -454,7 +443,7 @@ impl Ty {
454 for _ in supplied_params..def_generics.count_params_including_parent() { 443 for _ in supplied_params..def_generics.count_params_including_parent() {
455 substs.push(Ty::Unknown); 444 substs.push(Ty::Unknown);
456 } 445 }
457 assert_eq!(substs.len(), def_generics.params.len()); 446 assert_eq!(substs.len(), def_generics.count_params_including_parent());
458 Substs(substs.into()) 447 Substs(substs.into())
459 } 448 }
460 449
@@ -639,8 +628,11 @@ impl fmt::Display for Ty {
639 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?; 628 join(sig.input.iter()).surround_with("fn(", ")").separator(", ").to_fmt(f)?;
640 write!(f, " -> {}", sig.output) 629 write!(f, " -> {}", sig.output)
641 } 630 }
642 Ty::FnDef { name, substs, sig, .. } => { 631 Ty::FnDef { def, name, substs, sig, .. } => {
643 write!(f, "fn {}", name)?; 632 match def {
633 CallableDef::Function(_) => write!(f, "fn {}", name)?,
634 CallableDef::Struct(_) | CallableDef::EnumVariant(_) => write!(f, "{}", name)?,
635 }
644 if substs.0.len() > 0 { 636 if substs.0.len() > 0 {
645 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?; 637 join(substs.0.iter()).surround_with("<", ">").separator(", ").to_fmt(f)?;
646 } 638 }
@@ -712,16 +704,18 @@ fn type_for_enum_variant_constructor(db: &impl HirDatabase, def: EnumVariant) ->
712 .iter() 704 .iter()
713 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref)) 705 .map(|(_, field)| Ty::from_hir(db, &resolver, &field.type_ref))
714 .collect::<Vec<_>>(); 706 .collect::<Vec<_>>();
715 let output = type_for_enum(db, def.parent_enum(db));
716 let sig = Arc::new(FnSig { input, output });
717 let substs = make_substs(&generics); 707 let substs = make_substs(&generics);
708 let output = type_for_enum(db, def.parent_enum(db)).apply_substs(substs.clone());
709 let sig = Arc::new(FnSig { input, output });
718 Ty::FnDef { def: def.into(), sig, name, substs } 710 Ty::FnDef { def: def.into(), sig, name, substs }
719} 711}
720 712
721fn make_substs(generics: &GenericParams) -> Substs { 713fn make_substs(generics: &GenericParams) -> Substs {
722 Substs( 714 Substs(
723 (0..generics.count_params_including_parent()) 715 generics
724 .map(|_p| Ty::Unknown) 716 .params_including_parent()
717 .into_iter()
718 .map(|p| Ty::Param { idx: p.idx, name: p.name.clone() })
725 .collect::<Vec<_>>() 719 .collect::<Vec<_>>()
726 .into(), 720 .into(),
727 ) 721 )
@@ -736,7 +730,7 @@ fn type_for_struct(db: &impl HirDatabase, s: Struct) -> Ty {
736 } 730 }
737} 731}
738 732
739pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { 733fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty {
740 let generics = s.generic_params(db); 734 let generics = s.generic_params(db);
741 Ty::Adt { 735 Ty::Adt {
742 def_id: s.into(), 736 def_id: s.into(),
@@ -1353,6 +1347,37 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1353 ty 1347 ty
1354 } 1348 }
1355 1349
1350 fn substs_for_method_call(
1351 &mut self,
1352 def_generics: Option<Arc<GenericParams>>,
1353 generic_args: &Option<GenericArgs>,
1354 ) -> Substs {
1355 let (parent_param_count, param_count) =
1356 def_generics.map_or((0, 0), |g| (g.count_parent_params(), g.params.len()));
1357 let mut substs = Vec::with_capacity(parent_param_count + param_count);
1358 for _ in 0..parent_param_count {
1359 substs.push(Ty::Unknown);
1360 }
1361 // handle provided type arguments
1362 if let Some(generic_args) = generic_args {
1363 // if args are provided, it should be all of them, but we can't rely on that
1364 for arg in generic_args.args.iter().take(param_count) {
1365 match arg {
1366 GenericArg::Type(type_ref) => {
1367 let ty = self.make_ty(type_ref);
1368 substs.push(ty);
1369 }
1370 }
1371 }
1372 };
1373 let supplied_params = substs.len();
1374 for _ in supplied_params..parent_param_count + param_count {
1375 substs.push(Ty::Unknown);
1376 }
1377 assert_eq!(substs.len(), parent_param_count + param_count);
1378 Substs(substs.into())
1379 }
1380
1356 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 1381 fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
1357 let body = Arc::clone(&self.body); // avoid borrow checker problem 1382 let body = Arc::clone(&self.body); // avoid borrow checker problem
1358 let ty = match &body[tgt_expr] { 1383 let ty = match &body[tgt_expr] {
@@ -1443,25 +1468,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1443 } 1468 }
1444 None => (Ty::Unknown, receiver_ty, None), 1469 None => (Ty::Unknown, receiver_ty, None),
1445 }; 1470 };
1446 // handle provided type arguments 1471 let substs = self.substs_for_method_call(def_generics, generic_args);
1447 let method_ty = if let Some(generic_args) = generic_args { 1472 let method_ty = method_ty.apply_substs(substs);
1448 // if args are provided, it should be all of them, but we can't rely on that
1449 let param_count = def_generics.map(|g| g.params.len()).unwrap_or(0);
1450 let mut new_substs = Vec::with_capacity(generic_args.args.len());
1451 for arg in generic_args.args.iter().take(param_count) {
1452 match arg {
1453 GenericArg::Type(type_ref) => {
1454 let ty = self.make_ty(type_ref);
1455 new_substs.push(ty);
1456 }
1457 }
1458 }
1459 let substs = method_ty.substs().unwrap_or_else(Substs::empty);
1460 let substs = substs.replace_tail(new_substs);
1461 method_ty.apply_substs(substs)
1462 } else {
1463 method_ty
1464 };
1465 let method_ty = self.insert_type_vars(method_ty); 1473 let method_ty = self.insert_type_vars(method_ty);
1466 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { 1474 let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty {
1467 Ty::FnPtr(sig) => { 1475 Ty::FnPtr(sig) => {