aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty/infer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty/infer.rs')
-rw-r--r--crates/ra_hir/src/ty/infer.rs124
1 files changed, 91 insertions, 33 deletions
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index e79e5e223..973de70df 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -28,24 +28,28 @@ use test_utils::tested_by;
28 28
29use super::{ 29use super::{
30 autoderef, method_resolution, op, primitive, 30 autoderef, method_resolution, op, primitive,
31 traits::{Guidance, Obligation, Solution}, 31 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
32 ApplicationTy, CallableDef, Substs, TraitRef, Ty, TypableDef, TypeCtor, 32 ApplicationTy, CallableDef, ProjectionTy, Substs, TraitRef, Ty, TypableDef, TypeCtor,
33}; 33};
34use crate::{ 34use crate::{
35 adt::VariantDef, 35 adt::VariantDef,
36 code_model::{ModuleDef::Trait, TypeAlias},
36 diagnostics::DiagnosticSink, 37 diagnostics::DiagnosticSink,
37 expr::{ 38 expr::{
38 self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, FieldPat, Literal, Pat, 39 self, Array, BinaryOp, BindingAnnotation, Body, Expr, ExprId, FieldPat, Literal, Pat,
39 PatId, Statement, UnaryOp, 40 PatId, Statement, UnaryOp,
40 }, 41 },
41 generics::{GenericParams, HasGenericParams}, 42 generics::{GenericParams, HasGenericParams},
42 nameres::Namespace, 43 nameres::{Namespace, PerNs},
43 path::{GenericArg, GenericArgs}, 44 path::{GenericArg, GenericArgs, PathKind, PathSegment},
44 resolve::{Resolution, Resolver}, 45 resolve::{
46 Resolution::{self, Def},
47 Resolver,
48 },
45 ty::infer::diagnostics::InferenceDiagnostic, 49 ty::infer::diagnostics::InferenceDiagnostic,
46 type_ref::{Mutability, TypeRef}, 50 type_ref::{Mutability, TypeRef},
47 AdtDef, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, ModuleDef, Name, Path, 51 AdtDef, AsName, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, KnownName,
48 StructField, 52 ModuleDef, Name, Path, StructField,
49}; 53};
50 54
51mod unify; 55mod unify;
@@ -323,34 +327,53 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
323 fn resolve_obligations_as_possible(&mut self) { 327 fn resolve_obligations_as_possible(&mut self) {
324 let obligations = mem::replace(&mut self.obligations, Vec::new()); 328 let obligations = mem::replace(&mut self.obligations, Vec::new());
325 for obligation in obligations { 329 for obligation in obligations {
326 let (solution, canonicalized) = match &obligation { 330 match &obligation {
327 Obligation::Trait(tr) => { 331 Obligation::Trait(tr) => {
328 let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone()); 332 let canonicalized = self.canonicalizer().canonicalize_trait_ref(tr.clone());
329 ( 333 let solution = self
330 self.db.implements( 334 .db
331 self.resolver.krate().unwrap(), 335 .implements(self.resolver.krate().unwrap(), canonicalized.value.clone());
332 canonicalized.value.clone(), 336 match solution {
333 ), 337 Some(Solution::Unique(substs)) => {
334 canonicalized, 338 canonicalized.apply_solution(self, substs.0);
335 ) 339 }
336 } 340 Some(Solution::Ambig(Guidance::Definite(substs))) => {
337 }; 341 canonicalized.apply_solution(self, substs.0);
338 match solution { 342 self.obligations.push(obligation);
339 Some(Solution::Unique(substs)) => { 343 }
340 canonicalized.apply_solution(self, substs.0); 344 Some(_) => {
341 } 345 // FIXME use this when trying to resolve everything at the end
342 Some(Solution::Ambig(Guidance::Definite(substs))) => { 346 self.obligations.push(obligation);
343 canonicalized.apply_solution(self, substs.0); 347 }
344 self.obligations.push(obligation); 348 None => {
345 } 349 // FIXME obligation cannot be fulfilled => diagnostic
346 Some(_) => { 350 }
347 // FIXME use this when trying to resolve everything at the end 351 };
348 self.obligations.push(obligation);
349 } 352 }
350 None => { 353 Obligation::Projection(pr) => {
351 // FIXME obligation cannot be fulfilled => diagnostic 354 let canonicalized = self.canonicalizer().canonicalize_projection(pr.clone());
355 let solution = self
356 .db
357 .normalize(self.resolver.krate().unwrap(), canonicalized.value.clone());
358
359 match solution {
360 Some(Solution::Unique(substs)) => {
361 canonicalized.apply_solution(self, substs.0);
362 }
363 Some(Solution::Ambig(Guidance::Definite(substs))) => {
364 canonicalized.apply_solution(self, substs.0);
365 self.obligations.push(obligation);
366 }
367 Some(_) => {
368 // FIXME use this when trying to resolve everything at the end
369 self.obligations.push(obligation);
370 }
371 None => {
372 // FIXME obligation cannot be fulfilled => diagnostic
373 }
374 };
352 } 375 }
353 } 376 };
354 } 377 }
355 } 378 }
356 379
@@ -967,8 +990,25 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
967 Ty::unit() 990 Ty::unit()
968 } 991 }
969 Expr::For { iterable, body, pat } => { 992 Expr::For { iterable, body, pat } => {
970 let _iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 993 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
971 self.infer_pat(*pat, &Ty::Unknown, BindingMode::default()); 994
995 let pat_ty = match self.resolve_into_iter_item() {
996 Some(into_iter_item_alias) => {
997 let pat_ty = self.new_type_var();
998 let projection = ProjectionPredicate {
999 ty: pat_ty.clone(),
1000 projection_ty: ProjectionTy {
1001 associated_ty: into_iter_item_alias,
1002 parameters: vec![iterable_ty].into(),
1003 },
1004 };
1005 self.obligations.push(Obligation::Projection(projection));
1006 self.resolve_ty_as_possible(&mut vec![], pat_ty)
1007 }
1008 None => Ty::Unknown,
1009 };
1010
1011 self.infer_pat(*pat, &pat_ty, BindingMode::default());
972 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 1012 self.infer_expr(*body, &Expectation::has_type(Ty::unit()));
973 Ty::unit() 1013 Ty::unit()
974 } 1014 }
@@ -1301,6 +1341,24 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
1301 fn infer_body(&mut self) { 1341 fn infer_body(&mut self) {
1302 self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone())); 1342 self.infer_expr(self.body.body_expr(), &Expectation::has_type(self.return_ty.clone()));
1303 } 1343 }
1344
1345 fn resolve_into_iter_item(&self) -> Option<TypeAlias> {
1346 let into_iter_path = Path {
1347 kind: PathKind::Abs,
1348 segments: vec![
1349 PathSegment { name: KnownName::Std.as_name(), args_and_bindings: None },
1350 PathSegment { name: KnownName::Iter.as_name(), args_and_bindings: None },
1351 PathSegment { name: KnownName::IntoIterator.as_name(), args_and_bindings: None },
1352 ],
1353 };
1354
1355 match self.resolver.resolve_path_segments(self.db, &into_iter_path).into_fully_resolved() {
1356 PerNs { types: Some(Def(Trait(trait_))), .. } => {
1357 Some(trait_.associated_type_by_name(self.db, KnownName::Item.as_name())?)
1358 }
1359 _ => None,
1360 }
1361 }
1304} 1362}
1305 1363
1306/// The ID of a type variable. 1364/// The ID of a type variable.