diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 83 |
1 files changed, 45 insertions, 38 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index d4d896673..7f28a6edd 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). |
@@ -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 | ||
721 | fn make_substs(generics: &GenericParams) -> Substs { | 713 | fn 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 | ||
739 | pub(crate) fn type_for_enum(db: &impl HirDatabase, s: Enum) -> Ty { | 733 | fn 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,36 @@ 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 | Substs(substs.into()) | ||
1378 | } | ||
1379 | |||
1356 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { | 1380 | fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { |
1357 | let body = Arc::clone(&self.body); // avoid borrow checker problem | 1381 | let body = Arc::clone(&self.body); // avoid borrow checker problem |
1358 | let ty = match &body[tgt_expr] { | 1382 | let ty = match &body[tgt_expr] { |
@@ -1443,25 +1467,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1443 | } | 1467 | } |
1444 | None => (Ty::Unknown, receiver_ty, None), | 1468 | None => (Ty::Unknown, receiver_ty, None), |
1445 | }; | 1469 | }; |
1446 | // handle provided type arguments | 1470 | let substs = self.substs_for_method_call(def_generics, generic_args); |
1447 | let method_ty = if let Some(generic_args) = generic_args { | 1471 | 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); | 1472 | let method_ty = self.insert_type_vars(method_ty); |
1466 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { | 1473 | let (expected_receiver_ty, param_tys, ret_ty) = match &method_ty { |
1467 | Ty::FnPtr(sig) => { | 1474 | Ty::FnPtr(sig) => { |