aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir
diff options
context:
space:
mode:
authorMarcus Klaas de Vries <[email protected]>2019-01-17 23:41:02 +0000
committerAleksey Kladov <[email protected]>2019-01-19 12:37:26 +0000
commitb5466f3fb36005c313205d944430498f17aea6fa (patch)
tree6d7ae5caf5a87c295a30343ce6892949f1668b52 /crates/ra_hir
parent5027c5d4ee38e07ee426df433d0c650d55b1be84 (diff)
Address issues flagged in review
Diffstat (limited to 'crates/ra_hir')
-rw-r--r--crates/ra_hir/src/code_model_impl/function/scope.rs2
-rw-r--r--crates/ra_hir/src/expr.rs9
-rw-r--r--crates/ra_hir/src/ty.rs109
3 files changed, 45 insertions, 75 deletions
diff --git a/crates/ra_hir/src/code_model_impl/function/scope.rs b/crates/ra_hir/src/code_model_impl/function/scope.rs
index 220c71f74..3a7d53a93 100644
--- a/crates/ra_hir/src/code_model_impl/function/scope.rs
+++ b/crates/ra_hir/src/code_model_impl/function/scope.rs
@@ -97,8 +97,6 @@ impl FnScopes {
97 }; 97 };
98 self.scopes[scope].entries.push(entry) 98 self.scopes[scope].entries.push(entry)
99 } 99 }
100 // FIXME: isn't every call to add_binding starting an entirely new
101 // tree walk!?
102 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)), 100 p => p.walk_child_pats(|pat| self.add_bindings(body, scope, pat)),
103 } 101 }
104 } 102 }
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs
index c05bbc442..1d0beb148 100644
--- a/crates/ra_hir/src/expr.rs
+++ b/crates/ra_hir/src/expr.rs
@@ -329,8 +329,6 @@ impl Expr {
329pub struct PatId(RawId); 329pub struct PatId(RawId);
330impl_arena_id!(PatId); 330impl_arena_id!(PatId);
331 331
332// copied verbatim from librustc::hir
333
334/// Explicit binding annotations given in the HIR for a binding. Note 332/// Explicit binding annotations given in the HIR for a binding. Note
335/// that this is not the final binding *mode* that we infer after type 333/// that this is not the final binding *mode* that we infer after type
336/// inference. 334/// inference.
@@ -341,8 +339,6 @@ pub enum BindingAnnotation {
341 /// when matching. For example, the `x` in `Some(x)` will have binding 339 /// when matching. For example, the `x` in `Some(x)` will have binding
342 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will 340 /// mode `None`; if you do `let Some(x) = &Some(22)`, it will
343 /// ultimately be inferred to be by-reference. 341 /// ultimately be inferred to be by-reference.
344 ///
345 /// Note that implicit reference skipping is not implemented yet (#42640).
346 Unannotated, 342 Unannotated,
347 343
348 /// Annotated with `mut x` -- could be either ref or not, similar to `None`. 344 /// Annotated with `mut x` -- could be either ref or not, similar to `None`.
@@ -375,7 +371,7 @@ pub struct FieldPat {
375/// Close relative to rustc's hir::PatKind 371/// Close relative to rustc's hir::PatKind
376#[derive(Debug, Clone, Eq, PartialEq)] 372#[derive(Debug, Clone, Eq, PartialEq)]
377pub enum Pat { 373pub enum Pat {
378 Missing, // do we need this? 374 Missing,
379 Wild, 375 Wild,
380 Tuple(Vec<PatId>), 376 Tuple(Vec<PatId>),
381 Struct { 377 Struct {
@@ -387,7 +383,6 @@ pub enum Pat {
387 start: ExprId, 383 start: ExprId,
388 end: ExprId, 384 end: ExprId,
389 }, 385 },
390 Box(PatId),
391 Slice { 386 Slice {
392 prefix: Vec<PatId>, 387 prefix: Vec<PatId>,
393 rest: Option<PatId>, 388 rest: Option<PatId>,
@@ -420,7 +415,7 @@ impl Pat {
420 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => { 415 Pat::Tuple(args) | Pat::TupleStruct { args, .. } => {
421 args.iter().map(|pat| *pat).for_each(f); 416 args.iter().map(|pat| *pat).for_each(f);
422 } 417 }
423 Pat::Ref { pat, .. } | Pat::Box(pat) => f(*pat), 418 Pat::Ref { pat, .. } => f(*pat),
424 Pat::Slice { 419 Pat::Slice {
425 prefix, 420 prefix,
426 rest, 421 rest,
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs
index 53b7b5836..09b816cc7 100644
--- a/crates/ra_hir/src/ty.rs
+++ b/crates/ra_hir/src/ty.rs
@@ -37,7 +37,7 @@ use crate::{
37 db::HirDatabase, 37 db::HirDatabase,
38 type_ref::{TypeRef, Mutability}, 38 type_ref::{TypeRef, Mutability},
39 name::KnownName, 39 name::KnownName,
40 expr::{Body, Expr, BindingAnnotation, MatchArm, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat}, 40 expr::{Body, Expr, BindingAnnotation, Literal, ExprId, Pat, PatId, UnaryOp, BinaryOp, Statement, FieldPat},
41}; 41};
42 42
43/// The ID of a type variable. 43/// The ID of a type variable.
@@ -874,15 +874,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
874 } 874 }
875 875
876 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> { 876 fn resolve_fields(&self, path: Option<&Path>) -> Option<(Ty, Vec<StructField>)> {
877 let def = path 877 let def_id = self.module.resolve_path(self.db, path?).take_types()?;
878 .and_then(|path| self.module.resolve_path(self.db, &path).take_types()) 878 let def = def_id.resolve(self.db);
879 .map(|def_id| def_id.resolve(self.db));
880
881 let def = if let Some(def) = def {
882 def
883 } else {
884 return None;
885 };
886 879
887 match def { 880 match def {
888 Def::Struct(s) => { 881 Def::Struct(s) => {
@@ -891,60 +884,47 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
891 .struct_data(s.def_id()) 884 .struct_data(s.def_id())
892 .variant_data 885 .variant_data
893 .fields() 886 .fields()
894 .iter() 887 .to_owned();
895 .cloned()
896 .collect();
897 Some((type_for_struct(self.db, s), fields)) 888 Some((type_for_struct(self.db, s), fields))
898 } 889 }
899 Def::EnumVariant(ev) => { 890 Def::EnumVariant(ev) => {
900 let fields: Vec<_> = ev.variant_data(self.db).fields().iter().cloned().collect(); 891 let fields: Vec<_> = ev.variant_data(self.db).fields().to_owned();
901 Some((type_for_enum_variant(self.db, ev), fields)) 892 Some((type_for_enum_variant(self.db, ev), fields))
902 } 893 }
903 _ => None, 894 _ => None,
904 } 895 }
905 } 896 }
906 897
907 fn infer_tuple_struct(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty { 898 fn infer_tuple_struct_pat(&mut self, path: Option<&Path>, subpats: &[PatId]) -> Ty {
908 let (ty, fields) = if let Some(x) = self.resolve_fields(path) { 899 let (ty, fields) = self
909 x 900 .resolve_fields(path)
910 } else { 901 .unwrap_or((Ty::Unknown, Vec::new()));
911 return Ty::Unknown;
912 };
913
914 if fields.len() != subpats.len() {
915 return Ty::Unknown;
916 }
917 902
918 for (&subpat, field) in subpats.iter().zip(fields.iter()) { 903 for (i, &subpat) in subpats.iter().enumerate() {
919 let sub_ty = self.make_ty(&field.type_ref); 904 let expected_ty = fields
920 self.infer_pat(subpat, &Expectation::has_type(sub_ty)); 905 .get(i)
906 .map_or(Ty::Unknown, |field| self.make_ty(&field.type_ref));
907 self.infer_pat(subpat, &Expectation::has_type(expected_ty));
921 } 908 }
922 909
923 ty 910 ty
924 } 911 }
925 912
926 fn infer_struct(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty { 913 fn infer_struct_pat(&mut self, path: Option<&Path>, subpats: &[FieldPat]) -> Ty {
927 let (ty, fields) = if let Some(x) = self.resolve_fields(path) { 914 let (ty, fields) = self
928 x 915 .resolve_fields(path)
929 } else { 916 .unwrap_or((Ty::Unknown, Vec::new()));
930 return Ty::Unknown;
931 };
932 917
933 for subpat in subpats { 918 for subpat in subpats {
934 let matching_field = fields.iter().find(|field| field.name == subpat.name); 919 let matching_field = fields.iter().find(|field| field.name == subpat.name);
935 920 let expected_ty =
936 if let Some(field) = matching_field { 921 matching_field.map_or(Ty::Unknown, |field| self.make_ty(&field.type_ref));
937 let typeref = &field.type_ref; 922 self.infer_pat(subpat.pat, &Expectation::has_type(expected_ty));
938 let sub_ty = self.make_ty(typeref);
939 self.infer_pat(subpat.pat, &Expectation::has_type(sub_ty));
940 }
941 } 923 }
942 924
943 ty 925 ty
944 } 926 }
945 927
946 // TODO: Expectation should probably contain a Cow pointer to Ty?
947 // so that we can make new expectations of subtypes cheaply
948 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty { 928 fn infer_pat(&mut self, pat: PatId, expected: &Expectation) -> Ty {
949 let body = Arc::clone(&self.body); // avoid borrow checker problem 929 let body = Arc::clone(&self.body); // avoid borrow checker problem
950 930
@@ -969,7 +949,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
969 } 949 }
970 Pat::Ref { pat, mutability } => { 950 Pat::Ref { pat, mutability } => {
971 let expectation = match expected.ty { 951 let expectation = match expected.ty {
972 Ty::Ref(ref sub_ty, exp_mut) if *mutability == exp_mut => { 952 Ty::Ref(ref sub_ty, exp_mut) => {
953 if *mutability != exp_mut {
954 // TODO: emit type error?
955 }
973 Expectation::has_type((&**sub_ty).clone()) 956 Expectation::has_type((&**sub_ty).clone())
974 } 957 }
975 _ => Expectation::none(), 958 _ => Expectation::none(),
@@ -980,18 +963,16 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
980 Pat::TupleStruct { 963 Pat::TupleStruct {
981 path: ref p, 964 path: ref p,
982 args: ref subpats, 965 args: ref subpats,
983 } => self.infer_tuple_struct(p.as_ref(), subpats), 966 } => self.infer_tuple_struct_pat(p.as_ref(), subpats),
984 Pat::Struct { 967 Pat::Struct {
985 path: ref p, 968 path: ref p,
986 args: ref fields, 969 args: ref fields,
987 } => self.infer_struct(p.as_ref(), fields), 970 } => self.infer_struct_pat(p.as_ref(), fields),
988 Pat::Path(path) => { 971 Pat::Path(path) => self
989 // is this right? 972 .module
990 self.module 973 .resolve_path(self.db, &path)
991 .resolve_path(self.db, &path) 974 .take_values()
992 .take_values() 975 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved)),
993 .map_or(Ty::Unknown, |resolved| self.db.type_for_def(resolved))
994 }
995 Pat::Bind { 976 Pat::Bind {
996 mode, 977 mode,
997 name: _name, 978 name: _name,
@@ -1000,10 +981,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1000 let subty = if let Some(subpat) = subpat { 981 let subty = if let Some(subpat) = subpat {
1001 self.infer_pat(*subpat, expected) 982 self.infer_pat(*subpat, expected)
1002 } else { 983 } else {
1003 let ty = self.new_type_var(); 984 expected.ty.clone()
1004 self.unify(&ty, &expected.ty);
1005 let ty = self.resolve_ty_as_possible(ty);
1006 ty
1007 }; 985 };
1008 986
1009 match mode { 987 match mode {
@@ -1075,8 +1053,8 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1075 assert_eq!(args.len(), arg_types.len()); 1053 assert_eq!(args.len(), arg_types.len());
1076 1054
1077 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) { 1055 for (arg_pat, arg_type) in args.iter().zip(arg_types.iter()) {
1078 let expected = if let Some(tyref) = arg_type { 1056 let expected = if let Some(type_ref) = arg_type {
1079 let ty = self.make_ty(tyref); 1057 let ty = self.make_ty(type_ref);
1080 Expectation::has_type(ty) 1058 Expectation::has_type(ty)
1081 } else { 1059 } else {
1082 Expectation::none() 1060 Expectation::none()
@@ -1143,21 +1121,20 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1143 ret_ty 1121 ret_ty
1144 } 1122 }
1145 Expr::Match { expr, arms } => { 1123 Expr::Match { expr, arms } => {
1146 let mut expected = expected.clone(); 1124 let expected = if expected.ty == Ty::Unknown {
1125 Expectation::has_type(self.new_type_var())
1126 } else {
1127 expected.clone()
1128 };
1147 let input_ty = self.infer_expr(*expr, &Expectation::none()); 1129 let input_ty = self.infer_expr(*expr, &Expectation::none());
1148 let pat_expectation = Expectation::has_type(input_ty); 1130 let pat_expectation = Expectation::has_type(input_ty);
1149 1131
1150 for MatchArm { 1132 for arm in arms {
1151 pats, 1133 for &pat in &arm.pats {
1152 expr: arm_expr,
1153 } in arms
1154 {
1155 for &pat in pats {
1156 let _pat_ty = self.infer_pat(pat, &pat_expectation); 1134 let _pat_ty = self.infer_pat(pat, &pat_expectation);
1157 } 1135 }
1158 // TODO type the guard 1136 // TODO type the guard
1159 let ty = self.infer_expr(*arm_expr, &expected); 1137 self.infer_expr(arm.expr, &expected);
1160 expected = Expectation::has_type(ty);
1161 } 1138 }
1162 1139
1163 expected.ty 1140 expected.ty