diff options
Diffstat (limited to 'crates/ra_hir/src')
-rw-r--r-- | crates/ra_hir/src/db.rs | 30 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty.rs | 89 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/infer/unify.rs | 22 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/method_resolution.rs | 6 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/tests.rs | 55 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits.rs | 29 | ||||
-rw-r--r-- | crates/ra_hir/src/ty/traits/chalk.rs | 319 |
8 files changed, 370 insertions, 186 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 276b0774f..d75d71d66 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -13,8 +13,10 @@ use crate::{ | |||
13 | lang_item::{LangItemTarget, LangItems}, | 13 | lang_item::{LangItemTarget, LangItems}, |
14 | traits::TraitData, | 14 | traits::TraitData, |
15 | ty::{ | 15 | ty::{ |
16 | method_resolution::CrateImplBlocks, traits::Impl, CallableDef, FnSig, GenericPredicate, | 16 | method_resolution::CrateImplBlocks, |
17 | InferenceResult, Namespace, Substs, Ty, TypableDef, TypeCtor, | 17 | traits::{AssocTyValue, Impl}, |
18 | CallableDef, FnSig, GenericPredicate, InferenceResult, Namespace, Substs, Ty, TypableDef, | ||
19 | TypeCtor, | ||
18 | }, | 20 | }, |
19 | type_alias::TypeAliasData, | 21 | type_alias::TypeAliasData, |
20 | Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField, | 22 | Const, ConstData, Crate, DefWithBody, FnData, Function, ImplBlock, Module, Static, StructField, |
@@ -119,26 +121,42 @@ pub trait HirDatabase: DefDatabase + AstDatabase { | |||
119 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; | 121 | fn intern_type_ctor(&self, type_ctor: TypeCtor) -> ids::TypeCtorId; |
120 | #[salsa::interned] | 122 | #[salsa::interned] |
121 | fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId; | 123 | fn intern_chalk_impl(&self, impl_: Impl) -> ids::GlobalImplId; |
124 | #[salsa::interned] | ||
125 | fn intern_assoc_ty_value(&self, assoc_ty_value: AssocTyValue) -> ids::AssocTyValueId; | ||
122 | 126 | ||
123 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] | 127 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_data_query)] |
124 | fn associated_ty_data(&self, id: chalk_ir::TypeId) -> Arc<chalk_rust_ir::AssociatedTyDatum>; | 128 | fn associated_ty_data( |
129 | &self, | ||
130 | id: chalk_ir::TypeId, | ||
131 | ) -> Arc<chalk_rust_ir::AssociatedTyDatum<chalk_ir::family::ChalkIr>>; | ||
125 | 132 | ||
126 | #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)] | 133 | #[salsa::invoke(crate::ty::traits::chalk::trait_datum_query)] |
127 | fn trait_datum( | 134 | fn trait_datum( |
128 | &self, | 135 | &self, |
129 | krate: Crate, | 136 | krate: Crate, |
130 | trait_id: chalk_ir::TraitId, | 137 | trait_id: chalk_ir::TraitId, |
131 | ) -> Arc<chalk_rust_ir::TraitDatum>; | 138 | ) -> Arc<chalk_rust_ir::TraitDatum<chalk_ir::family::ChalkIr>>; |
132 | 139 | ||
133 | #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)] | 140 | #[salsa::invoke(crate::ty::traits::chalk::struct_datum_query)] |
134 | fn struct_datum( | 141 | fn struct_datum( |
135 | &self, | 142 | &self, |
136 | krate: Crate, | 143 | krate: Crate, |
137 | struct_id: chalk_ir::StructId, | 144 | struct_id: chalk_ir::StructId, |
138 | ) -> Arc<chalk_rust_ir::StructDatum>; | 145 | ) -> Arc<chalk_rust_ir::StructDatum<chalk_ir::family::ChalkIr>>; |
139 | 146 | ||
140 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] | 147 | #[salsa::invoke(crate::ty::traits::chalk::impl_datum_query)] |
141 | fn impl_datum(&self, krate: Crate, impl_id: chalk_ir::ImplId) -> Arc<chalk_rust_ir::ImplDatum>; | 148 | fn impl_datum( |
149 | &self, | ||
150 | krate: Crate, | ||
151 | impl_id: chalk_ir::ImplId, | ||
152 | ) -> Arc<chalk_rust_ir::ImplDatum<chalk_ir::family::ChalkIr>>; | ||
153 | |||
154 | #[salsa::invoke(crate::ty::traits::chalk::associated_ty_value_query)] | ||
155 | fn associated_ty_value( | ||
156 | &self, | ||
157 | krate: Crate, | ||
158 | id: chalk_rust_ir::AssociatedTyValueId, | ||
159 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<chalk_ir::family::ChalkIr>>; | ||
142 | 160 | ||
143 | #[salsa::invoke(crate::ty::traits::trait_solve_query)] | 161 | #[salsa::invoke(crate::ty::traits::trait_solve_query)] |
144 | fn trait_solve( | 162 | fn trait_solve( |
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index fe083c0c6..2b59365fb 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -37,3 +37,9 @@ impl_intern_key!(TypeCtorId); | |||
37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 37 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
38 | pub struct GlobalImplId(salsa::InternId); | 38 | pub struct GlobalImplId(salsa::InternId); |
39 | impl_intern_key!(GlobalImplId); | 39 | impl_intern_key!(GlobalImplId); |
40 | |||
41 | /// This exists just for Chalk, because it needs a unique ID for each associated | ||
42 | /// type value in an impl (even synthetic ones). | ||
43 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
44 | pub struct AssocTyValueId(salsa::InternId); | ||
45 | impl_intern_key!(AssocTyValueId); | ||
diff --git a/crates/ra_hir/src/ty.rs b/crates/ra_hir/src/ty.rs index ff6030ac4..a54135188 100644 --- a/crates/ra_hir/src/ty.rs +++ b/crates/ra_hir/src/ty.rs | |||
@@ -224,8 +224,8 @@ impl TypeWalk for ProjectionTy { | |||
224 | self.parameters.walk(f); | 224 | self.parameters.walk(f); |
225 | } | 225 | } |
226 | 226 | ||
227 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 227 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
228 | self.parameters.walk_mut(f); | 228 | self.parameters.walk_mut_binders(f, binders); |
229 | } | 229 | } |
230 | } | 230 | } |
231 | 231 | ||
@@ -291,6 +291,20 @@ pub enum Ty { | |||
291 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 291 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
292 | pub struct Substs(Arc<[Ty]>); | 292 | pub struct Substs(Arc<[Ty]>); |
293 | 293 | ||
294 | impl TypeWalk for Substs { | ||
295 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
296 | for t in self.0.iter() { | ||
297 | t.walk(f); | ||
298 | } | ||
299 | } | ||
300 | |||
301 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { | ||
302 | for t in make_mut_slice(&mut self.0) { | ||
303 | t.walk_mut_binders(f, binders); | ||
304 | } | ||
305 | } | ||
306 | } | ||
307 | |||
294 | impl Substs { | 308 | impl Substs { |
295 | pub fn empty() -> Substs { | 309 | pub fn empty() -> Substs { |
296 | Substs(Arc::new([])) | 310 | Substs(Arc::new([])) |
@@ -304,18 +318,6 @@ impl Substs { | |||
304 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) | 318 | Substs(self.0[..std::cmp::min(self.0.len(), n)].into()) |
305 | } | 319 | } |
306 | 320 | ||
307 | pub fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
308 | for t in self.0.iter() { | ||
309 | t.walk(f); | ||
310 | } | ||
311 | } | ||
312 | |||
313 | pub fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
314 | for t in make_mut_slice(&mut self.0) { | ||
315 | t.walk_mut(f); | ||
316 | } | ||
317 | } | ||
318 | |||
319 | pub fn as_single(&self) -> &Ty { | 321 | pub fn as_single(&self) -> &Ty { |
320 | if self.0.len() != 1 { | 322 | if self.0.len() != 1 { |
321 | panic!("expected substs of len 1, got {:?}", self); | 323 | panic!("expected substs of len 1, got {:?}", self); |
@@ -440,8 +442,8 @@ impl TypeWalk for TraitRef { | |||
440 | self.substs.walk(f); | 442 | self.substs.walk(f); |
441 | } | 443 | } |
442 | 444 | ||
443 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 445 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
444 | self.substs.walk_mut(f); | 446 | self.substs.walk_mut_binders(f, binders); |
445 | } | 447 | } |
446 | } | 448 | } |
447 | 449 | ||
@@ -491,10 +493,12 @@ impl TypeWalk for GenericPredicate { | |||
491 | } | 493 | } |
492 | } | 494 | } |
493 | 495 | ||
494 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 496 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
495 | match self { | 497 | match self { |
496 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut(f), | 498 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), |
497 | GenericPredicate::Projection(projection_pred) => projection_pred.walk_mut(f), | 499 | GenericPredicate::Projection(projection_pred) => { |
500 | projection_pred.walk_mut_binders(f, binders) | ||
501 | } | ||
498 | GenericPredicate::Error => {} | 502 | GenericPredicate::Error => {} |
499 | } | 503 | } |
500 | } | 504 | } |
@@ -544,9 +548,9 @@ impl TypeWalk for FnSig { | |||
544 | } | 548 | } |
545 | } | 549 | } |
546 | 550 | ||
547 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 551 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
548 | for t in make_mut_slice(&mut self.params_and_return) { | 552 | for t in make_mut_slice(&mut self.params_and_return) { |
549 | t.walk_mut(f); | 553 | t.walk_mut_binders(f, binders); |
550 | } | 554 | } |
551 | } | 555 | } |
552 | } | 556 | } |
@@ -671,7 +675,20 @@ impl Ty { | |||
671 | /// types, similar to Chalk's `Fold` trait. | 675 | /// types, similar to Chalk's `Fold` trait. |
672 | pub trait TypeWalk { | 676 | pub trait TypeWalk { |
673 | fn walk(&self, f: &mut impl FnMut(&Ty)); | 677 | fn walk(&self, f: &mut impl FnMut(&Ty)); |
674 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)); | 678 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { |
679 | self.walk_mut_binders(&mut |ty, _binders| f(ty), 0); | ||
680 | } | ||
681 | /// Walk the type, counting entered binders. | ||
682 | /// | ||
683 | /// `Ty::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
684 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
685 | /// substitute a certain bound variable, we can't just walk the whole type | ||
686 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
687 | /// things that introduce new bound variables, we have to keep track of | ||
688 | /// that. Currently, the only thing that introduces bound variables on our | ||
689 | /// side are `Ty::Dyn` and `Ty::Opaque`, which each introduce a bound | ||
690 | /// variable for the self type. | ||
691 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize); | ||
675 | 692 | ||
676 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | 693 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self |
677 | where | 694 | where |
@@ -700,14 +717,22 @@ pub trait TypeWalk { | |||
700 | } | 717 | } |
701 | 718 | ||
702 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). | 719 | /// Substitutes `Ty::Bound` vars (as opposed to type parameters). |
703 | fn subst_bound_vars(self, substs: &Substs) -> Self | 720 | fn subst_bound_vars(mut self, substs: &Substs) -> Self |
704 | where | 721 | where |
705 | Self: Sized, | 722 | Self: Sized, |
706 | { | 723 | { |
707 | self.fold(&mut |ty| match ty { | 724 | self.walk_mut_binders( |
708 | Ty::Bound(idx) => substs.get(idx as usize).cloned().unwrap_or_else(|| Ty::Bound(idx)), | 725 | &mut |ty, binders| match ty { |
709 | ty => ty, | 726 | &mut Ty::Bound(idx) => { |
710 | }) | 727 | if idx as usize >= binders && (idx as usize - binders) < substs.len() { |
728 | *ty = substs.0[idx as usize - binders].clone(); | ||
729 | } | ||
730 | } | ||
731 | _ => {} | ||
732 | }, | ||
733 | 0, | ||
734 | ); | ||
735 | self | ||
711 | } | 736 | } |
712 | 737 | ||
713 | /// Shifts up `Ty::Bound` vars by `n`. | 738 | /// Shifts up `Ty::Bound` vars by `n`. |
@@ -748,22 +773,22 @@ impl TypeWalk for Ty { | |||
748 | f(self); | 773 | f(self); |
749 | } | 774 | } |
750 | 775 | ||
751 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 776 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
752 | match self { | 777 | match self { |
753 | Ty::Apply(a_ty) => { | 778 | Ty::Apply(a_ty) => { |
754 | a_ty.parameters.walk_mut(f); | 779 | a_ty.parameters.walk_mut_binders(f, binders); |
755 | } | 780 | } |
756 | Ty::Projection(p_ty) => { | 781 | Ty::Projection(p_ty) => { |
757 | p_ty.parameters.walk_mut(f); | 782 | p_ty.parameters.walk_mut_binders(f, binders); |
758 | } | 783 | } |
759 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { | 784 | Ty::Dyn(predicates) | Ty::Opaque(predicates) => { |
760 | for p in make_mut_slice(predicates) { | 785 | for p in make_mut_slice(predicates) { |
761 | p.walk_mut(f); | 786 | p.walk_mut_binders(f, binders + 1); |
762 | } | 787 | } |
763 | } | 788 | } |
764 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} | 789 | Ty::Param { .. } | Ty::Bound(_) | Ty::Infer(_) | Ty::Unknown => {} |
765 | } | 790 | } |
766 | f(self); | 791 | f(self, binders); |
767 | } | 792 | } |
768 | } | 793 | } |
769 | 794 | ||
diff --git a/crates/ra_hir/src/ty/infer/unify.rs b/crates/ra_hir/src/ty/infer/unify.rs index ca33cc7f8..64d9394cf 100644 --- a/crates/ra_hir/src/ty/infer/unify.rs +++ b/crates/ra_hir/src/ty/infer/unify.rs | |||
@@ -134,17 +134,19 @@ where | |||
134 | } | 134 | } |
135 | 135 | ||
136 | impl<T> Canonicalized<T> { | 136 | impl<T> Canonicalized<T> { |
137 | pub fn decanonicalize_ty(&self, ty: Ty) -> Ty { | 137 | pub fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { |
138 | ty.fold(&mut |ty| match ty { | 138 | ty.walk_mut_binders( |
139 | Ty::Bound(idx) => { | 139 | &mut |ty, binders| match ty { |
140 | if (idx as usize) < self.free_vars.len() { | 140 | &mut Ty::Bound(idx) => { |
141 | Ty::Infer(self.free_vars[idx as usize]) | 141 | if idx as usize >= binders && (idx as usize - binders) < self.free_vars.len() { |
142 | } else { | 142 | *ty = Ty::Infer(self.free_vars[idx as usize - binders]); |
143 | Ty::Bound(idx) | 143 | } |
144 | } | 144 | } |
145 | } | 145 | _ => {} |
146 | ty => ty, | 146 | }, |
147 | }) | 147 | 0, |
148 | ); | ||
149 | ty | ||
148 | } | 150 | } |
149 | 151 | ||
150 | pub fn apply_solution( | 152 | pub fn apply_solution( |
diff --git a/crates/ra_hir/src/ty/method_resolution.rs b/crates/ra_hir/src/ty/method_resolution.rs index 9aad2d3fe..d20aeaacf 100644 --- a/crates/ra_hir/src/ty/method_resolution.rs +++ b/crates/ra_hir/src/ty/method_resolution.rs | |||
@@ -228,14 +228,10 @@ fn iterate_trait_method_candidates<T>( | |||
228 | 'traits: for t in traits { | 228 | 'traits: for t in traits { |
229 | let data = t.trait_data(db); | 229 | let data = t.trait_data(db); |
230 | 230 | ||
231 | // FIXME this is a bit of a hack, since Chalk should say the same thing | ||
232 | // anyway, but currently Chalk doesn't implement `dyn/impl Trait` yet | ||
233 | let inherently_implemented = ty.value.inherent_trait() == Some(t); | ||
234 | |||
235 | // we'll be lazy about checking whether the type implements the | 231 | // we'll be lazy about checking whether the type implements the |
236 | // trait, but if we find out it doesn't, we'll skip the rest of the | 232 | // trait, but if we find out it doesn't, we'll skip the rest of the |
237 | // iteration | 233 | // iteration |
238 | let mut known_implemented = inherently_implemented; | 234 | let mut known_implemented = false; |
239 | for &item in data.items() { | 235 | for &item in data.items() { |
240 | if !is_valid_candidate(db, name, mode, item) { | 236 | if !is_valid_candidate(db, name, mode, item) { |
241 | continue; | 237 | continue; |
diff --git a/crates/ra_hir/src/ty/tests.rs b/crates/ra_hir/src/ty/tests.rs index 9a26e02fa..ca1693679 100644 --- a/crates/ra_hir/src/ty/tests.rs +++ b/crates/ra_hir/src/ty/tests.rs | |||
@@ -3983,11 +3983,11 @@ fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { | |||
3983 | [180; 183) 'bar': fn bar() -> impl Trait<u64> | 3983 | [180; 183) 'bar': fn bar() -> impl Trait<u64> |
3984 | [180; 185) 'bar()': impl Trait<u64> | 3984 | [180; 185) 'bar()': impl Trait<u64> |
3985 | [191; 192) 'x': impl Trait<u64> | 3985 | [191; 192) 'x': impl Trait<u64> |
3986 | [191; 198) 'x.foo()': {unknown} | 3986 | [191; 198) 'x.foo()': u64 |
3987 | [204; 205) 'y': &impl Trait<u64> | 3987 | [204; 205) 'y': &impl Trait<u64> |
3988 | [204; 211) 'y.foo()': {unknown} | 3988 | [204; 211) 'y.foo()': u64 |
3989 | [217; 218) 'z': impl Trait<u64> | 3989 | [217; 218) 'z': impl Trait<u64> |
3990 | [217; 224) 'z.foo()': {unknown} | 3990 | [217; 224) 'z.foo()': u64 |
3991 | [230; 231) 'x': impl Trait<u64> | 3991 | [230; 231) 'x': impl Trait<u64> |
3992 | [230; 238) 'x.foo2()': i64 | 3992 | [230; 238) 'x.foo2()': i64 |
3993 | [244; 245) 'y': &impl Trait<u64> | 3993 | [244; 245) 'y': &impl Trait<u64> |
@@ -4033,11 +4033,11 @@ fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { | |||
4033 | [177; 180) 'bar': fn bar() -> dyn Trait<u64> | 4033 | [177; 180) 'bar': fn bar() -> dyn Trait<u64> |
4034 | [177; 182) 'bar()': dyn Trait<u64> | 4034 | [177; 182) 'bar()': dyn Trait<u64> |
4035 | [188; 189) 'x': dyn Trait<u64> | 4035 | [188; 189) 'x': dyn Trait<u64> |
4036 | [188; 195) 'x.foo()': {unknown} | 4036 | [188; 195) 'x.foo()': u64 |
4037 | [201; 202) 'y': &dyn Trait<u64> | 4037 | [201; 202) 'y': &dyn Trait<u64> |
4038 | [201; 208) 'y.foo()': {unknown} | 4038 | [201; 208) 'y.foo()': u64 |
4039 | [214; 215) 'z': dyn Trait<u64> | 4039 | [214; 215) 'z': dyn Trait<u64> |
4040 | [214; 221) 'z.foo()': {unknown} | 4040 | [214; 221) 'z.foo()': u64 |
4041 | [227; 228) 'x': dyn Trait<u64> | 4041 | [227; 228) 'x': dyn Trait<u64> |
4042 | [227; 235) 'x.foo2()': i64 | 4042 | [227; 235) 'x.foo2()': i64 |
4043 | [241; 242) 'y': &dyn Trait<u64> | 4043 | [241; 242) 'y': &dyn Trait<u64> |
@@ -4185,6 +4185,49 @@ fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { | |||
4185 | } | 4185 | } |
4186 | 4186 | ||
4187 | #[test] | 4187 | #[test] |
4188 | fn impl_trait_assoc_binding_projection_bug() { | ||
4189 | let (db, pos) = TestDB::with_position( | ||
4190 | r#" | ||
4191 | //- /main.rs crate:main deps:std | ||
4192 | pub trait Language { | ||
4193 | type Kind; | ||
4194 | } | ||
4195 | pub enum RustLanguage {} | ||
4196 | impl Language for RustLanguage { | ||
4197 | type Kind = SyntaxKind; | ||
4198 | } | ||
4199 | struct SyntaxNode<L> {} | ||
4200 | fn foo() -> impl Iterator<Item = SyntaxNode<RustLanguage>> {} | ||
4201 | |||
4202 | trait Clone { | ||
4203 | fn clone(&self) -> Self; | ||
4204 | } | ||
4205 | |||
4206 | fn api_walkthrough() { | ||
4207 | for node in foo() { | ||
4208 | node.clone()<|>; | ||
4209 | } | ||
4210 | } | ||
4211 | |||
4212 | //- /std.rs crate:std | ||
4213 | #[prelude_import] use iter::*; | ||
4214 | mod iter { | ||
4215 | trait IntoIterator { | ||
4216 | type Item; | ||
4217 | } | ||
4218 | trait Iterator { | ||
4219 | type Item; | ||
4220 | } | ||
4221 | impl<T: Iterator> IntoIterator for T { | ||
4222 | type Item = <T as Iterator>::Item; | ||
4223 | } | ||
4224 | } | ||
4225 | "#, | ||
4226 | ); | ||
4227 | assert_eq!("{unknown}", type_at_pos(&db, pos)); | ||
4228 | } | ||
4229 | |||
4230 | #[test] | ||
4188 | fn projection_eq_within_chalk() { | 4231 | fn projection_eq_within_chalk() { |
4189 | // std::env::set_var("CHALK_DEBUG", "1"); | 4232 | // std::env::set_var("CHALK_DEBUG", "1"); |
4190 | assert_snapshot!( | 4233 | assert_snapshot!( |
diff --git a/crates/ra_hir/src/ty/traits.rs b/crates/ra_hir/src/ty/traits.rs index 4f1eab150..45f725438 100644 --- a/crates/ra_hir/src/ty/traits.rs +++ b/crates/ra_hir/src/ty/traits.rs | |||
@@ -8,7 +8,7 @@ use ra_prof::profile; | |||
8 | use rustc_hash::FxHashSet; | 8 | use rustc_hash::FxHashSet; |
9 | 9 | ||
10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; | 10 | use super::{Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TypeWalk}; |
11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait}; | 11 | use crate::{db::HirDatabase, expr::ExprId, Crate, DefWithBody, ImplBlock, Trait, TypeAlias}; |
12 | 12 | ||
13 | use self::chalk::{from_chalk, ToChalk}; | 13 | use self::chalk::{from_chalk, ToChalk}; |
14 | 14 | ||
@@ -17,7 +17,7 @@ pub(crate) mod chalk; | |||
17 | #[derive(Debug, Clone)] | 17 | #[derive(Debug, Clone)] |
18 | pub struct TraitSolver { | 18 | pub struct TraitSolver { |
19 | krate: Crate, | 19 | krate: Crate, |
20 | inner: Arc<Mutex<chalk_solve::Solver>>, | 20 | inner: Arc<Mutex<chalk_solve::Solver<ChalkIr>>>, |
21 | } | 21 | } |
22 | 22 | ||
23 | /// We need eq for salsa | 23 | /// We need eq for salsa |
@@ -34,7 +34,7 @@ impl TraitSolver { | |||
34 | &self, | 34 | &self, |
35 | db: &impl HirDatabase, | 35 | db: &impl HirDatabase, |
36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, | 36 | goal: &chalk_ir::UCanonical<chalk_ir::InEnvironment<chalk_ir::Goal<ChalkIr>>>, |
37 | ) -> Option<chalk_solve::Solution> { | 37 | ) -> Option<chalk_solve::Solution<ChalkIr>> { |
38 | let context = ChalkContext { db, krate: self.krate }; | 38 | let context = ChalkContext { db, krate: self.krate }; |
39 | debug!("solve goal: {:?}", goal); | 39 | debug!("solve goal: {:?}", goal); |
40 | let mut solver = match self.inner.lock() { | 40 | let mut solver = match self.inner.lock() { |
@@ -165,9 +165,9 @@ impl TypeWalk for ProjectionPredicate { | |||
165 | self.ty.walk(f); | 165 | self.ty.walk(f); |
166 | } | 166 | } |
167 | 167 | ||
168 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | 168 | fn walk_mut_binders(&mut self, f: &mut impl FnMut(&mut Ty, usize), binders: usize) { |
169 | self.projection_ty.walk_mut(f); | 169 | self.projection_ty.walk_mut_binders(f, binders); |
170 | self.ty.walk_mut(f); | 170 | self.ty.walk_mut_binders(f, binders); |
171 | } | 171 | } |
172 | } | 172 | } |
173 | 173 | ||
@@ -188,6 +188,7 @@ pub(crate) fn trait_solve_query( | |||
188 | } | 188 | } |
189 | 189 | ||
190 | let canonical = goal.to_chalk(db).cast(); | 190 | let canonical = goal.to_chalk(db).cast(); |
191 | |||
191 | // We currently don't deal with universes (I think / hope they're not yet | 192 | // We currently don't deal with universes (I think / hope they're not yet |
192 | // relevant for our use cases?) | 193 | // relevant for our use cases?) |
193 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; | 194 | let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; |
@@ -195,7 +196,10 @@ pub(crate) fn trait_solve_query( | |||
195 | solution.map(|solution| solution_from_chalk(db, solution)) | 196 | solution.map(|solution| solution_from_chalk(db, solution)) |
196 | } | 197 | } |
197 | 198 | ||
198 | fn solution_from_chalk(db: &impl HirDatabase, solution: chalk_solve::Solution) -> Solution { | 199 | fn solution_from_chalk( |
200 | db: &impl HirDatabase, | ||
201 | solution: chalk_solve::Solution<ChalkIr>, | ||
202 | ) -> Solution { | ||
199 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { | 203 | let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<ChalkIr>>| { |
200 | let value = subst | 204 | let value = subst |
201 | .value | 205 | .value |
@@ -300,3 +304,14 @@ pub enum Impl { | |||
300 | /// Closure types implement the Fn traits synthetically. | 304 | /// Closure types implement the Fn traits synthetically. |
301 | ClosureFnTraitImpl(ClosureFnTraitImplData), | 305 | ClosureFnTraitImpl(ClosureFnTraitImplData), |
302 | } | 306 | } |
307 | |||
308 | /// An associated type value. Usually this comes from a `type` declaration | ||
309 | /// inside an impl block, but for built-in impls we have to synthesize it. | ||
310 | /// (We only need this because Chalk wants a unique ID for each of these.) | ||
311 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
312 | pub enum AssocTyValue { | ||
313 | /// A normal assoc type value from an impl block. | ||
314 | TypeAlias(TypeAlias), | ||
315 | /// The output type of the Fn trait implementation. | ||
316 | ClosureFnTraitImplOutput(ClosureFnTraitImplData), | ||
317 | } | ||
diff --git a/crates/ra_hir/src/ty/traits/chalk.rs b/crates/ra_hir/src/ty/traits/chalk.rs index 68304b950..9bf93981a 100644 --- a/crates/ra_hir/src/ty/traits/chalk.rs +++ b/crates/ra_hir/src/ty/traits/chalk.rs | |||
@@ -7,22 +7,19 @@ use chalk_ir::{ | |||
7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, | 7 | cast::Cast, family::ChalkIr, Identifier, ImplId, Parameter, PlaceholderIndex, TypeId, |
8 | TypeKindId, TypeName, UniverseIndex, | 8 | TypeKindId, TypeName, UniverseIndex, |
9 | }; | 9 | }; |
10 | use chalk_rust_ir::{AssociatedTyDatum, ImplDatum, StructDatum, TraitDatum}; | 10 | use chalk_rust_ir::{AssociatedTyDatum, AssociatedTyValue, ImplDatum, StructDatum, TraitDatum}; |
11 | 11 | ||
12 | use hir_expand::name; | 12 | use hir_expand::name; |
13 | 13 | ||
14 | use ra_db::salsa::{InternId, InternKey}; | 14 | use ra_db::salsa::{InternId, InternKey}; |
15 | 15 | ||
16 | use super::{Canonical, ChalkContext, Impl, Obligation}; | 16 | use super::{AssocTyValue, Canonical, ChalkContext, Impl, Obligation}; |
17 | use crate::{ | 17 | use crate::{ |
18 | db::HirDatabase, | 18 | db::HirDatabase, |
19 | generics::{GenericDef, HasGenericParams}, | 19 | generics::{GenericDef, HasGenericParams}, |
20 | ty::display::HirDisplay, | 20 | ty::display::HirDisplay, |
21 | ty::{ | 21 | ty::{ApplicationTy, GenericPredicate, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, TypeWalk}, |
22 | ApplicationTy, GenericPredicate, Namespace, ProjectionTy, Substs, TraitRef, Ty, TypeCtor, | 22 | Crate, HasBody, ImplBlock, Trait, TypeAlias, |
23 | TypeWalk, | ||
24 | }, | ||
25 | AssocItem, Crate, HasBody, ImplBlock, Trait, TypeAlias, | ||
26 | }; | 23 | }; |
27 | 24 | ||
28 | /// This represents a trait whose name we could not resolve. | 25 | /// This represents a trait whose name we could not resolve. |
@@ -59,29 +56,36 @@ impl ToChalk for Ty { | |||
59 | } | 56 | } |
60 | }; | 57 | }; |
61 | let parameters = apply_ty.parameters.to_chalk(db); | 58 | let parameters = apply_ty.parameters.to_chalk(db); |
62 | chalk_ir::ApplicationTy { name, parameters }.cast() | 59 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
63 | } | 60 | } |
64 | Ty::Projection(proj_ty) => { | 61 | Ty::Projection(proj_ty) => { |
65 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); | 62 | let associated_ty_id = proj_ty.associated_ty.to_chalk(db); |
66 | let parameters = proj_ty.parameters.to_chalk(db); | 63 | let parameters = proj_ty.parameters.to_chalk(db); |
67 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast() | 64 | chalk_ir::ProjectionTy { associated_ty_id, parameters }.cast().intern() |
68 | } | 65 | } |
69 | Ty::Param { idx, .. } => { | 66 | Ty::Param { idx, .. } => { |
70 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() | 67 | PlaceholderIndex { ui: UniverseIndex::ROOT, idx: idx as usize }.to_ty::<ChalkIr>() |
71 | } | 68 | } |
72 | Ty::Bound(idx) => chalk_ir::Ty::BoundVar(idx as usize), | 69 | Ty::Bound(idx) => chalk_ir::TyData::BoundVar(idx as usize).intern(), |
73 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), | 70 | Ty::Infer(_infer_ty) => panic!("uncanonicalized infer ty"), |
74 | // FIXME use Chalk's Dyn/Opaque once the bugs with that are fixed | 71 | Ty::Dyn(predicates) => { |
75 | Ty::Unknown | Ty::Dyn(_) | Ty::Opaque(_) => { | 72 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); |
73 | chalk_ir::TyData::Dyn(make_binders(where_clauses, 1)).intern() | ||
74 | } | ||
75 | Ty::Opaque(predicates) => { | ||
76 | let where_clauses = predicates.iter().cloned().map(|p| p.to_chalk(db)).collect(); | ||
77 | chalk_ir::TyData::Opaque(make_binders(where_clauses, 1)).intern() | ||
78 | } | ||
79 | Ty::Unknown => { | ||
76 | let parameters = Vec::new(); | 80 | let parameters = Vec::new(); |
77 | let name = TypeName::Error; | 81 | let name = TypeName::Error; |
78 | chalk_ir::ApplicationTy { name, parameters }.cast() | 82 | chalk_ir::ApplicationTy { name, parameters }.cast().intern() |
79 | } | 83 | } |
80 | } | 84 | } |
81 | } | 85 | } |
82 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { | 86 | fn from_chalk(db: &impl HirDatabase, chalk: chalk_ir::Ty<ChalkIr>) -> Self { |
83 | match chalk { | 87 | match chalk.data().clone() { |
84 | chalk_ir::Ty::Apply(apply_ty) => { | 88 | chalk_ir::TyData::Apply(apply_ty) => { |
85 | // FIXME this is kind of hacky due to the fact that | 89 | // FIXME this is kind of hacky due to the fact that |
86 | // TypeName::Placeholder is a Ty::Param on our side | 90 | // TypeName::Placeholder is a Ty::Param on our side |
87 | match apply_ty.name { | 91 | match apply_ty.name { |
@@ -104,21 +108,21 @@ impl ToChalk for Ty { | |||
104 | } | 108 | } |
105 | } | 109 | } |
106 | } | 110 | } |
107 | chalk_ir::Ty::Projection(proj) => { | 111 | chalk_ir::TyData::Projection(proj) => { |
108 | let associated_ty = from_chalk(db, proj.associated_ty_id); | 112 | let associated_ty = from_chalk(db, proj.associated_ty_id); |
109 | let parameters = from_chalk(db, proj.parameters); | 113 | let parameters = from_chalk(db, proj.parameters); |
110 | Ty::Projection(ProjectionTy { associated_ty, parameters }) | 114 | Ty::Projection(ProjectionTy { associated_ty, parameters }) |
111 | } | 115 | } |
112 | chalk_ir::Ty::ForAll(_) => unimplemented!(), | 116 | chalk_ir::TyData::ForAll(_) => unimplemented!(), |
113 | chalk_ir::Ty::BoundVar(idx) => Ty::Bound(idx as u32), | 117 | chalk_ir::TyData::BoundVar(idx) => Ty::Bound(idx as u32), |
114 | chalk_ir::Ty::InferenceVar(_iv) => Ty::Unknown, | 118 | chalk_ir::TyData::InferenceVar(_iv) => Ty::Unknown, |
115 | chalk_ir::Ty::Dyn(where_clauses) => { | 119 | chalk_ir::TyData::Dyn(where_clauses) => { |
116 | assert_eq!(where_clauses.binders.len(), 1); | 120 | assert_eq!(where_clauses.binders.len(), 1); |
117 | let predicates = | 121 | let predicates = |
118 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 122 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
119 | Ty::Dyn(predicates) | 123 | Ty::Dyn(predicates) |
120 | } | 124 | } |
121 | chalk_ir::Ty::Opaque(where_clauses) => { | 125 | chalk_ir::TyData::Opaque(where_clauses) => { |
122 | assert_eq!(where_clauses.binders.len(), 1); | 126 | assert_eq!(where_clauses.binders.len(), 1); |
123 | let predicates = | 127 | let predicates = |
124 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); | 128 | where_clauses.value.into_iter().map(|c| from_chalk(db, c)).collect(); |
@@ -211,6 +215,21 @@ impl ToChalk for TypeAlias { | |||
211 | } | 215 | } |
212 | } | 216 | } |
213 | 217 | ||
218 | impl ToChalk for AssocTyValue { | ||
219 | type Chalk = chalk_rust_ir::AssociatedTyValueId; | ||
220 | |||
221 | fn to_chalk(self, db: &impl HirDatabase) -> chalk_rust_ir::AssociatedTyValueId { | ||
222 | db.intern_assoc_ty_value(self).into() | ||
223 | } | ||
224 | |||
225 | fn from_chalk( | ||
226 | db: &impl HirDatabase, | ||
227 | assoc_ty_value_id: chalk_rust_ir::AssociatedTyValueId, | ||
228 | ) -> AssocTyValue { | ||
229 | db.lookup_intern_assoc_ty_value(assoc_ty_value_id.into()) | ||
230 | } | ||
231 | } | ||
232 | |||
214 | impl ToChalk for GenericPredicate { | 233 | impl ToChalk for GenericPredicate { |
215 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; | 234 | type Chalk = chalk_ir::QuantifiedWhereClause<ChalkIr>; |
216 | 235 | ||
@@ -399,20 +418,20 @@ fn convert_where_clauses( | |||
399 | result | 418 | result |
400 | } | 419 | } |
401 | 420 | ||
402 | impl<'a, DB> chalk_solve::RustIrDatabase for ChalkContext<'a, DB> | 421 | impl<'a, DB> chalk_solve::RustIrDatabase<ChalkIr> for ChalkContext<'a, DB> |
403 | where | 422 | where |
404 | DB: HirDatabase, | 423 | DB: HirDatabase, |
405 | { | 424 | { |
406 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum> { | 425 | fn associated_ty_data(&self, id: TypeId) -> Arc<AssociatedTyDatum<ChalkIr>> { |
407 | self.db.associated_ty_data(id) | 426 | self.db.associated_ty_data(id) |
408 | } | 427 | } |
409 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum> { | 428 | fn trait_datum(&self, trait_id: chalk_ir::TraitId) -> Arc<TraitDatum<ChalkIr>> { |
410 | self.db.trait_datum(self.krate, trait_id) | 429 | self.db.trait_datum(self.krate, trait_id) |
411 | } | 430 | } |
412 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum> { | 431 | fn struct_datum(&self, struct_id: chalk_ir::StructId) -> Arc<StructDatum<ChalkIr>> { |
413 | self.db.struct_datum(self.krate, struct_id) | 432 | self.db.struct_datum(self.krate, struct_id) |
414 | } | 433 | } |
415 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum> { | 434 | fn impl_datum(&self, impl_id: ImplId) -> Arc<ImplDatum<ChalkIr>> { |
416 | self.db.impl_datum(self.krate, impl_id) | 435 | self.db.impl_datum(self.krate, impl_id) |
417 | } | 436 | } |
418 | fn impls_for_trait( | 437 | fn impls_for_trait( |
@@ -462,13 +481,11 @@ where | |||
462 | fn type_name(&self, _id: TypeKindId) -> Identifier { | 481 | fn type_name(&self, _id: TypeKindId) -> Identifier { |
463 | unimplemented!() | 482 | unimplemented!() |
464 | } | 483 | } |
465 | fn split_projection<'p>( | 484 | fn associated_ty_value( |
466 | &self, | 485 | &self, |
467 | projection: &'p chalk_ir::ProjectionTy<ChalkIr>, | 486 | id: chalk_rust_ir::AssociatedTyValueId, |
468 | ) -> (Arc<AssociatedTyDatum>, &'p [Parameter<ChalkIr>], &'p [Parameter<ChalkIr>]) { | 487 | ) -> Arc<AssociatedTyValue<ChalkIr>> { |
469 | debug!("split_projection {:?}", projection); | 488 | self.db.associated_ty_value(self.krate, id) |
470 | // we don't support GATs, so I think this should always be correct currently | ||
471 | (self.db.associated_ty_data(projection.associated_ty_id), &projection.parameters, &[]) | ||
472 | } | 489 | } |
473 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { | 490 | fn custom_clauses(&self) -> Vec<chalk_ir::ProgramClause<ChalkIr>> { |
474 | vec![] | 491 | vec![] |
@@ -485,7 +502,7 @@ where | |||
485 | pub(crate) fn associated_ty_data_query( | 502 | pub(crate) fn associated_ty_data_query( |
486 | db: &impl HirDatabase, | 503 | db: &impl HirDatabase, |
487 | id: TypeId, | 504 | id: TypeId, |
488 | ) -> Arc<AssociatedTyDatum> { | 505 | ) -> Arc<AssociatedTyDatum<ChalkIr>> { |
489 | debug!("associated_ty_data {:?}", id); | 506 | debug!("associated_ty_data {:?}", id); |
490 | let type_alias: TypeAlias = from_chalk(db, id); | 507 | let type_alias: TypeAlias = from_chalk(db, id); |
491 | let trait_ = match type_alias.container(db) { | 508 | let trait_ = match type_alias.container(db) { |
@@ -493,19 +510,16 @@ pub(crate) fn associated_ty_data_query( | |||
493 | _ => panic!("associated type not in trait"), | 510 | _ => panic!("associated type not in trait"), |
494 | }; | 511 | }; |
495 | let generic_params = type_alias.generic_params(db); | 512 | let generic_params = type_alias.generic_params(db); |
496 | let parameter_kinds = generic_params | 513 | let bound_data = chalk_rust_ir::AssociatedTyDatumBound { |
497 | .params_including_parent() | 514 | // FIXME add bounds and where clauses |
498 | .into_iter() | 515 | bounds: vec![], |
499 | .map(|p| chalk_ir::ParameterKind::Ty(lalrpop_intern::intern(&p.name.to_string()))) | 516 | where_clauses: vec![], |
500 | .collect(); | 517 | }; |
501 | let datum = AssociatedTyDatum { | 518 | let datum = AssociatedTyDatum { |
502 | trait_id: trait_.to_chalk(db), | 519 | trait_id: trait_.to_chalk(db), |
503 | id, | 520 | id, |
504 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), | 521 | name: lalrpop_intern::intern(&type_alias.name(db).to_string()), |
505 | parameter_kinds, | 522 | binders: make_binders(bound_data, generic_params.count_params_including_parent()), |
506 | // FIXME add bounds and where clauses | ||
507 | bounds: vec![], | ||
508 | where_clauses: vec![], | ||
509 | }; | 523 | }; |
510 | Arc::new(datum) | 524 | Arc::new(datum) |
511 | } | 525 | } |
@@ -514,17 +528,10 @@ pub(crate) fn trait_datum_query( | |||
514 | db: &impl HirDatabase, | 528 | db: &impl HirDatabase, |
515 | krate: Crate, | 529 | krate: Crate, |
516 | trait_id: chalk_ir::TraitId, | 530 | trait_id: chalk_ir::TraitId, |
517 | ) -> Arc<TraitDatum> { | 531 | ) -> Arc<TraitDatum<ChalkIr>> { |
518 | debug!("trait_datum {:?}", trait_id); | 532 | debug!("trait_datum {:?}", trait_id); |
519 | if trait_id == UNKNOWN_TRAIT { | 533 | if trait_id == UNKNOWN_TRAIT { |
520 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { | 534 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses: Vec::new() }; |
521 | trait_ref: chalk_ir::TraitRef { | ||
522 | trait_id: UNKNOWN_TRAIT, | ||
523 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | ||
524 | }, | ||
525 | associated_ty_ids: Vec::new(), | ||
526 | where_clauses: Vec::new(), | ||
527 | }; | ||
528 | 535 | ||
529 | let flags = chalk_rust_ir::TraitFlags { | 536 | let flags = chalk_rust_ir::TraitFlags { |
530 | auto: false, | 537 | auto: false, |
@@ -532,18 +539,24 @@ pub(crate) fn trait_datum_query( | |||
532 | upstream: true, | 539 | upstream: true, |
533 | fundamental: false, | 540 | fundamental: false, |
534 | non_enumerable: true, | 541 | non_enumerable: true, |
542 | coinductive: false, | ||
535 | }; | 543 | }; |
536 | return Arc::new(TraitDatum { binders: make_binders(trait_datum_bound, 1), flags }); | 544 | return Arc::new(TraitDatum { |
545 | id: trait_id, | ||
546 | binders: make_binders(trait_datum_bound, 1), | ||
547 | flags, | ||
548 | associated_ty_ids: vec![], | ||
549 | }); | ||
537 | } | 550 | } |
538 | let trait_: Trait = from_chalk(db, trait_id); | 551 | let trait_: Trait = from_chalk(db, trait_id); |
539 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); | 552 | debug!("trait {:?} = {:?}", trait_id, trait_.name(db)); |
540 | let generic_params = trait_.generic_params(db); | 553 | let generic_params = trait_.generic_params(db); |
541 | let bound_vars = Substs::bound_vars(&generic_params); | 554 | let bound_vars = Substs::bound_vars(&generic_params); |
542 | let trait_ref = trait_.trait_ref(db).subst(&bound_vars).to_chalk(db); | ||
543 | let flags = chalk_rust_ir::TraitFlags { | 555 | let flags = chalk_rust_ir::TraitFlags { |
544 | auto: trait_.is_auto(db), | 556 | auto: trait_.is_auto(db), |
545 | upstream: trait_.module(db).krate() != krate, | 557 | upstream: trait_.module(db).krate() != krate, |
546 | non_enumerable: true, | 558 | non_enumerable: true, |
559 | coinductive: false, // only relevant for Chalk testing | ||
547 | // FIXME set these flags correctly | 560 | // FIXME set these flags correctly |
548 | marker: false, | 561 | marker: false, |
549 | fundamental: false, | 562 | fundamental: false, |
@@ -558,10 +571,13 @@ pub(crate) fn trait_datum_query( | |||
558 | }) | 571 | }) |
559 | .map(|type_alias| type_alias.to_chalk(db)) | 572 | .map(|type_alias| type_alias.to_chalk(db)) |
560 | .collect(); | 573 | .collect(); |
561 | let trait_datum_bound = | 574 | let trait_datum_bound = chalk_rust_ir::TraitDatumBound { where_clauses }; |
562 | chalk_rust_ir::TraitDatumBound { trait_ref, where_clauses, associated_ty_ids }; | 575 | let trait_datum = TraitDatum { |
563 | let trait_datum = | 576 | id: trait_id, |
564 | TraitDatum { binders: make_binders(trait_datum_bound, bound_vars.len()), flags }; | 577 | binders: make_binders(trait_datum_bound, bound_vars.len()), |
578 | flags, | ||
579 | associated_ty_ids, | ||
580 | }; | ||
565 | Arc::new(trait_datum) | 581 | Arc::new(trait_datum) |
566 | } | 582 | } |
567 | 583 | ||
@@ -569,7 +585,7 @@ pub(crate) fn struct_datum_query( | |||
569 | db: &impl HirDatabase, | 585 | db: &impl HirDatabase, |
570 | krate: Crate, | 586 | krate: Crate, |
571 | struct_id: chalk_ir::StructId, | 587 | struct_id: chalk_ir::StructId, |
572 | ) -> Arc<StructDatum> { | 588 | ) -> Arc<StructDatum<ChalkIr>> { |
573 | debug!("struct_datum {:?}", struct_id); | 589 | debug!("struct_datum {:?}", struct_id); |
574 | let type_ctor: TypeCtor = from_chalk(db, struct_id); | 590 | let type_ctor: TypeCtor = from_chalk(db, struct_id); |
575 | debug!("struct {:?} = {:?}", struct_id, type_ctor); | 591 | debug!("struct {:?} = {:?}", struct_id, type_ctor); |
@@ -588,17 +604,12 @@ pub(crate) fn struct_datum_query( | |||
588 | // FIXME set fundamental flag correctly | 604 | // FIXME set fundamental flag correctly |
589 | fundamental: false, | 605 | fundamental: false, |
590 | }; | 606 | }; |
591 | let self_ty = chalk_ir::ApplicationTy { | ||
592 | name: TypeName::TypeKindId(type_ctor.to_chalk(db).into()), | ||
593 | parameters: (0..num_params).map(|i| chalk_ir::Ty::BoundVar(i).cast()).collect(), | ||
594 | }; | ||
595 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { | 607 | let struct_datum_bound = chalk_rust_ir::StructDatumBound { |
596 | self_ty, | ||
597 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) | 608 | fields: Vec::new(), // FIXME add fields (only relevant for auto traits) |
598 | where_clauses, | 609 | where_clauses, |
599 | flags, | ||
600 | }; | 610 | }; |
601 | let struct_datum = StructDatum { binders: make_binders(struct_datum_bound, num_params) }; | 611 | let struct_datum = |
612 | StructDatum { id: struct_id, binders: make_binders(struct_datum_bound, num_params), flags }; | ||
602 | Arc::new(struct_datum) | 613 | Arc::new(struct_datum) |
603 | } | 614 | } |
604 | 615 | ||
@@ -606,16 +617,15 @@ pub(crate) fn impl_datum_query( | |||
606 | db: &impl HirDatabase, | 617 | db: &impl HirDatabase, |
607 | krate: Crate, | 618 | krate: Crate, |
608 | impl_id: ImplId, | 619 | impl_id: ImplId, |
609 | ) -> Arc<ImplDatum> { | 620 | ) -> Arc<ImplDatum<ChalkIr>> { |
610 | let _p = ra_prof::profile("impl_datum"); | 621 | let _p = ra_prof::profile("impl_datum"); |
611 | debug!("impl_datum {:?}", impl_id); | 622 | debug!("impl_datum {:?}", impl_id); |
612 | let impl_: Impl = from_chalk(db, impl_id); | 623 | let impl_: Impl = from_chalk(db, impl_id); |
613 | match impl_ { | 624 | match impl_ { |
614 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), | 625 | Impl::ImplBlock(impl_block) => impl_block_datum(db, krate, impl_id, impl_block), |
615 | Impl::ClosureFnTraitImpl(data) => { | 626 | Impl::ClosureFnTraitImpl(data) => closure_fn_trait_impl_datum(db, krate, data), |
616 | closure_fn_trait_impl_datum(db, krate, impl_id, data).unwrap_or_else(invalid_impl_datum) | ||
617 | } | ||
618 | } | 627 | } |
628 | .unwrap_or_else(invalid_impl_datum) | ||
619 | } | 629 | } |
620 | 630 | ||
621 | fn impl_block_datum( | 631 | fn impl_block_datum( |
@@ -623,13 +633,11 @@ fn impl_block_datum( | |||
623 | krate: Crate, | 633 | krate: Crate, |
624 | impl_id: ImplId, | 634 | impl_id: ImplId, |
625 | impl_block: ImplBlock, | 635 | impl_block: ImplBlock, |
626 | ) -> Arc<ImplDatum> { | 636 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
627 | let generic_params = impl_block.generic_params(db); | 637 | let generic_params = impl_block.generic_params(db); |
628 | let bound_vars = Substs::bound_vars(&generic_params); | 638 | let bound_vars = Substs::bound_vars(&generic_params); |
629 | let trait_ref = impl_block | 639 | let trait_ref = impl_block.target_trait_ref(db)?.subst(&bound_vars); |
630 | .target_trait_ref(db) | 640 | let trait_ = trait_ref.trait_; |
631 | .expect("FIXME handle unresolved impl block trait ref") | ||
632 | .subst(&bound_vars); | ||
633 | let impl_type = if impl_block.krate(db) == krate { | 641 | let impl_type = if impl_block.krate(db) == krate { |
634 | chalk_rust_ir::ImplType::Local | 642 | chalk_rust_ir::ImplType::Local |
635 | } else { | 643 | } else { |
@@ -644,28 +652,7 @@ fn impl_block_datum( | |||
644 | trait_ref.display(db), | 652 | trait_ref.display(db), |
645 | where_clauses | 653 | where_clauses |
646 | ); | 654 | ); |
647 | let trait_ = trait_ref.trait_; | ||
648 | let trait_ref = trait_ref.to_chalk(db); | 655 | let trait_ref = trait_ref.to_chalk(db); |
649 | let associated_ty_values = impl_block | ||
650 | .items(db) | ||
651 | .into_iter() | ||
652 | .filter_map(|item| match item { | ||
653 | AssocItem::TypeAlias(t) => Some(t), | ||
654 | _ => None, | ||
655 | }) | ||
656 | .filter_map(|t| { | ||
657 | let assoc_ty = trait_.associated_type_by_name(db, &t.name(db))?; | ||
658 | let ty = db.type_for_def(t.into(), Namespace::Types).subst(&bound_vars); | ||
659 | Some(chalk_rust_ir::AssociatedTyValue { | ||
660 | impl_id, | ||
661 | associated_ty_id: assoc_ty.to_chalk(db), | ||
662 | value: chalk_ir::Binders { | ||
663 | value: chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }, | ||
664 | binders: vec![], // we don't support GATs yet | ||
665 | }, | ||
666 | }) | ||
667 | }) | ||
668 | .collect(); | ||
669 | 656 | ||
670 | let polarity = if negative { | 657 | let polarity = if negative { |
671 | chalk_rust_ir::Polarity::Negative | 658 | chalk_rust_ir::Polarity::Negative |
@@ -673,31 +660,41 @@ fn impl_block_datum( | |||
673 | chalk_rust_ir::Polarity::Positive | 660 | chalk_rust_ir::Polarity::Positive |
674 | }; | 661 | }; |
675 | 662 | ||
676 | let impl_datum_bound = | 663 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses }; |
677 | chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses, associated_ty_values }; | 664 | let associated_ty_value_ids = impl_block |
665 | .items(db) | ||
666 | .into_iter() | ||
667 | .filter_map(|item| match item { | ||
668 | crate::AssocItem::TypeAlias(type_alias) => Some(type_alias), | ||
669 | _ => None, | ||
670 | }) | ||
671 | .filter(|type_alias| { | ||
672 | // don't include associated types that don't exist in the trait | ||
673 | trait_.associated_type_by_name(db, &type_alias.name(db)).is_some() | ||
674 | }) | ||
675 | .map(|type_alias| AssocTyValue::TypeAlias(type_alias).to_chalk(db)) | ||
676 | .collect(); | ||
678 | debug!("impl_datum: {:?}", impl_datum_bound); | 677 | debug!("impl_datum: {:?}", impl_datum_bound); |
679 | let impl_datum = ImplDatum { | 678 | let impl_datum = ImplDatum { |
680 | binders: make_binders(impl_datum_bound, bound_vars.len()), | 679 | binders: make_binders(impl_datum_bound, bound_vars.len()), |
681 | impl_type, | 680 | impl_type, |
682 | polarity, | 681 | polarity, |
682 | associated_ty_value_ids, | ||
683 | }; | 683 | }; |
684 | Arc::new(impl_datum) | 684 | Some(Arc::new(impl_datum)) |
685 | } | 685 | } |
686 | 686 | ||
687 | fn invalid_impl_datum() -> Arc<ImplDatum> { | 687 | fn invalid_impl_datum() -> Arc<ImplDatum<ChalkIr>> { |
688 | let trait_ref = chalk_ir::TraitRef { | 688 | let trait_ref = chalk_ir::TraitRef { |
689 | trait_id: UNKNOWN_TRAIT, | 689 | trait_id: UNKNOWN_TRAIT, |
690 | parameters: vec![chalk_ir::Ty::BoundVar(0).cast()], | 690 | parameters: vec![chalk_ir::TyData::BoundVar(0).cast().intern().cast()], |
691 | }; | ||
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | ||
693 | trait_ref, | ||
694 | where_clauses: Vec::new(), | ||
695 | associated_ty_values: Vec::new(), | ||
696 | }; | 691 | }; |
692 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { trait_ref, where_clauses: Vec::new() }; | ||
697 | let impl_datum = ImplDatum { | 693 | let impl_datum = ImplDatum { |
698 | binders: make_binders(impl_datum_bound, 1), | 694 | binders: make_binders(impl_datum_bound, 1), |
699 | impl_type: chalk_rust_ir::ImplType::External, | 695 | impl_type: chalk_rust_ir::ImplType::External, |
700 | polarity: chalk_rust_ir::Polarity::Positive, | 696 | polarity: chalk_rust_ir::Polarity::Positive, |
697 | associated_ty_value_ids: Vec::new(), | ||
701 | }; | 698 | }; |
702 | Arc::new(impl_datum) | 699 | Arc::new(impl_datum) |
703 | } | 700 | } |
@@ -705,15 +702,19 @@ fn invalid_impl_datum() -> Arc<ImplDatum> { | |||
705 | fn closure_fn_trait_impl_datum( | 702 | fn closure_fn_trait_impl_datum( |
706 | db: &impl HirDatabase, | 703 | db: &impl HirDatabase, |
707 | krate: Crate, | 704 | krate: Crate, |
708 | impl_id: ImplId, | ||
709 | data: super::ClosureFnTraitImplData, | 705 | data: super::ClosureFnTraitImplData, |
710 | ) -> Option<Arc<ImplDatum>> { | 706 | ) -> Option<Arc<ImplDatum<ChalkIr>>> { |
711 | // for some closure |X, Y| -> Z: | 707 | // for some closure |X, Y| -> Z: |
712 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } | 708 | // impl<T, U, V> Fn<(T, U)> for closure<fn(T, U) -> V> { Output = V } |
713 | 709 | ||
714 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
715 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait | 710 | let trait_ = get_fn_trait(db, krate, data.fn_trait)?; // get corresponding fn trait |
716 | 711 | ||
712 | // validate FnOnce trait, since we need it in the assoc ty value definition | ||
713 | // and don't want to return a valid value only to find out later that FnOnce | ||
714 | // is broken | ||
715 | let fn_once_trait = get_fn_trait(db, krate, super::FnTrait::FnOnce)?; | ||
716 | fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | ||
717 | |||
717 | let num_args: u16 = match &data.def.body(db)[data.expr] { | 718 | let num_args: u16 = match &data.def.body(db)[data.expr] { |
718 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | 719 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, |
719 | _ => { | 720 | _ => { |
@@ -726,7 +727,6 @@ fn closure_fn_trait_impl_datum( | |||
726 | TypeCtor::Tuple { cardinality: num_args }, | 727 | TypeCtor::Tuple { cardinality: num_args }, |
727 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), | 728 | Substs::builder(num_args as usize).fill_with_bound_vars(0).build(), |
728 | ); | 729 | ); |
729 | let output_ty = Ty::Bound(num_args.into()); | ||
730 | let sig_ty = Ty::apply( | 730 | let sig_ty = Ty::apply( |
731 | TypeCtor::FnPtr { num_args }, | 731 | TypeCtor::FnPtr { num_args }, |
732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), | 732 | Substs::builder(num_args as usize + 1).fill_with_bound_vars(0).build(), |
@@ -739,32 +739,99 @@ fn closure_fn_trait_impl_datum( | |||
739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), | 739 | substs: Substs::build_for_def(db, trait_).push(self_ty).push(arg_ty).build(), |
740 | }; | 740 | }; |
741 | 741 | ||
742 | let output_ty_id = fn_once_trait.associated_type_by_name(db, &name::OUTPUT_TYPE)?; | 742 | let output_ty_id = AssocTyValue::ClosureFnTraitImplOutput(data.clone()).to_chalk(db); |
743 | |||
744 | let output_ty_value = chalk_rust_ir::AssociatedTyValue { | ||
745 | associated_ty_id: output_ty_id.to_chalk(db), | ||
746 | impl_id, | ||
747 | value: make_binders( | ||
748 | chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }, | ||
749 | 0, | ||
750 | ), | ||
751 | }; | ||
752 | 743 | ||
753 | let impl_type = chalk_rust_ir::ImplType::External; | 744 | let impl_type = chalk_rust_ir::ImplType::External; |
754 | 745 | ||
755 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { | 746 | let impl_datum_bound = chalk_rust_ir::ImplDatumBound { |
756 | trait_ref: trait_ref.to_chalk(db), | 747 | trait_ref: trait_ref.to_chalk(db), |
757 | where_clauses: Vec::new(), | 748 | where_clauses: Vec::new(), |
758 | associated_ty_values: vec![output_ty_value], | ||
759 | }; | 749 | }; |
760 | let impl_datum = ImplDatum { | 750 | let impl_datum = ImplDatum { |
761 | binders: make_binders(impl_datum_bound, num_args as usize + 1), | 751 | binders: make_binders(impl_datum_bound, num_args as usize + 1), |
762 | impl_type, | 752 | impl_type, |
763 | polarity: chalk_rust_ir::Polarity::Positive, | 753 | polarity: chalk_rust_ir::Polarity::Positive, |
754 | associated_ty_value_ids: vec![output_ty_id], | ||
764 | }; | 755 | }; |
765 | Some(Arc::new(impl_datum)) | 756 | Some(Arc::new(impl_datum)) |
766 | } | 757 | } |
767 | 758 | ||
759 | pub(crate) fn associated_ty_value_query( | ||
760 | db: &impl HirDatabase, | ||
761 | krate: Crate, | ||
762 | id: chalk_rust_ir::AssociatedTyValueId, | ||
763 | ) -> Arc<chalk_rust_ir::AssociatedTyValue<ChalkIr>> { | ||
764 | let data: AssocTyValue = from_chalk(db, id); | ||
765 | match data { | ||
766 | AssocTyValue::TypeAlias(type_alias) => { | ||
767 | type_alias_associated_ty_value(db, krate, type_alias) | ||
768 | } | ||
769 | AssocTyValue::ClosureFnTraitImplOutput(data) => { | ||
770 | closure_fn_trait_output_assoc_ty_value(db, krate, data) | ||
771 | } | ||
772 | } | ||
773 | } | ||
774 | |||
775 | fn type_alias_associated_ty_value( | ||
776 | db: &impl HirDatabase, | ||
777 | _krate: Crate, | ||
778 | type_alias: TypeAlias, | ||
779 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
780 | let impl_block = type_alias.impl_block(db).expect("assoc ty value should be in impl"); | ||
781 | let impl_id = Impl::ImplBlock(impl_block).to_chalk(db); | ||
782 | let trait_ = impl_block | ||
783 | .target_trait_ref(db) | ||
784 | .expect("assoc ty value should not exist") // we don't return any assoc ty values if the impl'd trait can't be resolved | ||
785 | .trait_; | ||
786 | let assoc_ty = trait_ | ||
787 | .associated_type_by_name(db, &type_alias.name(db)) | ||
788 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | ||
789 | let generic_params = impl_block.generic_params(db); | ||
790 | let bound_vars = Substs::bound_vars(&generic_params); | ||
791 | let ty = db.type_for_def(type_alias.into(), crate::ty::Namespace::Types).subst(&bound_vars); | ||
792 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; | ||
793 | let value = chalk_rust_ir::AssociatedTyValue { | ||
794 | impl_id, | ||
795 | associated_ty_id: assoc_ty.to_chalk(db), | ||
796 | value: make_binders(value_bound, bound_vars.len()), | ||
797 | }; | ||
798 | Arc::new(value) | ||
799 | } | ||
800 | |||
801 | fn closure_fn_trait_output_assoc_ty_value( | ||
802 | db: &impl HirDatabase, | ||
803 | krate: Crate, | ||
804 | data: super::ClosureFnTraitImplData, | ||
805 | ) -> Arc<AssociatedTyValue<ChalkIr>> { | ||
806 | let impl_id = Impl::ClosureFnTraitImpl(data.clone()).to_chalk(db); | ||
807 | |||
808 | let num_args: u16 = match &data.def.body(db)[data.expr] { | ||
809 | crate::expr::Expr::Lambda { args, .. } => args.len() as u16, | ||
810 | _ => { | ||
811 | log::warn!("closure for closure type {:?} not found", data); | ||
812 | 0 | ||
813 | } | ||
814 | }; | ||
815 | |||
816 | let output_ty = Ty::Bound(num_args.into()); | ||
817 | |||
818 | let fn_once_trait = | ||
819 | get_fn_trait(db, krate, super::FnTrait::FnOnce).expect("assoc ty value should not exist"); | ||
820 | |||
821 | let output_ty_id = fn_once_trait | ||
822 | .associated_type_by_name(db, &name::OUTPUT_TYPE) | ||
823 | .expect("assoc ty value should not exist"); | ||
824 | |||
825 | let value_bound = chalk_rust_ir::AssociatedTyValueBound { ty: output_ty.to_chalk(db) }; | ||
826 | |||
827 | let value = chalk_rust_ir::AssociatedTyValue { | ||
828 | associated_ty_id: output_ty_id.to_chalk(db), | ||
829 | impl_id, | ||
830 | value: make_binders(value_bound, num_args as usize + 1), | ||
831 | }; | ||
832 | Arc::new(value) | ||
833 | } | ||
834 | |||
768 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { | 835 | fn get_fn_trait(db: &impl HirDatabase, krate: Crate, fn_trait: super::FnTrait) -> Option<Trait> { |
769 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; | 836 | let target = db.lang_item(krate, fn_trait.lang_item_name().into())?; |
770 | match target { | 837 | match target { |
@@ -803,3 +870,15 @@ impl From<crate::ids::GlobalImplId> for chalk_ir::ImplId { | |||
803 | chalk_ir::ImplId(id_to_chalk(impl_id)) | 870 | chalk_ir::ImplId(id_to_chalk(impl_id)) |
804 | } | 871 | } |
805 | } | 872 | } |
873 | |||
874 | impl From<chalk_rust_ir::AssociatedTyValueId> for crate::ids::AssocTyValueId { | ||
875 | fn from(id: chalk_rust_ir::AssociatedTyValueId) -> Self { | ||
876 | id_from_chalk(id.0) | ||
877 | } | ||
878 | } | ||
879 | |||
880 | impl From<crate::ids::AssocTyValueId> for chalk_rust_ir::AssociatedTyValueId { | ||
881 | fn from(assoc_ty_value_id: crate::ids::AssocTyValueId) -> Self { | ||
882 | chalk_rust_ir::AssociatedTyValueId(id_to_chalk(assoc_ty_value_id)) | ||
883 | } | ||
884 | } | ||