diff options
Diffstat (limited to 'crates/ra_hir/src/ty')
-rw-r--r-- | crates/ra_hir/src/ty/autoderef.rs | 89 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer.rs | 48 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 84 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 110 |
7 files changed, 327 insertions, 44 deletions
diff --git a/crates/ra_hir/src/ty/autoderef.rs b/crates/ra_hir/src/ty/autoderef.rs index a442a856c..1f443d49b 100644 --- a/crates/ra_hir/src/ty/autoderef.rs +++ b/crates/ra_hir/src/ty/autoderef.rs | |||
@@ -5,17 +5,88 @@ | |||
5 | 5 | ||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use crate::HirDatabase; | 8 | use log::{info, warn}; |
9 | use super::Ty; | ||
10 | 9 | ||
11 | impl Ty { | 10 | use crate::{HirDatabase, Name, Resolver, HasGenericParams}; |
12 | /// Iterates over the possible derefs of `ty`. | 11 | use super::{traits::Solution, Ty, Canonical}; |
13 | pub fn autoderef<'a>(self, db: &'a impl HirDatabase) -> impl Iterator<Item = Ty> + 'a { | 12 | |
14 | successors(Some(self), move |ty| ty.autoderef_step(db)) | 13 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
14 | |||
15 | pub(crate) fn autoderef<'a>( | ||
16 | db: &'a impl HirDatabase, | ||
17 | resolver: &'a Resolver, | ||
18 | ty: Canonical<Ty>, | ||
19 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | ||
20 | successors(Some(ty), move |ty| deref(db, resolver, ty)).take(AUTODEREF_RECURSION_LIMIT) | ||
21 | } | ||
22 | |||
23 | pub(crate) fn deref( | ||
24 | db: &impl HirDatabase, | ||
25 | resolver: &Resolver, | ||
26 | ty: &Canonical<Ty>, | ||
27 | ) -> Option<Canonical<Ty>> { | ||
28 | if let Some(derefed) = ty.value.builtin_deref() { | ||
29 | Some(Canonical { value: derefed, num_vars: ty.num_vars }) | ||
30 | } else { | ||
31 | deref_by_trait(db, resolver, ty) | ||
32 | } | ||
33 | } | ||
34 | |||
35 | fn deref_by_trait( | ||
36 | db: &impl HirDatabase, | ||
37 | resolver: &Resolver, | ||
38 | ty: &Canonical<Ty>, | ||
39 | ) -> Option<Canonical<Ty>> { | ||
40 | let krate = resolver.krate()?; | ||
41 | let deref_trait = match db.lang_item(krate, "deref".into())? { | ||
42 | crate::lang_item::LangItemTarget::Trait(t) => t, | ||
43 | _ => return None, | ||
44 | }; | ||
45 | let target = deref_trait.associated_type_by_name(db, Name::target())?; | ||
46 | |||
47 | if target.generic_params(db).count_params_including_parent() != 1 { | ||
48 | // the Target type + Deref trait should only have one generic parameter, | ||
49 | // namely Deref's Self type | ||
50 | return None; | ||
15 | } | 51 | } |
16 | 52 | ||
17 | fn autoderef_step(&self, _db: &impl HirDatabase) -> Option<Ty> { | 53 | // FIXME make the Canonical handling nicer |
18 | // FIXME Deref::deref | 54 | |
19 | self.builtin_deref() | 55 | let projection = super::traits::ProjectionPredicate { |
56 | ty: Ty::Bound(0), | ||
57 | projection_ty: super::ProjectionTy { | ||
58 | associated_ty: target, | ||
59 | parameters: vec![ty.value.clone().shift_bound_vars(1)].into(), | ||
60 | }, | ||
61 | }; | ||
62 | |||
63 | let canonical = super::Canonical { num_vars: 1 + ty.num_vars, value: projection }; | ||
64 | |||
65 | let solution = db.normalize(krate, canonical)?; | ||
66 | |||
67 | match &solution { | ||
68 | Solution::Unique(vars) => { | ||
69 | // FIXME: vars may contain solutions for any inference variables | ||
70 | // that happened to be inside ty. To correctly handle these, we | ||
71 | // would have to pass the solution up to the inference context, but | ||
72 | // that requires a larger refactoring (especially if the deref | ||
73 | // happens during method resolution). So for the moment, we just | ||
74 | // check that we're not in the situation we're we would actually | ||
75 | // need to handle the values of the additional variables, i.e. | ||
76 | // they're just being 'passed through'. In the 'standard' case where | ||
77 | // we have `impl<T> Deref for Foo<T> { Target = T }`, that should be | ||
78 | // the case. | ||
79 | for i in 1..vars.0.num_vars { | ||
80 | if vars.0.value[i] != Ty::Bound((i - 1) as u32) { | ||
81 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty, solution); | ||
82 | return None; | ||
83 | } | ||
84 | } | ||
85 | Some(Canonical { value: vars.0.value[0].clone(), num_vars: vars.0.num_vars }) | ||
86 | } | ||
87 | Solution::Ambig(_) => { | ||
88 | info!("Ambiguous solution for derefing {:?}: {:?}", ty, solution); | ||
89 | None | ||
90 | } | ||
20 | } | 91 | } |
21 | } | 92 | } |
diff --git a/crates/ra_hir/src/ty/infer.rs b/crates/ra_hir/src/ty/infer.rs index e150d7fd8..1ee40c70a 100644 --- a/crates/ra_hir/src/ty/infer.rs +++ b/crates/ra_hir/src/ty/infer.rs | |||
@@ -46,7 +46,7 @@ use crate::{ | |||
46 | use super::{ | 46 | use super::{ |
47 | Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef, | 47 | Ty, TypableDef, Substs, primitive, op, ApplicationTy, TypeCtor, CallableDef, TraitRef, |
48 | traits::{Solution, Obligation, Guidance}, | 48 | traits::{Solution, Obligation, Guidance}, |
49 | method_resolution, | 49 | method_resolution, autoderef, |
50 | }; | 50 | }; |
51 | 51 | ||
52 | mod unify; | 52 | mod unify; |
@@ -1074,25 +1074,27 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1074 | } | 1074 | } |
1075 | Expr::Field { expr, name } => { | 1075 | Expr::Field { expr, name } => { |
1076 | let receiver_ty = self.infer_expr(*expr, &Expectation::none()); | 1076 | let receiver_ty = self.infer_expr(*expr, &Expectation::none()); |
1077 | let ty = receiver_ty | 1077 | let canonicalized = self.canonicalizer().canonicalize_ty(receiver_ty); |
1078 | .autoderef(self.db) | 1078 | let ty = autoderef::autoderef( |
1079 | .find_map(|derefed_ty| match derefed_ty { | 1079 | self.db, |
1080 | Ty::Apply(a_ty) => match a_ty.ctor { | 1080 | &self.resolver.clone(), |
1081 | TypeCtor::Tuple { .. } => { | 1081 | canonicalized.value.clone(), |
1082 | let i = name.to_string().parse::<usize>().ok(); | 1082 | ) |
1083 | i.and_then(|i| a_ty.parameters.0.get(i).cloned()) | 1083 | .find_map(|derefed_ty| match canonicalized.decanonicalize_ty(derefed_ty.value) { |
1084 | } | 1084 | Ty::Apply(a_ty) => match a_ty.ctor { |
1085 | TypeCtor::Adt(AdtDef::Struct(s)) => { | 1085 | TypeCtor::Tuple { .. } => { |
1086 | s.field(self.db, name).map(|field| { | 1086 | let i = name.to_string().parse::<usize>().ok(); |
1087 | self.write_field_resolution(tgt_expr, field); | 1087 | i.and_then(|i| a_ty.parameters.0.get(i).cloned()) |
1088 | field.ty(self.db).subst(&a_ty.parameters) | 1088 | } |
1089 | }) | 1089 | TypeCtor::Adt(AdtDef::Struct(s)) => s.field(self.db, name).map(|field| { |
1090 | } | 1090 | self.write_field_resolution(tgt_expr, field); |
1091 | _ => None, | 1091 | field.ty(self.db).subst(&a_ty.parameters) |
1092 | }, | 1092 | }), |
1093 | _ => None, | 1093 | _ => None, |
1094 | }) | 1094 | }, |
1095 | .unwrap_or(Ty::Unknown); | 1095 | _ => None, |
1096 | }) | ||
1097 | .unwrap_or(Ty::Unknown); | ||
1096 | self.insert_type_vars(ty) | 1098 | self.insert_type_vars(ty) |
1097 | } | 1099 | } |
1098 | Expr::Try { expr } => { | 1100 | Expr::Try { expr } => { |
@@ -1124,10 +1126,12 @@ impl<'a, D: HirDatabase> InferenceContext<'a, D> { | |||
1124 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); | 1126 | let inner_ty = self.infer_expr(*expr, &Expectation::none()); |
1125 | match op { | 1127 | match op { |
1126 | UnaryOp::Deref => { | 1128 | UnaryOp::Deref => { |
1127 | if let Some(derefed_ty) = inner_ty.builtin_deref() { | 1129 | let canonicalized = self.canonicalizer().canonicalize_ty(inner_ty); |
1128 | derefed_ty | 1130 | if let Some(derefed_ty) = |
1131 | autoderef::deref(self.db, &self.resolver, &canonicalized.value) | ||
1132 | { | ||
1133 | canonicalized.decanonicalize_ty(derefed_ty.value) | ||
1129 | } else { | 1134 | } else { |
1130 | // FIXME Deref::deref | ||
1131 | Ty::Unknown | 1135 | Ty::Unknown |
1132 | } | 1136 | } |
1133 | } | 1137 | } |
diff --git a/crates/ra_hir/src/ty/lower.rs b/crates/ra_hir/src/ty/lower.rs index 26c213a41..300616a53 100644 --- a/crates/ra_hir/src/ty/lower.rs +++ b/crates/ra_hir/src/ty/lower.rs | |||
@@ -460,7 +460,7 @@ fn type_for_type_alias(db: &impl HirDatabase, t: TypeAlias) -> Ty { | |||
460 | let resolver = t.resolver(db); | 460 | let resolver = t.resolver(db); |
461 | let type_ref = t.type_ref(db); | 461 | let type_ref = t.type_ref(db); |
462 | let substs = Substs::identity(&generics); | 462 | let substs = Substs::identity(&generics); |
463 | let inner = Ty::from_hir(db, &resolver, &type_ref); | 463 | let inner = Ty::from_hir(db, &resolver, &type_ref.unwrap_or(TypeRef::Error)); |
464 | inner.subst(&substs) | 464 | inner.subst(&substs) |
465 | } | 465 | } |
466 | 466 | ||
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 646e58aa9..ad26d591c 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -16,7 +16,7 @@ use crate::{ | |||
16 | generics::HasGenericParams, | 16 | generics::HasGenericParams, |
17 | ty::primitive::{UncertainIntTy, UncertainFloatTy} | 17 | ty::primitive::{UncertainIntTy, UncertainFloatTy} |
18 | }; | 18 | }; |
19 | use super::{TraitRef, Canonical}; | 19 | use super::{TraitRef, Canonical, autoderef}; |
20 | 20 | ||
21 | /// This is used as a key for indexing impls. | 21 | /// This is used as a key for indexing impls. |
22 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 22 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
@@ -162,8 +162,7 @@ pub(crate) fn iterate_method_candidates<T>( | |||
162 | // rustc does an autoderef and then autoref again). | 162 | // rustc does an autoderef and then autoref again). |
163 | 163 | ||
164 | let krate = resolver.krate()?; | 164 | let krate = resolver.krate()?; |
165 | for derefed_ty in ty.value.clone().autoderef(db) { | 165 | for derefed_ty in autoderef::autoderef(db, resolver, ty.clone()) { |
166 | let derefed_ty = Canonical { value: derefed_ty, num_vars: ty.num_vars }; | ||
167 | if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback) | 166 | if let Some(result) = iterate_inherent_methods(&derefed_ty, db, name, krate, &mut callback) |
168 | { | 167 | { |
169 | return Some(result); | 168 | return Some(result); |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 54b2a8c16..0fe7805e2 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -2737,6 +2737,90 @@ fn main() { | |||
2737 | assert_eq!(t, "Foo"); | 2737 | assert_eq!(t, "Foo"); |
2738 | } | 2738 | } |
2739 | 2739 | ||
2740 | #[test] | ||
2741 | fn deref_trait() { | ||
2742 | let t = type_at( | ||
2743 | r#" | ||
2744 | //- /main.rs | ||
2745 | #[lang = "deref"] | ||
2746 | trait Deref { | ||
2747 | type Target; | ||
2748 | fn deref(&self) -> &Self::Target; | ||
2749 | } | ||
2750 | |||
2751 | struct Arc<T>; | ||
2752 | impl<T> Deref for Arc<T> { | ||
2753 | type Target = T; | ||
2754 | } | ||
2755 | |||
2756 | struct S; | ||
2757 | impl S { | ||
2758 | fn foo(&self) -> u128 {} | ||
2759 | } | ||
2760 | |||
2761 | fn test(s: Arc<S>) { | ||
2762 | (*s, s.foo())<|> | ||
2763 | } | ||
2764 | "#, | ||
2765 | ); | ||
2766 | assert_eq!(t, "(S, u128)"); | ||
2767 | } | ||
2768 | |||
2769 | #[test] | ||
2770 | fn deref_trait_with_inference_var() { | ||
2771 | let t = type_at( | ||
2772 | r#" | ||
2773 | //- /main.rs | ||
2774 | #[lang = "deref"] | ||
2775 | trait Deref { | ||
2776 | type Target; | ||
2777 | fn deref(&self) -> &Self::Target; | ||
2778 | } | ||
2779 | |||
2780 | struct Arc<T>; | ||
2781 | fn new_arc<T>() -> Arc<T> {} | ||
2782 | impl<T> Deref for Arc<T> { | ||
2783 | type Target = T; | ||
2784 | } | ||
2785 | |||
2786 | struct S; | ||
2787 | fn foo(a: Arc<S>) {} | ||
2788 | |||
2789 | fn test() { | ||
2790 | let a = new_arc(); | ||
2791 | let b = (*a)<|>; | ||
2792 | foo(a); | ||
2793 | } | ||
2794 | "#, | ||
2795 | ); | ||
2796 | assert_eq!(t, "S"); | ||
2797 | } | ||
2798 | |||
2799 | #[test] | ||
2800 | fn deref_trait_infinite_recursion() { | ||
2801 | let t = type_at( | ||
2802 | r#" | ||
2803 | //- /main.rs | ||
2804 | #[lang = "deref"] | ||
2805 | trait Deref { | ||
2806 | type Target; | ||
2807 | fn deref(&self) -> &Self::Target; | ||
2808 | } | ||
2809 | |||
2810 | struct S; | ||
2811 | |||
2812 | impl Deref for S { | ||
2813 | type Target = S; | ||
2814 | } | ||
2815 | |||
2816 | fn test(s: S) { | ||
2817 | s.foo()<|>; | ||
2818 | } | ||
2819 | "#, | ||
2820 | ); | ||
2821 | assert_eq!(t, "{unknown}"); | ||
2822 | } | ||
2823 | |||
2740 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { | 2824 | fn type_at_pos(db: &MockDatabase, pos: FilePosition) -> String { |
2741 | let file = db.parse(pos.file_id).ok().unwrap(); | 2825 | let file = db.parse(pos.file_id).ok().unwrap(); |
2742 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); | 2826 | let expr = algo::find_node_at_offset::<ast::Expr>(file.syntax(), pos.offset).unwrap(); |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index fda7f9c04..9a6349d4b 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -8,7 +8,7 @@ use chalk_ir::cast::Cast; | |||
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
9 | 9 | ||
10 | use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; | 10 | use crate::{Crate, Trait, db::HirDatabase, ImplBlock}; |
11 | use super::{TraitRef, Ty, Canonical}; | 11 | use super::{TraitRef, Ty, Canonical, ProjectionTy}; |
12 | 12 | ||
13 | use self::chalk::{ToChalk, from_chalk}; | 13 | use self::chalk::{ToChalk, from_chalk}; |
14 | 14 | ||
@@ -75,6 +75,13 @@ pub enum Obligation { | |||
75 | /// Prove that a certain type implements a trait (the type is the `Self` type | 75 | /// Prove that a certain type implements a trait (the type is the `Self` type |
76 | /// parameter to the `TraitRef`). | 76 | /// parameter to the `TraitRef`). |
77 | Trait(TraitRef), | 77 | Trait(TraitRef), |
78 | // Projection(ProjectionPredicate), | ||
79 | } | ||
80 | |||
81 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
82 | pub struct ProjectionPredicate { | ||
83 | pub projection_ty: ProjectionTy, | ||
84 | pub ty: Ty, | ||
78 | } | 85 | } |
79 | 86 | ||
80 | /// Check using Chalk whether trait is implemented for given parameters including `Self` type. | 87 | /// Check using Chalk whether trait is implemented for given parameters including `Self` type. |
@@ -98,6 +105,30 @@ pub(crate) fn implements_query( | |||
98 | solution.map(|solution| solution_from_chalk(db, solution)) | 105 | solution.map(|solution| solution_from_chalk(db, solution)) |
99 | } | 106 | } |
100 | 107 | ||
108 | pub(crate) fn normalize_query( | ||
109 | db: &impl HirDatabase, | ||
110 | krate: Crate, | ||
111 | projection: Canonical<ProjectionPredicate>, | ||
112 | ) -> Option<Solution> { | ||
113 | let goal: chalk_ir::Goal = chalk_ir::Normalize { | ||
114 | projection: projection.value.projection_ty.to_chalk(db), | ||
115 | ty: projection.value.ty.to_chalk(db), | ||
116 | } | ||
117 | .cast(); | ||
118 | debug!("goal: {:?}", goal); | ||
119 | // FIXME unify with `implements` | ||
120 | let env = chalk_ir::Environment::new(); | ||
121 | let in_env = chalk_ir::InEnvironment::new(&env, goal); | ||
122 | let parameter = chalk_ir::ParameterKind::Ty(chalk_ir::UniverseIndex::ROOT); | ||
123 | let canonical = | ||
124 | chalk_ir::Canonical { value: in_env, binders: vec![parameter; projection.num_vars] }; | ||
125 | // We currently don't deal with universes (I think / hope they're not yet | ||
126 | // relevant for our use cases?) | ||
127 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; | ||
128 | let solution = solve(db, krate, &u_canonical); | ||
129 | solution.map(|solution| solution_from_chalk(db, solution)) | ||
130 | } | ||
131 | |||
101 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { | 132 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { |
102 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { | 133 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution>| { |
103 | let value = subst | 134 | let value = subst |
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 1e4806db0..5105588ee 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -3,7 +3,7 @@ use std::sync::Arc; | |||
3 | 3 | ||
4 | use log::debug; | 4 | use log::debug; |
5 | 5 | ||
6 | use chalk_ir::{TypeId, ImplId, TypeKindId, ProjectionTy, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; | 6 | use chalk_ir::{TypeId, ImplId, TypeKindId, Parameter, Identifier, cast::Cast, PlaceholderIndex, UniverseIndex, TypeName}; |
7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; | 7 | use chalk_rust_ir::{AssociatedTyDatum, TraitDatum, StructDatum, ImplDatum}; |
8 | 8 | ||
9 | use test_utils::tested_by; | 9 | use test_utils::tested_by; |
@@ -12,9 +12,9 @@ use ra_db::salsa::{InternId, InternKey}; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | Trait, HasGenericParams, ImplBlock, | 13 | Trait, HasGenericParams, ImplBlock, |
14 | db::HirDatabase, | 14 | db::HirDatabase, |
15 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef}, | 15 | ty::{TraitRef, Ty, ApplicationTy, TypeCtor, Substs, GenericPredicate, CallableDef, ProjectionTy}, |
16 | ty::display::HirDisplay, | 16 | ty::display::HirDisplay, |
17 | generics::GenericDef, | 17 | generics::GenericDef, TypeAlias, ImplItem, |
18 | }; | 18 | }; |
19 | use super::ChalkContext; | 19 | use super::ChalkContext; |
20 | 20 | ||
@@ -156,6 +156,18 @@ impl ToChalk for ImplBlock { | |||
156 | } | 156 | } |
157 | } | 157 | } |
158 | 158 | ||
159 | impl ToChalk for TypeAlias { | ||
160 | type Chalk = chalk_ir::TypeId; | ||
161 | |||
162 | fn to_chalk(self, _db: &impl HirDatabase) -> chalk_ir::TypeId { | ||
163 | self.id.into() | ||
164 | } | ||
165 | |||
166 | fn from_chalk(_db: &impl HirDatabase, impl_id: chalk_ir::TypeId) -> TypeAlias { | ||
167 | TypeAlias { id: impl_id.into() } | ||
168 | } | ||
169 | } | ||
170 | |||
159 | impl ToChalk for GenericPredicate { | 171 | impl ToChalk for GenericPredicate { |
160 | type Chalk = chalk_ir::QuantifiedWhereClause; | 172 | type Chalk = chalk_ir::QuantifiedWhereClause; |
161 | 173 | ||
@@ -183,6 +195,24 @@ impl ToChalk for GenericPredicate { | |||
183 | } | 195 | } |
184 | } | 196 | } |
185 | 197 | ||
198 | impl ToChalk for ProjectionTy { | ||
199 | type Chalk = chalk_ir::ProjectionTy; | ||
200 | |||
201 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_ir::ProjectionTy { | ||
202 | chalk_ir::ProjectionTy { | ||
203 | associated_ty_id: self.associated_ty.to_chalk(db), | ||
204 | parameters: self.parameters.to_chalk(db), | ||
205 | } | ||
206 | } | ||
207 | |||
208 | fn from_chalk(db: &impl HirDatabase, projection_ty: chalk_ir::ProjectionTy) -> ProjectionTy { | ||
209 | ProjectionTy { | ||
210 | associated_ty: from_chalk(db, projection_ty.associated_ty_id), | ||
211 | parameters: from_chalk(db, projection_ty.parameters), | ||
212 | } | ||
213 | } | ||
214 | } | ||
215 | |||
186 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { | 216 | fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> { |
187 | chalk_ir::Binders { | 217 | chalk_ir::Binders { |
188 | value, | 218 | value, |
@@ -225,8 +255,29 @@ impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | |||
225 | where | 255 | where |
226 | DB: HirDatabase, | 256 | DB: HirDatabase, |
227 | { | 257 | { |
228 | fn associated_ty_data(&self, _ty: TypeId) -> Arc<AssociatedTyDatum> { | 258 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> { |
229 | unimplemented!() | 259 | debug!("associated_ty_data {:?}", id); |
260 | let type_alias: TypeAlias = from_chalk(self.db, id); | ||
261 | let trait_ = match type_alias.container(self.db) { | ||
262 | Some(crate::Container::Trait(t)) => t, | ||
263 | _ => panic!("associated type not in trait"), | ||
264 | }; | ||
265 | let generic_params = type_alias.generic_params(self.db); | ||
266 | let parameter_kinds = generic_params | ||
267 | .params_including_parent() | ||
268 | .into_iter() | ||
269 | .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string()))) | ||
270 | .collect(); | ||
271 | let datum = AssociatedTyDatum { | ||
272 | trait_id: trait_.to_chalk(self.db), | ||
273 | id, | ||
274 | name: lalrpop_intern::intern(&type_alias.name(self.db).to_string()), | ||
275 | parameter_kinds, | ||
276 | // FIXME add bounds and where clauses | ||
277 | bounds: vec![], | ||
278 | where_clauses: vec![], | ||
279 | }; | ||
280 | Arc::new(datum) | ||
230 | } | 281 | } |
231 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 282 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { |
232 | debug!("trait_datum {:?}", trait_id); | 283 | debug!("trait_datum {:?}", trait_id); |
@@ -260,7 +311,15 @@ where | |||
260 | fundamental: false, | 311 | fundamental: false, |
261 | }; | 312 | }; |
262 | let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); | 313 | let where_clauses = convert_where_clauses(self.db, trait_.into(), &bound_vars); |
263 | let associated_ty_ids = Vec::new(); // FIXME add associated tys | 314 | let associated_ty_ids = trait_ |
315 | .items(self.db) | ||
316 | .into_iter() | ||
317 | .filter_map(|trait_item| match trait_item { | ||
318 | crate::traits::TraitItem::TypeAlias(type_alias) => Some(type_alias), | ||
319 | _ => None, | ||
320 | }) | ||
321 | .map(|type_alias| type_alias.to_chalk(self.db)) | ||
322 | .collect(); | ||
264 | let trait_datum_bound = | 323 | let trait_datum_bound = |
265 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; | 324 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, flags, associated_ty_ids }; |
266 | let trait_datum = TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()) }; | 325 | let trait_datum = TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()) }; |
@@ -359,7 +418,29 @@ where | |||
359 | trait_ref.display(self.db), | 418 | trait_ref.display(self.db), |
360 | where_clauses | 419 | where_clauses |
361 | ); | 420 | ); |
421 | let trait_ = trait_ref.trait_; | ||
362 | let trait_ref = trait_ref.to_chalk(self.db); | 422 | let trait_ref = trait_ref.to_chalk(self.db); |
423 | let associated_ty_values = impl_block | ||
424 | .items(self.db) | ||
425 | .into_iter() | ||
426 | .filter_map(|item| match item { | ||
427 | ImplItem::TypeAlias(t) => Some(t), | ||
428 | _ => None, | ||
429 | }) | ||
430 | .filter_map(|t| { | ||
431 | let assoc_ty = trait_.associated_type_by_name(self.db, t.name(self.db))?; | ||
432 | let ty = self.db.type_for_def(t.into(), crate::Namespace::Types).subst(&bound_vars); | ||
433 | Some(chalk_rust_ir::AssociatedTyValue { | ||
434 | impl_id, | ||
435 | associated_ty_id: assoc_ty.to_chalk(self.db), | ||
436 | value: chalk_ir::Binders { | ||
437 | value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(self.db) }, | ||
438 | binders: vec![], // we don't support GATs yet | ||
439 | }, | ||
440 | }) | ||
441 | }) | ||
442 | .collect(); | ||
443 | |||
363 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 444 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
364 | trait_ref: if negative { | 445 | trait_ref: if negative { |
365 | chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref) | 446 | chalk_rust_ir::PolarizedTraitRef::Negative(trait_ref) |
@@ -367,9 +448,10 @@ where | |||
367 | chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref) | 448 | chalk_rust_ir::PolarizedTraitRef::Positive(trait_ref) |
368 | }, | 449 | }, |
369 | where_clauses, | 450 | where_clauses, |
370 | associated_ty_values: Vec::new(), // FIXME add associated type values | 451 | associated_ty_values, |
371 | impl_type, | 452 | impl_type, |
372 | }; | 453 | }; |
454 | debug!("impl_datum: {:?}", impl_datum_bound); | ||
373 | let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, bound_vars.len()) }; | 455 | let impl_datum = ImplDatum { binders: make_binders(impl_datum_bound, bound_vars.len()) }; |
374 | Arc::new(impl_datum) | 456 | Arc::new(impl_datum) |
375 | } | 457 | } |
@@ -405,7 +487,7 @@ where | |||
405 | } | 487 | } |
406 | fn split_projection<'p>( | 488 | fn split_projection<'p>( |
407 | &self, | 489 | &self, |
408 | projection: &'p ProjectionTy, | 490 | projection: &'p chalk_ir::ProjectionTy, |
409 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { | 491 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter], &'p [Parameter]) { |
410 | debug!("split_projection {:?}", projection); | 492 | debug!("split_projection {:?}", projection); |
411 | unimplemented!() | 493 | unimplemented!() |
@@ -440,6 +522,18 @@ impl From<crate::ids::TraitId> for chalk_ir::TraitId { | |||
440 | } | 522 | } |
441 | } | 523 | } |
442 | 524 | ||
525 | impl From<chalk_ir::TypeId> for crate::ids::TypeAliasId { | ||
526 | fn from(type_id: chalk_ir::TypeId) -> Self { | ||
527 | id_from_chalk(type_id.0) | ||
528 | } | ||
529 | } | ||
530 | |||
531 | impl From<crate::ids::TypeAliasId> for chalk_ir::TypeId { | ||
532 | fn from(type_id: crate::ids::TypeAliasId) -> Self { | ||
533 | chalk_ir::TypeId(id_to_chalk(type_id)) | ||
534 | } | ||
535 | } | ||
536 | |||
443 | impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { | 537 | impl From<chalk_ir::StructId> for crate::ids::TypeCtorId { |
444 | fn from(struct_id: chalk_ir::StructId) -> Self { | 538 | fn from(struct_id: chalk_ir::StructId) -> Self { |
445 | id_from_chalk(struct_id.0) | 539 | id_from_chalk(struct_id.0) |