diff options
Diffstat (limited to 'crates/ra_hir/src/ty.rs')
-rw-r--r-- | crates/ra_hir/src/ty.rs | 180 |
1 files changed, 101 insertions, 79 deletions
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index 4c96579ee..f9cdbcab3 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -382,7 +382,8 @@ impl Ty { | |||
382 | 382 | ||
383 | // Resolve in module (in type namespace) | 383 | // Resolve in module (in type namespace) |
384 | let resolved = match module.resolve_path(db, path).take_types() { | 384 | let resolved = match module.resolve_path(db, path).take_types() { |
385 | Some(ModuleDef::Def(r)) => r, | 385 | Some(ModuleDef::Def(r)) => r.into(), |
386 | Some(ModuleDef::Function(f)) => f.into(), | ||
386 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, | 387 | None | Some(ModuleDef::Module(_)) => return Ty::Unknown, |
387 | }; | 388 | }; |
388 | let ty = db.type_for_def(resolved); | 389 | let ty = db.type_for_def(resolved); |
@@ -399,36 +400,38 @@ impl Ty { | |||
399 | impl_block: Option<&ImplBlock>, | 400 | impl_block: Option<&ImplBlock>, |
400 | outer_generics: &GenericParams, | 401 | outer_generics: &GenericParams, |
401 | path: &Path, | 402 | path: &Path, |
402 | resolved: DefId, | 403 | resolved: TypableDef, |
403 | ) -> Substs { | 404 | ) -> Substs { |
404 | let mut substs = Vec::new(); | 405 | let mut substs = Vec::new(); |
405 | let def = resolved.resolve(db); | ||
406 | let last = path | 406 | let last = path |
407 | .segments | 407 | .segments |
408 | .last() | 408 | .last() |
409 | .expect("path should have at least one segment"); | 409 | .expect("path should have at least one segment"); |
410 | let (def_generics, segment) = match def { | 410 | let (def_generics, segment) = match resolved { |
411 | Def::Struct(s) => (s.generic_params(db), last), | 411 | TypableDef::Function(func) => (func.generic_params(db), last), |
412 | Def::Enum(e) => (e.generic_params(db), last), | 412 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
413 | Def::Function(f) => (f.generic_params(db), last), | 413 | Def::Struct(s) => (s.generic_params(db), last), |
414 | Def::Trait(t) => (t.generic_params(db), last), | 414 | Def::Enum(e) => (e.generic_params(db), last), |
415 | Def::EnumVariant(ev) => { | 415 | Def::Trait(t) => (t.generic_params(db), last), |
416 | // the generic args for an enum variant may be either specified | 416 | Def::EnumVariant(ev) => { |
417 | // on the segment referring to the enum, or on the segment | 417 | // the generic args for an enum variant may be either specified |
418 | // referring to the variant. So `Option::<T>::None` and | 418 | // on the segment referring to the enum, or on the segment |
419 | // `Option::None::<T>` are both allowed (though the former is | 419 | // referring to the variant. So `Option::<T>::None` and |
420 | // preferred). See also `def_ids_for_path_segments` in rustc. | 420 | // `Option::None::<T>` are both allowed (though the former is |
421 | let len = path.segments.len(); | 421 | // preferred). See also `def_ids_for_path_segments` in rustc. |
422 | let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() { | 422 | let len = path.segments.len(); |
423 | // Option::<T>::None | 423 | let segment = if len >= 2 && path.segments[len - 2].args_and_bindings.is_some() |
424 | &path.segments[len - 2] | 424 | { |
425 | } else { | 425 | // Option::<T>::None |
426 | // Option::None::<T> | 426 | &path.segments[len - 2] |
427 | last | 427 | } else { |
428 | }; | 428 | // Option::None::<T> |
429 | (ev.parent_enum(db).generic_params(db), segment) | 429 | last |
430 | } | 430 | }; |
431 | _ => return Substs::empty(), | 431 | (ev.parent_enum(db).generic_params(db), segment) |
432 | } | ||
433 | _ => return Substs::empty(), | ||
434 | }, | ||
432 | }; | 435 | }; |
433 | // substs_from_path | 436 | // substs_from_path |
434 | if let Some(generic_args) = &segment.args_and_bindings { | 437 | if let Some(generic_args) = &segment.args_and_bindings { |
@@ -660,21 +663,40 @@ pub(crate) fn type_for_enum_variant(db: &impl HirDatabase, ev: EnumVariant) -> T | |||
660 | type_for_enum(db, enum_parent) | 663 | type_for_enum(db, enum_parent) |
661 | } | 664 | } |
662 | 665 | ||
663 | pub(super) fn type_for_def(db: &impl HirDatabase, def_id: DefId) -> Ty { | 666 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] |
664 | let def = def_id.resolve(db); | 667 | pub enum TypableDef { |
668 | Function(Function), | ||
669 | Def(DefId), | ||
670 | } | ||
671 | |||
672 | impl From<Function> for TypableDef { | ||
673 | fn from(func: Function) -> TypableDef { | ||
674 | TypableDef::Function(func) | ||
675 | } | ||
676 | } | ||
677 | |||
678 | impl From<DefId> for TypableDef { | ||
679 | fn from(func: DefId) -> TypableDef { | ||
680 | TypableDef::Def(func) | ||
681 | } | ||
682 | } | ||
683 | |||
684 | pub(super) fn type_for_def(db: &impl HirDatabase, def: TypableDef) -> Ty { | ||
665 | match def { | 685 | match def { |
666 | Def::Function(f) => type_for_fn(db, f), | 686 | TypableDef::Function(f) => type_for_fn(db, f), |
667 | Def::Struct(s) => type_for_struct(db, s), | 687 | TypableDef::Def(def_id) => match def_id.resolve(db) { |
668 | Def::Enum(e) => type_for_enum(db, e), | 688 | Def::Struct(s) => type_for_struct(db, s), |
669 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), | 689 | Def::Enum(e) => type_for_enum(db, e), |
670 | _ => { | 690 | Def::EnumVariant(ev) => type_for_enum_variant(db, ev), |
671 | log::debug!( | 691 | _ => { |
672 | "trying to get type for item of unknown type {:?} {:?}", | 692 | log::debug!( |
673 | def_id, | 693 | "trying to get type for item of unknown type {:?} {:?}", |
674 | def | 694 | def_id, |
675 | ); | 695 | def |
676 | Ty::Unknown | 696 | ); |
677 | } | 697 | Ty::Unknown |
698 | } | ||
699 | }, | ||
678 | } | 700 | } |
679 | } | 701 | } |
680 | 702 | ||
@@ -694,28 +716,23 @@ pub(super) fn type_for_field(db: &impl HirDatabase, def_id: DefId, field: Name) | |||
694 | ), | 716 | ), |
695 | }; | 717 | }; |
696 | let module = def_id.module(db); | 718 | let module = def_id.module(db); |
697 | let impl_block = def_id.impl_block(db); | 719 | // We can't have an impl block ere, right? |
720 | // let impl_block = def_id.impl_block(db); | ||
698 | let type_ref = variant_data.get_field_type_ref(&field)?; | 721 | let type_ref = variant_data.get_field_type_ref(&field)?; |
699 | Some(Ty::from_hir( | 722 | Some(Ty::from_hir(db, &module, None, &generics, &type_ref)) |
700 | db, | ||
701 | &module, | ||
702 | impl_block.as_ref(), | ||
703 | &generics, | ||
704 | &type_ref, | ||
705 | )) | ||
706 | } | 723 | } |
707 | 724 | ||
708 | /// The result of type inference: A mapping from expressions and patterns to types. | 725 | /// The result of type inference: A mapping from expressions and patterns to types. |
709 | #[derive(Clone, PartialEq, Eq, Debug)] | 726 | #[derive(Clone, PartialEq, Eq, Debug)] |
710 | pub struct InferenceResult { | 727 | pub struct InferenceResult { |
711 | /// For each method call expr, record the function it resolved to. | 728 | /// For each method call expr, record the function it resolved to. |
712 | method_resolutions: FxHashMap<ExprId, DefId>, | 729 | method_resolutions: FxHashMap<ExprId, Function>, |
713 | type_of_expr: ArenaMap<ExprId, Ty>, | 730 | type_of_expr: ArenaMap<ExprId, Ty>, |
714 | type_of_pat: ArenaMap<PatId, Ty>, | 731 | type_of_pat: ArenaMap<PatId, Ty>, |
715 | } | 732 | } |
716 | 733 | ||
717 | impl InferenceResult { | 734 | impl InferenceResult { |
718 | pub fn method_resolution(&self, expr: ExprId) -> Option<DefId> { | 735 | pub fn method_resolution(&self, expr: ExprId) -> Option<Function> { |
719 | self.method_resolutions.get(&expr).map(|it| *it) | 736 | self.method_resolutions.get(&expr).map(|it| *it) |
720 | } | 737 | } |
721 | } | 738 | } |
@@ -745,7 +762,7 @@ struct InferenceContext<'a, D: HirDatabase> { | |||
745 | module: Module, | 762 | module: Module, |
746 | impl_block: Option<ImplBlock>, | 763 | impl_block: Option<ImplBlock>, |
747 | var_unification_table: InPlaceUnificationTable<TypeVarId>, | 764 | var_unification_table: InPlaceUnificationTable<TypeVarId>, |
748 | method_resolutions: FxHashMap<ExprId, DefId>, | 765 | method_resolutions: FxHashMap<ExprId, Function>, |
749 | type_of_expr: ArenaMap<ExprId, Ty>, | 766 | type_of_expr: ArenaMap<ExprId, Ty>, |
750 | type_of_pat: ArenaMap<PatId, Ty>, | 767 | type_of_pat: ArenaMap<PatId, Ty>, |
751 | /// The return type of the function being inferred. | 768 | /// The return type of the function being inferred. |
@@ -871,8 +888,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
871 | self.type_of_expr.insert(expr, ty); | 888 | self.type_of_expr.insert(expr, ty); |
872 | } | 889 | } |
873 | 890 | ||
874 | fn write_method_resolution(&mut self, expr: ExprId, def_id: DefId) { | 891 | fn write_method_resolution(&mut self, expr: ExprId, func: Function) { |
875 | self.method_resolutions.insert(expr, def_id); | 892 | self.method_resolutions.insert(expr, func); |
876 | } | 893 | } |
877 | 894 | ||
878 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { | 895 | fn write_pat_ty(&mut self, pat: PatId, ty: Ty) { |
@@ -1060,7 +1077,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1060 | 1077 | ||
1061 | // resolve in module | 1078 | // resolve in module |
1062 | let resolved = match self.module.resolve_path(self.db, &path).take_values()? { | 1079 | let resolved = match self.module.resolve_path(self.db, &path).take_values()? { |
1063 | ModuleDef::Def(it) => it, | 1080 | ModuleDef::Def(it) => it.into(), |
1081 | ModuleDef::Function(func) => func.into(), | ||
1064 | ModuleDef::Module(_) => return None, | 1082 | ModuleDef::Module(_) => return None, |
1065 | }; | 1083 | }; |
1066 | let ty = self.db.type_for_def(resolved); | 1084 | let ty = self.db.type_for_def(resolved); |
@@ -1073,8 +1091,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1073 | Some(path) => path, | 1091 | Some(path) => path, |
1074 | None => return (Ty::Unknown, None), | 1092 | None => return (Ty::Unknown, None), |
1075 | }; | 1093 | }; |
1076 | let def_id = match self.module.resolve_path(self.db, &path).take_types() { | 1094 | let def = match self.module.resolve_path(self.db, &path).take_types() { |
1077 | Some(ModuleDef::Def(def_id)) => def_id, | 1095 | Some(ModuleDef::Def(def_id)) => def_id.into(), |
1096 | Some(ModuleDef::Function(func)) => func.into(), | ||
1078 | _ => return (Ty::Unknown, None), | 1097 | _ => return (Ty::Unknown, None), |
1079 | }; | 1098 | }; |
1080 | // TODO remove the duplication between here and `Ty::from_path`? | 1099 | // TODO remove the duplication between here and `Ty::from_path`? |
@@ -1086,20 +1105,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1086 | self.impl_block.as_ref(), | 1105 | self.impl_block.as_ref(), |
1087 | &generics, | 1106 | &generics, |
1088 | path, | 1107 | path, |
1089 | def_id, | 1108 | def, |
1090 | ); | 1109 | ); |
1091 | match def_id.resolve(self.db) { | 1110 | match def { |
1092 | Def::Struct(s) => { | 1111 | TypableDef::Def(def_id) => match def_id.resolve(self.db) { |
1093 | let ty = type_for_struct(self.db, s); | 1112 | Def::Struct(s) => { |
1094 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1113 | let ty = type_for_struct(self.db, s); |
1095 | (ty, Some(def_id)) | 1114 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1096 | } | 1115 | (ty, Some(def_id)) |
1097 | Def::EnumVariant(ev) => { | 1116 | } |
1098 | let ty = type_for_enum_variant(self.db, ev); | 1117 | Def::EnumVariant(ev) => { |
1099 | let ty = self.insert_type_vars(ty.apply_substs(substs)); | 1118 | let ty = type_for_enum_variant(self.db, ev); |
1100 | (ty, Some(def_id)) | 1119 | let ty = self.insert_type_vars(ty.apply_substs(substs)); |
1101 | } | 1120 | (ty, Some(def_id)) |
1102 | _ => (Ty::Unknown, None), | 1121 | } |
1122 | _ => (Ty::Unknown, None), | ||
1123 | }, | ||
1124 | TypableDef::Function(_) => (Ty::Unknown, None), | ||
1103 | } | 1125 | } |
1104 | } | 1126 | } |
1105 | 1127 | ||
@@ -1216,7 +1238,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1216 | .resolve_path(self.db, &path) | 1238 | .resolve_path(self.db, &path) |
1217 | .take_values() | 1239 | .take_values() |
1218 | .and_then(|module_def| match module_def { | 1240 | .and_then(|module_def| match module_def { |
1219 | ModuleDef::Def(it) => Some(it), | 1241 | ModuleDef::Def(it) => Some(it.into()), |
1242 | ModuleDef::Function(func) => Some(func.into()), | ||
1220 | ModuleDef::Module(_) => None, | 1243 | ModuleDef::Module(_) => None, |
1221 | }) | 1244 | }) |
1222 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), | 1245 | .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)), |
@@ -1339,9 +1362,9 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1339 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); | 1362 | let receiver_ty = self.infer_expr(*receiver, &Expectation::none()); |
1340 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); | 1363 | let resolved = receiver_ty.clone().lookup_method(self.db, method_name); |
1341 | let method_ty = match resolved { | 1364 | let method_ty = match resolved { |
1342 | Some(def_id) => { | 1365 | Some(func) => { |
1343 | self.write_method_resolution(expr, def_id); | 1366 | self.write_method_resolution(expr, func); |
1344 | self.db.type_for_def(def_id) | 1367 | self.db.type_for_def(func.into()) |
1345 | } | 1368 | } |
1346 | None => Ty::Unknown, | 1369 | None => Ty::Unknown, |
1347 | }; | 1370 | }; |
@@ -1610,16 +1633,15 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1610 | } | 1633 | } |
1611 | } | 1634 | } |
1612 | 1635 | ||
1613 | pub fn infer(db: &impl HirDatabase, def_id: DefId) -> Arc<InferenceResult> { | 1636 | pub fn infer(db: &impl HirDatabase, func: Function) -> Arc<InferenceResult> { |
1614 | db.check_canceled(); | 1637 | db.check_canceled(); |
1615 | let function = Function::new(def_id); // TODO: consts also need inference | 1638 | let body = func.body(db); |
1616 | let body = function.body(db); | 1639 | let scopes = db.fn_scopes(func); |
1617 | let scopes = db.fn_scopes(def_id); | 1640 | let module = func.module(db); |
1618 | let module = function.module(db); | 1641 | let impl_block = func.impl_block(db); |
1619 | let impl_block = function.impl_block(db); | ||
1620 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); | 1642 | let mut ctx = InferenceContext::new(db, body, scopes, module, impl_block); |
1621 | 1643 | ||
1622 | let signature = function.signature(db); | 1644 | let signature = func.signature(db); |
1623 | ctx.collect_fn_signature(&signature); | 1645 | ctx.collect_fn_signature(&signature); |
1624 | 1646 | ||
1625 | ctx.infer_body(); | 1647 | ctx.infer_body(); |