diff options
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 49 |
1 files changed, 41 insertions, 8 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index 52a49070a..827addddd 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -40,7 +40,7 @@ use crate::{ | |||
40 | PatId, Statement, UnaryOp, | 40 | PatId, Statement, UnaryOp, |
41 | }, | 41 | }, |
42 | generics::{GenericParams, HasGenericParams}, | 42 | generics::{GenericParams, HasGenericParams}, |
43 | name::{INTO_ITERATOR, ITEM, ITER, SELF_TYPE, STD}, | 43 | name, |
44 | nameres::{Namespace, PerNs}, | 44 | nameres::{Namespace, PerNs}, |
45 | path::{GenericArg, GenericArgs, PathKind, PathSegment}, | 45 | path::{GenericArg, GenericArgs, PathKind, PathSegment}, |
46 | resolve::{ | 46 | resolve::{ |
@@ -843,7 +843,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
843 | // Parent arguments are unknown, except for the receiver type | 843 | // Parent arguments are unknown, except for the receiver type |
844 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { | 844 | if let Some(parent_generics) = def_generics.and_then(|p| p.parent_params.clone()) { |
845 | for param in &parent_generics.params { | 845 | for param in &parent_generics.params { |
846 | if param.name == SELF_TYPE { | 846 | if param.name == name::SELF_TYPE { |
847 | substs.push(receiver_ty.clone()); | 847 | substs.push(receiver_ty.clone()); |
848 | } else { | 848 | } else { |
849 | substs.push(Ty::Unknown); | 849 | substs.push(Ty::Unknown); |
@@ -1140,8 +1140,23 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1140 | self.insert_type_vars(ty) | 1140 | self.insert_type_vars(ty) |
1141 | } | 1141 | } |
1142 | Expr::Try { expr } => { | 1142 | Expr::Try { expr } => { |
1143 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1143 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
1144 | Ty::Unknown | 1144 | let ty = match self.resolve_ops_try_ok() { |
1145 | Some(ops_try_ok_alias) => { | ||
1146 | let ty = self.new_type_var(); | ||
1147 | let projection = ProjectionPredicate { | ||
1148 | ty: ty.clone(), | ||
1149 | projection_ty: ProjectionTy { | ||
1150 | associated_ty: ops_try_ok_alias, | ||
1151 | parameters: vec![inner_ty].into(), | ||
1152 | }, | ||
1153 | }; | ||
1154 | self.obligations.push(Obligation::Projection(projection)); | ||
1155 | self.resolve_ty_as_possible(&mut vec![], ty) | ||
1156 | } | ||
1157 | None => Ty::Unknown, | ||
1158 | }; | ||
1159 | ty | ||
1145 | } | 1160 | } |
1146 | Expr::Cast { expr, type_ref } => { | 1161 | Expr::Cast { expr, type_ref } => { |
1147 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1162 | let _inner_ty = self.infer_expr(*expr, &Expectation::none()); |
@@ -1347,15 +1362,33 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1347 | let into_iter_path = Path { | 1362 | let into_iter_path = Path { |
1348 | kind: PathKind::Abs, | 1363 | kind: PathKind::Abs, |
1349 | segments: vec![ | 1364 | segments: vec![ |
1350 | PathSegment { name: STD, args_and_bindings: None }, | 1365 | PathSegment { name: name::STD, args_and_bindings: None }, |
1351 | PathSegment { name: ITER, args_and_bindings: None }, | 1366 | PathSegment { name: name::ITER, args_and_bindings: None }, |
1352 | PathSegment { name: INTO_ITERATOR, args_and_bindings: None }, | 1367 | PathSegment { name: name::INTO_ITERATOR, args_and_bindings: None }, |
1353 | ], | 1368 | ], |
1354 | }; | 1369 | }; |
1355 | 1370 | ||
1356 | match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() { | 1371 | match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() { |
1357 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | 1372 | PerNs { types: Some(Def(Trait(trait_))), .. } => { |
1358 | Some(trait_.associated_type_by_name(self.db, ITEM)?) | 1373 | Some(trait_.associated_type_by_name(self.db, name::ITEM)?) |
1374 | } | ||
1375 | _ => None, | ||
1376 | } | ||
1377 | } | ||
1378 | |||
1379 | fn resolve_ops_try_ok(&self) -> Option<TypeAlias> { | ||
1380 | let ops_try_path = Path { | ||
1381 | kind: PathKind::Abs, | ||
1382 | segments: vec![ | ||
1383 | PathSegment { name: name::STD, args_and_bindings: None }, | ||
1384 | PathSegment { name: name::OPS, args_and_bindings: None }, | ||
1385 | PathSegment { name: name::TRY, args_and_bindings: None }, | ||
1386 | ], | ||
1387 | }; | ||
1388 | |||
1389 | match self.resolver.resolve_path_segments(self.db, &ops_try_path).into_fully_resolved() { | ||
1390 | PerNs { types: Some(Def(Trait(trait_))), .. } => { | ||
1391 | Some(trait_.associated_type_by_name(self.db, name::OK)?) | ||
1359 | } | 1392 | } |
1360 | _ => None, | 1393 | _ => None, |
1361 | } | 1394 | } |