aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r--crates/ra_hir/src/ty/autoderef.rs2
-rw-r--r--crates/ra_hir/src/ty/infer.rs14
-rw-r--r--crates/ra_hir/src/ty/infer/unify.rs2
-rw-r--r--crates/ra_hir/src/ty/lower.rs86
-rw-r--r--crates/ra_hir/src/ty/tests.rs124
-rw-r--r--crates/ra_hir/src/ty/traits.rs17
-rw-r--r--crates/ra_hir/src/ty/traits/chalk.rs8
7 files changed, 207 insertions, 46 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs
index 2535d4ae7..08f52a53b 100644
--- a/crates/ra_hir/src/ty/autoderef.rs
+++ b/crates/ra_hir/src/ty/autoderef.rs
@@ -7,7 +7,7 @@ use std::iter::successors;
7 7
8use log::{info, warn}; 8use log::{info, warn};
9 9
10use super::{traits::Solution, Canonical, Ty}; 10use super::{traits::Solution, Canonical, Ty, TypeWalk};
11use crate::{HasGenericParams, HirDatabase, Name, Resolver}; 11use crate::{HasGenericParams, HirDatabase, Name, Resolver};
12 12
13const AUTODEREF_RECURSION_LIMIT: usize = 10; 13const AUTODEREF_RECURSION_LIMIT: usize = 10;
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs
index 812990426..ec3b7ffef 100644
--- a/crates/ra_hir/src/ty/infer.rs
+++ b/crates/ra_hir/src/ty/infer.rs
@@ -30,7 +30,7 @@ use super::{
30 autoderef, lower, method_resolution, op, primitive, 30 autoderef, lower, method_resolution, op, primitive,
31 traits::{Guidance, Obligation, ProjectionPredicate, Solution}, 31 traits::{Guidance, Obligation, ProjectionPredicate, Solution},
32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef, 32 ApplicationTy, CallableDef, InEnvironment, ProjectionTy, Substs, TraitEnvironment, TraitRef,
33 Ty, TypableDef, TypeCtor, 33 Ty, TypableDef, TypeCtor, TypeWalk,
34}; 34};
35use crate::{ 35use crate::{
36 adt::VariantDef, 36 adt::VariantDef,
@@ -50,8 +50,8 @@ use crate::{
50 }, 50 },
51 ty::infer::diagnostics::InferenceDiagnostic, 51 ty::infer::diagnostics::InferenceDiagnostic,
52 type_ref::{Mutability, TypeRef}, 52 type_ref::{Mutability, TypeRef},
53 AdtDef, ConstData, DefWithBody, FnData, Function, HirDatabase, ImplItem, ModuleDef, Name, Path, 53 AdtDef, ConstData, DefWithBody, FnData, Function, HasBody, HirDatabase, ImplItem, ModuleDef,
54 StructField, 54 Name, Path, StructField,
55}; 55};
56 56
57mod unify; 57mod unify;
@@ -749,7 +749,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
749 let is_non_ref_pat = match &body[pat] { 749 let is_non_ref_pat = match &body[pat] {
750 Pat::Tuple(..) 750 Pat::Tuple(..)
751 | Pat::TupleStruct { .. } 751 | Pat::TupleStruct { .. }
752 | Pat::Struct { .. } 752 | Pat::Record { .. }
753 | Pat::Range { .. } 753 | Pat::Range { .. }
754 | Pat::Slice { .. } => true, 754 | Pat::Slice { .. } => true,
755 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented. 755 // FIXME: Path/Lit might actually evaluate to ref, but inference is unimplemented.
@@ -806,10 +806,10 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
806 let subty = self.infer_pat(*pat, expectation, default_bm); 806 let subty = self.infer_pat(*pat, expectation, default_bm);
807 Ty::apply_one(TypeCtor::Ref(*mutability), subty) 807 Ty::apply_one(TypeCtor::Ref(*mutability), subty)
808 } 808 }
809 Pat::TupleStruct { path: ref p, args: ref subpats } => { 809 Pat::TupleStruct { path: p, args: subpats } => {
810 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm) 810 self.infer_tuple_struct_pat(p.as_ref(), subpats, expected, default_bm)
811 } 811 }
812 Pat::Struct { path: ref p, args: ref fields } => { 812 Pat::Record { path: p, args: fields } => {
813 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 813 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat)
814 } 814 }
815 Pat::Path(path) => { 815 Pat::Path(path) => {
@@ -817,7 +817,7 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> {
817 let resolver = self.resolver.clone(); 817 let resolver = self.resolver.clone();
818 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown) 818 self.infer_path_expr(&resolver, &path, pat.into()).unwrap_or(Ty::Unknown)
819 } 819 }
820 Pat::Bind { mode, name: _name, subpat } => { 820 Pat::Bind { mode, name: _, subpat } => {
821 let mode = if mode == &BindingAnnotation::Unannotated { 821 let mode = if mode == &BindingAnnotation::Unannotated {
822 default_bm 822 default_bm
823 } else { 823 } else {
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs
index e7e8825d1..9a0d2d8f9 100644
--- a/crates/ra_hir/src/ty/infer/unify.rs
+++ b/crates/ra_hir/src/ty/infer/unify.rs
@@ -3,7 +3,7 @@
3use super::{InferenceContext, Obligation}; 3use super::{InferenceContext, Obligation};
4use crate::db::HirDatabase; 4use crate::db::HirDatabase;
5use crate::ty::{ 5use crate::ty::{
6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, 6 Canonical, InEnvironment, InferTy, ProjectionPredicate, ProjectionTy, TraitRef, Ty, TypeWalk,
7}; 7};
8 8
9impl<'a, D: HirDatabase> InferenceContext<'a, D> { 9impl<'a, D: HirDatabase> InferenceContext<'a, D> {
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs
index 47d161277..f6f0137cf 100644
--- a/crates/ra_hir/src/ty/lower.rs
+++ b/crates/ra_hir/src/ty/lower.rs
@@ -8,7 +8,10 @@
8use std::iter; 8use std::iter;
9use std::sync::Arc; 9use std::sync::Arc;
10 10
11use super::{FnSig, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor}; 11use super::{
12 FnSig, GenericPredicate, ProjectionPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
13 TypeWalk,
14};
12use crate::{ 15use crate::{
13 adt::VariantDef, 16 adt::VariantDef,
14 generics::HasGenericParams, 17 generics::HasGenericParams,
@@ -62,7 +65,9 @@ impl Ty {
62 let self_ty = Ty::Bound(0); 65 let self_ty = Ty::Bound(0);
63 let predicates = bounds 66 let predicates = bounds
64 .iter() 67 .iter()
65 .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) 68 .flat_map(|b| {
69 GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())
70 })
66 .collect::<Vec<_>>(); 71 .collect::<Vec<_>>();
67 Ty::Dyn(predicates.into()) 72 Ty::Dyn(predicates.into())
68 } 73 }
@@ -70,7 +75,9 @@ impl Ty {
70 let self_ty = Ty::Bound(0); 75 let self_ty = Ty::Bound(0);
71 let predicates = bounds 76 let predicates = bounds
72 .iter() 77 .iter()
73 .map(|b| GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())) 78 .flat_map(|b| {
79 GenericPredicate::from_type_bound(db, resolver, b, self_ty.clone())
80 })
74 .collect::<Vec<_>>(); 81 .collect::<Vec<_>>();
75 Ty::Opaque(predicates.into()) 82 Ty::Opaque(predicates.into())
76 } 83 }
@@ -326,15 +333,6 @@ impl TraitRef {
326 TraitRef { trait_, substs } 333 TraitRef { trait_, substs }
327 } 334 }
328 335
329 pub(crate) fn from_where_predicate(
330 db: &impl HirDatabase,
331 resolver: &Resolver,
332 pred: &WherePredicate,
333 ) -> Option<TraitRef> {
334 let self_ty = Ty::from_hir(db, resolver, &pred.type_ref);
335 TraitRef::from_type_bound(db, resolver, &pred.bound, self_ty)
336 }
337
338 pub(crate) fn from_type_bound( 336 pub(crate) fn from_type_bound(
339 db: &impl HirDatabase, 337 db: &impl HirDatabase,
340 resolver: &Resolver, 338 resolver: &Resolver,
@@ -349,26 +347,58 @@ impl TraitRef {
349} 347}
350 348
351impl GenericPredicate { 349impl GenericPredicate {
352 pub(crate) fn from_where_predicate( 350 pub(crate) fn from_where_predicate<'a>(
353 db: &impl HirDatabase, 351 db: &'a impl HirDatabase,
354 resolver: &Resolver, 352 resolver: &'a Resolver,
355 where_predicate: &WherePredicate, 353 where_predicate: &'a WherePredicate,
356 ) -> GenericPredicate { 354 ) -> impl Iterator<Item = GenericPredicate> + 'a {
357 TraitRef::from_where_predicate(db, &resolver, where_predicate) 355 let self_ty = Ty::from_hir(db, resolver, &where_predicate.type_ref);
358 .map_or(GenericPredicate::Error, GenericPredicate::Implemented) 356 GenericPredicate::from_type_bound(db, resolver, &where_predicate.bound, self_ty)
359 } 357 }
360 358
361 pub(crate) fn from_type_bound( 359 pub(crate) fn from_type_bound<'a>(
362 db: &impl HirDatabase, 360 db: &'a impl HirDatabase,
363 resolver: &Resolver, 361 resolver: &'a Resolver,
364 bound: &TypeBound, 362 bound: &'a TypeBound,
365 self_ty: Ty, 363 self_ty: Ty,
366 ) -> GenericPredicate { 364 ) -> impl Iterator<Item = GenericPredicate> + 'a {
367 TraitRef::from_type_bound(db, &resolver, bound, self_ty) 365 let trait_ref = TraitRef::from_type_bound(db, &resolver, bound, self_ty);
368 .map_or(GenericPredicate::Error, GenericPredicate::Implemented) 366 iter::once(trait_ref.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented))
367 .chain(
368 trait_ref.into_iter().flat_map(move |tr| {
369 assoc_type_bindings_from_type_bound(db, resolver, bound, tr)
370 }),
371 )
369 } 372 }
370} 373}
371 374
375fn assoc_type_bindings_from_type_bound<'a>(
376 db: &'a impl HirDatabase,
377 resolver: &'a Resolver,
378 bound: &'a TypeBound,
379 trait_ref: TraitRef,
380) -> impl Iterator<Item = GenericPredicate> + 'a {
381 let last_segment = match bound {
382 TypeBound::Path(path) => path.segments.last(),
383 TypeBound::Error => None,
384 };
385 last_segment
386 .into_iter()
387 .flat_map(|segment| segment.args_and_bindings.iter())
388 .flat_map(|args_and_bindings| args_and_bindings.bindings.iter())
389 .map(move |(name, type_ref)| {
390 let associated_ty = match trait_ref.trait_.associated_type_by_name(db, name.clone()) {
391 None => return GenericPredicate::Error,
392 Some(t) => t,
393 };
394 let projection_ty =
395 ProjectionTy { associated_ty, parameters: trait_ref.substs.clone() };
396 let ty = Ty::from_hir(db, resolver, type_ref);
397 let projection_predicate = ProjectionPredicate { projection_ty, ty };
398 GenericPredicate::Projection(projection_predicate)
399 })
400}
401
372/// Build the declared type of an item. This depends on the namespace; e.g. for 402/// Build the declared type of an item. This depends on the namespace; e.g. for
373/// `struct Foo(usize)`, we have two types: The type of the struct itself, and 403/// `struct Foo(usize)`, we have two types: The type of the struct itself, and
374/// the constructor function `(usize) -> Foo` which lives in the values 404/// the constructor function `(usize) -> Foo` which lives in the values
@@ -425,7 +455,7 @@ pub(crate) fn trait_env(
425) -> Arc<super::TraitEnvironment> { 455) -> Arc<super::TraitEnvironment> {
426 let predicates = resolver 456 let predicates = resolver
427 .where_predicates_in_scope() 457 .where_predicates_in_scope()
428 .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) 458 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
429 .collect::<Vec<_>>(); 459 .collect::<Vec<_>>();
430 460
431 Arc::new(super::TraitEnvironment { predicates }) 461 Arc::new(super::TraitEnvironment { predicates })
@@ -439,7 +469,7 @@ pub(crate) fn generic_predicates_query(
439 let resolver = def.resolver(db); 469 let resolver = def.resolver(db);
440 let predicates = resolver 470 let predicates = resolver
441 .where_predicates_in_scope() 471 .where_predicates_in_scope()
442 .map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred)) 472 .flat_map(|pred| GenericPredicate::from_where_predicate(db, &resolver, pred))
443 .collect::<Vec<_>>(); 473 .collect::<Vec<_>>();
444 predicates.into() 474 predicates.into()
445} 475}
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs
index b034fd59e..d92d4659b 100644
--- a/crates/ra_hir/src/ty/tests.rs
+++ b/crates/ra_hir/src/ty/tests.rs
@@ -2793,6 +2793,10 @@ fn main() {
2793} 2793}
2794"#), 2794"#),
2795 @r###" 2795 @r###"
2796 ![0; 17) '{Foo(v...,2,])}': Foo
2797 ![1; 4) 'Foo': Foo({unknown}) -> Foo
2798 ![1; 16) 'Foo(vec![1,2,])': Foo
2799 ![5; 15) 'vec![1,2,]': {unknown}
2796 [156; 182) '{ ...,2); }': () 2800 [156; 182) '{ ...,2); }': ()
2797 [166; 167) 'x': Foo 2801 [166; 167) 'x': Foo
2798 "### 2802 "###
@@ -3548,6 +3552,97 @@ fn test() {
3548 ); 3552 );
3549} 3553}
3550 3554
3555#[test]
3556fn assoc_type_bindings() {
3557 assert_snapshot!(
3558 infer(r#"
3559trait Trait {
3560 type Type;
3561}
3562
3563fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
3564fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
3565fn set<T: Trait<Type = u64>>(t: T) -> T {t}
3566
3567struct S<T>;
3568impl<T> Trait for S<T> { type Type = T; }
3569
3570fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
3571 get(x);
3572 get2(x);
3573 get(y);
3574 get2(y);
3575 get(set(S));
3576 get2(set(S));
3577 get2(S::<str>);
3578}
3579"#),
3580 @r###"
3581 [50; 51) 't': T
3582 [78; 80) '{}': ()
3583 [112; 113) 't': T
3584 [123; 125) '{}': ()
3585 [155; 156) 't': T
3586 [166; 169) '{t}': T
3587 [167; 168) 't': T
3588 [257; 258) 'x': T
3589 [263; 264) 'y': impl Trait<Type = i64>
3590 [290; 398) '{ ...r>); }': ()
3591 [296; 299) 'get': fn get<T>(T) -> <T as Trait>::Type
3592 [296; 302) 'get(x)': {unknown}
3593 [300; 301) 'x': T
3594 [308; 312) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U
3595 [308; 315) 'get2(x)': {unknown}
3596 [313; 314) 'x': T
3597 [321; 324) 'get': fn get<impl Trait<Type = i64>>(T) -> <T as Trait>::Type
3598 [321; 327) 'get(y)': {unknown}
3599 [325; 326) 'y': impl Trait<Type = i64>
3600 [333; 337) 'get2': fn get2<{unknown}, S<{unknown}>>(T) -> U
3601 [333; 340) 'get2(y)': {unknown}
3602 [338; 339) 'y': impl Trait<Type = i64>
3603 [346; 349) 'get': fn get<S<u64>>(T) -> <T as Trait>::Type
3604 [346; 357) 'get(set(S))': u64
3605 [350; 353) 'set': fn set<S<u64>>(T) -> T
3606 [350; 356) 'set(S)': S<u64>
3607 [354; 355) 'S': S<u64>
3608 [363; 367) 'get2': fn get2<u64, S<u64>>(T) -> U
3609 [363; 375) 'get2(set(S))': u64
3610 [368; 371) 'set': fn set<S<u64>>(T) -> T
3611 [368; 374) 'set(S)': S<u64>
3612 [372; 373) 'S': S<u64>
3613 [381; 385) 'get2': fn get2<str, S<str>>(T) -> U
3614 [381; 395) 'get2(S::<str>)': str
3615 [386; 394) 'S::<str>': S<str>
3616 "###
3617 );
3618}
3619
3620#[test]
3621fn projection_eq_within_chalk() {
3622 // std::env::set_var("CHALK_DEBUG", "1");
3623 assert_snapshot!(
3624 infer(r#"
3625trait Trait1 {
3626 type Type;
3627}
3628trait Trait2<T> {
3629 fn foo(self) -> T;
3630}
3631impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
3632
3633fn test<T: Trait1<Type = u32>>(x: T) {
3634 x.foo();
3635}
3636"#),
3637 @r###"
3638 [62; 66) 'self': Self
3639 [164; 165) 'x': T
3640 [170; 186) '{ ...o(); }': ()
3641 [176; 177) 'x': T
3642 [176; 183) 'x.foo()': {unknown}
3643 "###
3644 );
3645}
3551fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { 3646fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String {
3552 let file = db.parse(pos.file_id).ok().unwrap(); 3647 let file = db.parse(pos.file_id).ok().unwrap();
3553 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); 3648 let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap();
@@ -3566,7 +3661,6 @@ fn infer(content: &str) -> String {
3566 let source_file = db.parse(file_id).ok().unwrap(); 3661 let source_file = db.parse(file_id).ok().unwrap();
3567 3662
3568 let mut acc = String::new(); 3663 let mut acc = String::new();
3569 // acc.push_str("\n");
3570 3664
3571 let mut infer_def = |inference_result: Arc<InferenceResult>, 3665 let mut infer_def = |inference_result: Arc<InferenceResult>,
3572 body_source_map: Arc<BodySourceMap>| { 3666 body_source_map: Arc<BodySourceMap>| {
@@ -3574,7 +3668,9 @@ fn infer(content: &str) -> String {
3574 3668
3575 for (pat, ty) in inference_result.type_of_pat.iter() { 3669 for (pat, ty) in inference_result.type_of_pat.iter() {
3576 let syntax_ptr = match body_source_map.pat_syntax(pat) { 3670 let syntax_ptr = match body_source_map.pat_syntax(pat) {
3577 Some(sp) => sp.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()), 3671 Some(sp) => {
3672 sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()))
3673 }
3578 None => continue, 3674 None => continue,
3579 }; 3675 };
3580 types.push((syntax_ptr, ty)); 3676 types.push((syntax_ptr, ty));
@@ -3582,22 +3678,34 @@ fn infer(content: &str) -> String {
3582 3678
3583 for (expr, ty) in inference_result.type_of_expr.iter() { 3679 for (expr, ty) in inference_result.type_of_expr.iter() {
3584 let syntax_ptr = match body_source_map.expr_syntax(expr) { 3680 let syntax_ptr = match body_source_map.expr_syntax(expr) {
3585 Some(sp) => sp, 3681 Some(sp) => {
3682 sp.map(|ast| ast.either(|it| it.syntax_node_ptr(), |it| it.syntax_node_ptr()))
3683 }
3586 None => continue, 3684 None => continue,
3587 }; 3685 };
3588 types.push((syntax_ptr, ty)); 3686 types.push((syntax_ptr, ty));
3589 } 3687 }
3590 3688
3591 // sort ranges for consistency 3689 // sort ranges for consistency
3592 types.sort_by_key(|(ptr, _)| (ptr.range().start(), ptr.range().end())); 3690 types.sort_by_key(|(src_ptr, _)| (src_ptr.ast.range().start(), src_ptr.ast.range().end()));
3593 for (syntax_ptr, ty) in &types { 3691 for (src_ptr, ty) in &types {
3594 let node = syntax_ptr.to_node(source_file.syntax()); 3692 let node = src_ptr.ast.to_node(&src_ptr.file_syntax(&db));
3693
3595 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) { 3694 let (range, text) = if let Some(self_param) = ast::SelfParam::cast(node.clone()) {
3596 (self_param.self_kw_token().text_range(), "self".to_string()) 3695 (self_param.self_kw_token().text_range(), "self".to_string())
3597 } else { 3696 } else {
3598 (syntax_ptr.range(), node.text().to_string().replace("\n", " ")) 3697 (src_ptr.ast.range(), node.text().to_string().replace("\n", " "))
3599 }; 3698 };
3600 write!(acc, "{} '{}': {}\n", range, ellipsize(text, 15), ty.display(&db)).unwrap(); 3699 let macro_prefix = if src_ptr.file_id != file_id.into() { "!" } else { "" };
3700 write!(
3701 acc,
3702 "{}{} '{}': {}\n",
3703 macro_prefix,
3704 range,
3705 ellipsize(text, 15),
3706 ty.display(&db)
3707 )
3708 .unwrap();
3601 } 3709 }
3602 }; 3710 };
3603 3711
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs
index b634f0b79..6e0271a96 100644
--- a/crates/ra_hir/src/ty/traits.rs
+++ b/crates/ra_hir/src/ty/traits.rs
@@ -8,7 +8,7 @@ use ra_db::salsa;
8use ra_prof::profile; 8use ra_prof::profile;
9use rustc_hash::FxHashSet; 9use rustc_hash::FxHashSet;
10 10
11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty}; 11use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk};
12use crate::{db::HirDatabase, Crate, ImplBlock, Trait}; 12use crate::{db::HirDatabase, Crate, ImplBlock, Trait};
13 13
14use self::chalk::{from_chalk, ToChalk}; 14use self::chalk::{from_chalk, ToChalk};
@@ -124,6 +124,9 @@ impl Obligation {
124 pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { 124 pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> {
125 match predicate { 125 match predicate {
126 GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), 126 GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)),
127 GenericPredicate::Projection(projection_pred) => {
128 Some(Obligation::Projection(projection_pred))
129 }
127 GenericPredicate::Error => None, 130 GenericPredicate::Error => None,
128 } 131 }
129 } 132 }
@@ -135,6 +138,18 @@ pub struct ProjectionPredicate {
135 pub ty: Ty, 138 pub ty: Ty,
136} 139}
137 140
141impl TypeWalk for ProjectionPredicate {
142 fn walk(&self, f: &mut impl FnMut(&Ty)) {
143 self.projection_ty.walk(f);
144 self.ty.walk(f);
145 }
146
147 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
148 self.projection_ty.walk_mut(f);
149 self.ty.walk_mut(f);
150 }
151}
152
138/// Solve a trait goal using Chalk. 153/// Solve a trait goal using Chalk.
139pub(crate) fn trait_solve_query( 154pub(crate) fn trait_solve_query(
140 db: &impl HirDatabase, 155 db: &impl HirDatabase,
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs
index 2ebc06135..c201c5e50 100644
--- a/crates/ra_hir/src/ty/traits/chalk.rs
+++ b/crates/ra_hir/src/ty/traits/chalk.rs
@@ -19,6 +19,7 @@ use crate::{
19 ty::display::HirDisplay, 19 ty::display::HirDisplay,
20 ty::{ 20 ty::{
21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, 21 ApplicationTy, CallableDef, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor,
22 TypeWalk,
22 }, 23 },
23 Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias, 24 Crate, HasGenericParams, ImplBlock, ImplItem, Trait, TypeAlias,
24}; 25};
@@ -211,6 +212,13 @@ impl ToChalk for GenericPredicate {
211 GenericPredicate::Implemented(trait_ref) => { 212 GenericPredicate::Implemented(trait_ref) => {
212 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0) 213 make_binders(chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)), 0)
213 } 214 }
215 GenericPredicate::Projection(projection_pred) => make_binders(
216 chalk_ir::WhereClause::ProjectionEq(chalk_ir::ProjectionEq {
217 projection: projection_pred.projection_ty.to_chalk(db),
218 ty: projection_pred.ty.to_chalk(db),
219 }),
220 0,
221 ),
214 GenericPredicate::Error => { 222 GenericPredicate::Error => {
215 let impossible_trait_ref = chalk_ir::TraitRef { 223 let impossible_trait_ref = chalk_ir::TraitRef {
216 trait_id: UNKNOWN_TRAIT, 224 trait_id: UNKNOWN_TRAIT,