aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorFlorian Diebold <[email protected]>2021-03-21 12:22:22 +0000
committerFlorian Diebold <[email protected]>2021-03-21 17:01:14 +0000
commit590c41635952e19c3caae525a827499dbd360049 (patch)
treeeca7c162975ef901b723d255512e61c047e838b8 /crates/hir_ty
parent35868c4f7dc479dd5f731a2785ec6a203046ea9c (diff)
Introduce QuantifiedWhereClause and DynTy analogous to Chalk
This introduces a bunch of new binders in lots of places, which we have to be careful about, but we had to add them at some point.
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/display.rs48
-rw-r--r--crates/hir_ty/src/infer/unify.rs15
-rw-r--r--crates/hir_ty/src/lib.rs73
-rw-r--r--crates/hir_ty/src/lower.rs55
-rw-r--r--crates/hir_ty/src/traits/chalk.rs10
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs94
6 files changed, 197 insertions, 98 deletions
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 9d3b79be3..372671405 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,6 +1,6 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{borrow::Cow, fmt}; 3use std::fmt;
4 4
5use arrayvec::ArrayVec; 5use arrayvec::ArrayVec;
6use chalk_ir::Mutability; 6use chalk_ir::Mutability;
@@ -20,7 +20,7 @@ use crate::{
20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 20 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, 21 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
22 CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, 22 CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy,
23 ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, 23 ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause,
24}; 24};
25 25
26pub struct HirFormatter<'a> { 26pub struct HirFormatter<'a> {
@@ -328,9 +328,9 @@ impl HirDisplay for Ty {
328 328
329 // FIXME: all this just to decide whether to use parentheses... 329 // FIXME: all this just to decide whether to use parentheses...
330 let datas; 330 let datas;
331 let predicates = match t.interned(&Interner) { 331 let predicates: Vec<_> = match t.interned(&Interner) {
332 TyKind::Dyn(predicates) if predicates.len() > 1 => { 332 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
333 Cow::Borrowed(predicates.as_ref()) 333 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
334 } 334 }
335 &TyKind::Alias(AliasTy::Opaque(OpaqueTy { 335 &TyKind::Alias(AliasTy::Opaque(OpaqueTy {
336 opaque_ty_id, 336 opaque_ty_id,
@@ -345,17 +345,21 @@ impl HirDisplay for Ty {
345 .as_ref() 345 .as_ref()
346 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 346 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
347 let bounds = data.subst(parameters); 347 let bounds = data.subst(parameters);
348 Cow::Owned(bounds.value) 348 bounds.value
349 } else { 349 } else {
350 Cow::Borrowed(&[][..]) 350 Vec::new()
351 } 351 }
352 } 352 }
353 _ => Cow::Borrowed(&[][..]), 353 _ => Vec::new(),
354 }; 354 };
355 355
356 if let [WhereClause::Implemented(trait_ref), _] = predicates.as_ref() { 356 if let Some(WhereClause::Implemented(trait_ref)) =
357 predicates.get(0).map(|b| b.skip_binders())
358 {
357 let trait_ = trait_ref.hir_trait_id(); 359 let trait_ = trait_ref.hir_trait_id();
358 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { 360 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
361 && predicates.len() <= 2
362 {
359 return write!(f, "{}", ty_display); 363 return write!(f, "{}", ty_display);
360 } 364 }
361 } 365 }
@@ -586,13 +590,25 @@ impl HirDisplay for Ty {
586 _ => false, 590 _ => false,
587 }) 591 })
588 .collect::<Vec<_>>(); 592 .collect::<Vec<_>>();
589 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; 593 write_bounds_like_dyn_trait_with_prefix(
594 "impl",
595 &bounds
596 .iter()
597 .cloned()
598 .map(crate::Binders::wrap_empty)
599 .collect::<Vec<_>>(),
600 f,
601 )?;
590 } 602 }
591 } 603 }
592 } 604 }
593 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 605 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?,
594 TyKind::Dyn(predicates) => { 606 TyKind::Dyn(dyn_ty) => {
595 write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; 607 write_bounds_like_dyn_trait_with_prefix(
608 "dyn",
609 dyn_ty.bounds.skip_binders().interned(),
610 f,
611 )?;
596 } 612 }
597 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, 613 TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?,
598 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { 614 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
@@ -661,7 +677,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai
661 677
662pub fn write_bounds_like_dyn_trait_with_prefix( 678pub fn write_bounds_like_dyn_trait_with_prefix(
663 prefix: &str, 679 prefix: &str,
664 predicates: &[WhereClause], 680 predicates: &[QuantifiedWhereClause],
665 f: &mut HirFormatter, 681 f: &mut HirFormatter,
666) -> Result<(), HirDisplayError> { 682) -> Result<(), HirDisplayError> {
667 write!(f, "{}", prefix)?; 683 write!(f, "{}", prefix)?;
@@ -674,7 +690,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix(
674} 690}
675 691
676fn write_bounds_like_dyn_trait( 692fn write_bounds_like_dyn_trait(
677 predicates: &[WhereClause], 693 predicates: &[QuantifiedWhereClause],
678 f: &mut HirFormatter, 694 f: &mut HirFormatter,
679) -> Result<(), HirDisplayError> { 695) -> Result<(), HirDisplayError> {
680 // Note: This code is written to produce nice results (i.e. 696 // Note: This code is written to produce nice results (i.e.
@@ -687,7 +703,7 @@ fn write_bounds_like_dyn_trait(
687 let mut angle_open = false; 703 let mut angle_open = false;
688 let mut is_fn_trait = false; 704 let mut is_fn_trait = false;
689 for p in predicates.iter() { 705 for p in predicates.iter() {
690 match p { 706 match p.skip_binders() {
691 WhereClause::Implemented(trait_ref) => { 707 WhereClause::Implemented(trait_ref) => {
692 let trait_ = trait_ref.hir_trait_id(); 708 let trait_ = trait_ref.hir_trait_id();
693 if !is_fn_trait { 709 if !is_fn_trait {
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 1fc03c8f4..35b0a2059 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -310,9 +310,18 @@ impl InferenceTable {
310 310
311 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, 311 (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true,
312 312
313 (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { 313 (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2))
314 for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { 314 if dyn1.bounds.skip_binders().interned().len()
315 if !self.unify_preds(pred1, pred2, depth + 1) { 315 == dyn2.bounds.skip_binders().interned().len() =>
316 {
317 for (pred1, pred2) in dyn1
318 .bounds
319 .skip_binders()
320 .interned()
321 .iter()
322 .zip(dyn2.bounds.skip_binders().interned().iter())
323 {
324 if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) {
316 return false; 325 return false;
317 } 326 }
318 } 327 }
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index ad908f957..e4b1f92e4 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -132,6 +132,12 @@ impl TypeWalk for ProjectionTy {
132 } 132 }
133} 133}
134 134
135#[derive(Clone, PartialEq, Eq, Debug, Hash)]
136pub struct DynTy {
137 /// The unknown self type.
138 pub bounds: Binders<QuantifiedWhereClauses>,
139}
140
135pub type FnSig = chalk_ir::FnSig<Interner>; 141pub type FnSig = chalk_ir::FnSig<Interner>;
136 142
137#[derive(Clone, PartialEq, Eq, Debug, Hash)] 143#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -283,7 +289,7 @@ pub enum TyKind {
283 /// represents the `Self` type inside the bounds. This is currently 289 /// represents the `Self` type inside the bounds. This is currently
284 /// implicit; Chalk has the `Binders` struct to make it explicit, but it 290 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
285 /// didn't seem worth the overhead yet. 291 /// didn't seem worth the overhead yet.
286 Dyn(Arc<[WhereClause]>), 292 Dyn(DynTy),
287 293
288 /// A placeholder for a type which could not be computed; this is propagated 294 /// A placeholder for a type which could not be computed; this is propagated
289 /// to avoid useless error messages. Doubles as a placeholder where type 295 /// to avoid useless error messages. Doubles as a placeholder where type
@@ -490,6 +496,13 @@ impl<T> Binders<T> {
490 Self { num_binders, value } 496 Self { num_binders, value }
491 } 497 }
492 498
499 pub fn wrap_empty(value: T) -> Self
500 where
501 T: TypeWalk,
502 {
503 Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) }
504 }
505
493 pub fn as_ref(&self) -> Binders<&T> { 506 pub fn as_ref(&self) -> Binders<&T> {
494 Binders { num_binders: self.num_binders, value: &self.value } 507 Binders { num_binders: self.num_binders, value: &self.value }
495 } 508 }
@@ -501,6 +514,10 @@ impl<T> Binders<T> {
501 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { 514 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
502 Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) 515 Some(Binders { num_binders: self.num_binders, value: f(self.value)? })
503 } 516 }
517
518 pub fn skip_binders(&self) -> &T {
519 &self.value
520 }
504} 521}
505 522
506impl<T: Clone> Binders<&T> { 523impl<T: Clone> Binders<&T> {
@@ -614,6 +631,24 @@ impl TypeWalk for WhereClause {
614 } 631 }
615} 632}
616 633
634pub type QuantifiedWhereClause = Binders<WhereClause>;
635
636#[derive(Debug, Clone, PartialEq, Eq, Hash)]
637pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
638
639impl QuantifiedWhereClauses {
640 pub fn from_iter(
641 _interner: &Interner,
642 elements: impl IntoIterator<Item = QuantifiedWhereClause>,
643 ) -> Self {
644 QuantifiedWhereClauses(elements.into_iter().collect())
645 }
646
647 pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
648 &self.0
649 }
650}
651
617/// Basically a claim (currently not validated / checked) that the contained 652/// Basically a claim (currently not validated / checked) that the contained
618/// type / trait ref contains no inference variables; any inference variables it 653/// type / trait ref contains no inference variables; any inference variables it
619/// contained have been replaced by bound variables, and `kinds` tells us how 654/// contained have been replaced by bound variables, and `kinds` tells us how
@@ -810,12 +845,14 @@ impl Ty {
810 } 845 }
811 846
812 /// If this is a `dyn Trait` type, this returns the `Trait` part. 847 /// If this is a `dyn Trait` type, this returns the `Trait` part.
813 pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { 848 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
814 match self.interned(&Interner) { 849 match self.interned(&Interner) {
815 TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { 850 TyKind::Dyn(dyn_ty) => {
816 WhereClause::Implemented(trait_ref) => Some(trait_ref), 851 dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() {
817 _ => None, 852 WhereClause::Implemented(trait_ref) => Some(trait_ref),
818 }), 853 _ => None,
854 })
855 }
819 _ => None, 856 _ => None,
820 } 857 }
821 } 858 }
@@ -892,7 +929,7 @@ impl Ty {
892 } 929 }
893 } 930 }
894 931
895 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<WhereClause>> { 932 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
896 match self.interned(&Interner) { 933 match self.interned(&Interner) {
897 TyKind::OpaqueType(opaque_ty_id, ..) => { 934 TyKind::OpaqueType(opaque_ty_id, ..) => {
898 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { 935 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
@@ -905,10 +942,13 @@ impl Ty {
905 // This is only used by type walking. 942 // This is only used by type walking.
906 // Parameters will be walked outside, and projection predicate is not used. 943 // Parameters will be walked outside, and projection predicate is not used.
907 // So just provide the Future trait. 944 // So just provide the Future trait.
908 let impl_bound = WhereClause::Implemented(TraitRef { 945 let impl_bound = Binders::new(
909 trait_id: to_chalk_trait_id(future_trait), 946 0,
910 substitution: Substitution::empty(), 947 WhereClause::Implemented(TraitRef {
911 }); 948 trait_id: to_chalk_trait_id(future_trait),
949 substitution: Substitution::empty(),
950 }),
951 );
912 Some(vec![impl_bound]) 952 Some(vec![impl_bound])
913 } else { 953 } else {
914 None 954 None
@@ -953,6 +993,7 @@ impl Ty {
953 }) => proj.self_type_parameter() == self, 993 }) => proj.self_type_parameter() == self,
954 _ => false, 994 _ => false,
955 }) 995 })
996 .map(Binders::wrap_empty)
956 .collect_vec(); 997 .collect_vec();
957 998
958 Some(predicates) 999 Some(predicates)
@@ -1094,8 +1135,8 @@ impl TypeWalk for Ty {
1094 t.walk(f); 1135 t.walk(f);
1095 } 1136 }
1096 } 1137 }
1097 TyKind::Dyn(predicates) => { 1138 TyKind::Dyn(dyn_ty) => {
1098 for p in predicates.iter() { 1139 for p in dyn_ty.bounds.value.interned().iter() {
1099 p.walk(f); 1140 p.walk(f);
1100 } 1141 }
1101 } 1142 }
@@ -1122,8 +1163,8 @@ impl TypeWalk for Ty {
1122 TyKind::Alias(AliasTy::Projection(p_ty)) => { 1163 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1123 p_ty.substitution.walk_mut_binders(f, binders); 1164 p_ty.substitution.walk_mut_binders(f, binders);
1124 } 1165 }
1125 TyKind::Dyn(predicates) => { 1166 TyKind::Dyn(dyn_ty) => {
1126 for p in make_mut_slice(predicates) { 1167 for p in make_mut_slice(&mut dyn_ty.bounds.value.0) {
1127 p.walk_mut_binders(f, binders.shifted_in()); 1168 p.walk_mut_binders(f, binders.shifted_in());
1128 } 1169 }
1129 } 1170 }
@@ -1173,7 +1214,7 @@ pub struct ReturnTypeImplTraits {
1173 1214
1174#[derive(Clone, PartialEq, Eq, Debug, Hash)] 1215#[derive(Clone, PartialEq, Eq, Debug, Hash)]
1175pub(crate) struct ReturnTypeImplTrait { 1216pub(crate) struct ReturnTypeImplTrait {
1176 pub(crate) bounds: Binders<Vec<WhereClause>>, 1217 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
1177} 1218}
1178 1219
1179pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 1220pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index fd451a823..45591e920 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -33,9 +33,10 @@ use crate::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
34 variant_data, 34 variant_data,
35 }, 35 },
36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, ImplTraitId, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
37 OpaqueTy, PolyFnSig, ProjectionTy, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, 37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
38 TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, WhereClause, 38 ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty,
39 TyKind, TypeWalk, WhereClause,
39}; 40};
40 41
41#[derive(Debug)] 42#[derive(Debug)]
@@ -188,13 +189,14 @@ impl<'a> TyLoweringContext<'a> {
188 TypeRef::DynTrait(bounds) => { 189 TypeRef::DynTrait(bounds) => {
189 let self_ty = 190 let self_ty =
190 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); 191 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner);
191 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { 192 let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
192 bounds 193 QuantifiedWhereClauses::from_iter(
193 .iter() 194 &Interner,
194 .flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)) 195 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
195 .collect() 196 )
196 }); 197 });
197 TyKind::Dyn(predicates).intern(&Interner) 198 let bounds = Binders::new(1, bounds);
199 TyKind::Dyn(DynTy { bounds }).intern(&Interner)
198 } 200 }
199 TypeRef::ImplTrait(bounds) => { 201 TypeRef::ImplTrait(bounds) => {
200 match self.impl_trait_mode { 202 match self.impl_trait_mode {
@@ -376,7 +378,16 @@ impl<'a> TyLoweringContext<'a> {
376 // FIXME report error (ambiguous associated type) 378 // FIXME report error (ambiguous associated type)
377 TyKind::Unknown.intern(&Interner) 379 TyKind::Unknown.intern(&Interner)
378 } else { 380 } else {
379 TyKind::Dyn(Arc::new([WhereClause::Implemented(trait_ref)])).intern(&Interner) 381 let dyn_ty = DynTy {
382 bounds: Binders::new(
383 1,
384 QuantifiedWhereClauses::from_iter(
385 &Interner,
386 Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))),
387 ),
388 ),
389 };
390 TyKind::Dyn(dyn_ty).intern(&Interner)
380 }; 391 };
381 return (ty, None); 392 return (ty, None);
382 } 393 }
@@ -670,7 +681,7 @@ impl<'a> TyLoweringContext<'a> {
670 &'a self, 681 &'a self,
671 where_predicate: &'a WherePredicate, 682 where_predicate: &'a WherePredicate,
672 ignore_bindings: bool, 683 ignore_bindings: bool,
673 ) -> impl Iterator<Item = WhereClause> + 'a { 684 ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
674 match where_predicate { 685 match where_predicate {
675 WherePredicate::ForLifetime { target, bound, .. } 686 WherePredicate::ForLifetime { target, bound, .. }
676 | WherePredicate::TypeBound { target, bound } => { 687 | WherePredicate::TypeBound { target, bound } => {
@@ -705,12 +716,12 @@ impl<'a> TyLoweringContext<'a> {
705 bound: &'a TypeBound, 716 bound: &'a TypeBound,
706 self_ty: Ty, 717 self_ty: Ty,
707 ignore_bindings: bool, 718 ignore_bindings: bool,
708 ) -> impl Iterator<Item = WhereClause> + 'a { 719 ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
709 let mut bindings = None; 720 let mut bindings = None;
710 let trait_ref = match bound { 721 let trait_ref = match bound {
711 TypeBound::Path(path) => { 722 TypeBound::Path(path) => {
712 bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); 723 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
713 bindings.clone().map(WhereClause::Implemented) 724 bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b))
714 } 725 }
715 TypeBound::Lifetime(_) => None, 726 TypeBound::Lifetime(_) => None,
716 TypeBound::Error => None, 727 TypeBound::Error => None,
@@ -727,7 +738,7 @@ impl<'a> TyLoweringContext<'a> {
727 &'a self, 738 &'a self,
728 bound: &'a TypeBound, 739 bound: &'a TypeBound,
729 trait_ref: TraitRef, 740 trait_ref: TraitRef,
730 ) -> impl Iterator<Item = WhereClause> + 'a { 741 ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a {
731 let last_segment = match bound { 742 let last_segment = match bound {
732 TypeBound::Path(path) => path.segments().last(), 743 TypeBound::Path(path) => path.segments().last(),
733 TypeBound::Error | TypeBound::Lifetime(_) => None, 744 TypeBound::Error | TypeBound::Lifetime(_) => None,
@@ -743,7 +754,7 @@ impl<'a> TyLoweringContext<'a> {
743 &binding.name, 754 &binding.name,
744 ); 755 );
745 let (super_trait_ref, associated_ty) = match found { 756 let (super_trait_ref, associated_ty) = match found {
746 None => return SmallVec::<[WhereClause; 1]>::new(), 757 None => return SmallVec::<[QuantifiedWhereClause; 1]>::new(),
747 Some(t) => t, 758 Some(t) => t,
748 }; 759 };
749 let projection_ty = ProjectionTy { 760 let projection_ty = ProjectionTy {
@@ -757,7 +768,7 @@ impl<'a> TyLoweringContext<'a> {
757 let ty = self.lower_ty(type_ref); 768 let ty = self.lower_ty(type_ref);
758 let alias_eq = 769 let alias_eq =
759 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; 770 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
760 preds.push(WhereClause::AliasEq(alias_eq)); 771 preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq)));
761 } 772 }
762 for bound in &binding.bounds { 773 for bound in &binding.bounds {
763 preds.extend(self.lower_type_bound( 774 preds.extend(self.lower_type_bound(
@@ -888,6 +899,9 @@ pub(crate) fn generic_predicates_for_param_query(
888 db: &dyn HirDatabase, 899 db: &dyn HirDatabase,
889 param_id: TypeParamId, 900 param_id: TypeParamId,
890) -> Arc<[Binders<WhereClause>]> { 901) -> Arc<[Binders<WhereClause>]> {
902 // FIXME: these binders are for the type parameters of the def. We need to
903 // introduce another level of binders for quantified where clauses (for<'a>
904 // ...)
891 let resolver = param_id.parent.resolver(db.upcast()); 905 let resolver = param_id.parent.resolver(db.upcast());
892 let ctx = 906 let ctx =
893 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 907 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
@@ -906,7 +920,7 @@ pub(crate) fn generic_predicates_for_param_query(
906 WherePredicate::Lifetime { .. } => false, 920 WherePredicate::Lifetime { .. } => false,
907 }) 921 })
908 .flat_map(|pred| { 922 .flat_map(|pred| {
909 ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p)) 923 ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p.value))
910 }) 924 })
911 .collect() 925 .collect()
912} 926}
@@ -930,7 +944,7 @@ pub(crate) fn trait_environment_query(
930 let mut clauses = Vec::new(); 944 let mut clauses = Vec::new();
931 for pred in resolver.where_predicates_in_scope() { 945 for pred in resolver.where_predicates_in_scope() {
932 for pred in ctx.lower_where_predicate(pred, false) { 946 for pred in ctx.lower_where_predicate(pred, false) {
933 if let WhereClause::Implemented(tr) = &pred { 947 if let WhereClause::Implemented(tr) = &pred.skip_binders() {
934 traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); 948 traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id()));
935 } 949 }
936 let program_clause: chalk_ir::ProgramClause<Interner> = 950 let program_clause: chalk_ir::ProgramClause<Interner> =
@@ -971,6 +985,9 @@ pub(crate) fn generic_predicates_query(
971 db: &dyn HirDatabase, 985 db: &dyn HirDatabase,
972 def: GenericDefId, 986 def: GenericDefId,
973) -> Arc<[Binders<WhereClause>]> { 987) -> Arc<[Binders<WhereClause>]> {
988 // FIXME: these binders are for the type parameters of the def. We need to
989 // introduce another level of binders for quantified where clauses (for<'a>
990 // ...)
974 let resolver = def.resolver(db.upcast()); 991 let resolver = def.resolver(db.upcast());
975 let ctx = 992 let ctx =
976 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 993 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
@@ -978,7 +995,7 @@ pub(crate) fn generic_predicates_query(
978 resolver 995 resolver
979 .where_predicates_in_scope() 996 .where_predicates_in_scope()
980 .flat_map(|pred| { 997 .flat_map(|pred| {
981 ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p)) 998 ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p.value))
982 }) 999 })
983 .collect() 1000 .collect()
984} 1001}
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 944145603..4019fdf17 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -238,7 +238,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
238 }); 238 });
239 let bound = OpaqueTyDatumBound { 239 let bound = OpaqueTyDatumBound {
240 bounds: make_binders( 240 bounds: make_binders(
241 vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], 241 vec![
242 wrap_in_empty_binders(impl_bound).to_chalk(self.db),
243 wrap_in_empty_binders(proj_bound).to_chalk(self.db),
244 ],
242 1, 245 1,
243 ), 246 ),
244 where_clauses: make_binders(vec![], 0), 247 where_clauses: make_binders(vec![], 0),
@@ -397,7 +400,6 @@ pub(crate) fn associated_ty_data_query(
397 .iter() 400 .iter()
398 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) 401 .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false))
399 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) 402 .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty))
400 .map(|bound| make_binders(bound.shifted_in(&Interner), 0))
401 .collect(); 403 .collect();
402 404
403 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 405 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
@@ -720,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
720 chalk_ir::ClosureId(id.as_intern_id()) 722 chalk_ir::ClosureId(id.as_intern_id())
721 } 723 }
722} 724}
725
726fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
727 crate::Binders::wrap_empty(value)
728}
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 65feb82e5..5b9c7e831 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa
7use chalk_solve::rust_ir; 7use chalk_solve::rust_ir;
8 8
9use base_db::salsa::InternKey; 9use base_db::salsa::InternKey;
10use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, 13 db::HirDatabase,
14 from_assoc_type_id,
15 primitive::UintTy, 14 primitive::UintTy,
16 traits::{Canonical, DomainGoal}, 15 traits::{Canonical, DomainGoal},
17 AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, Scalar, Substitution, 16 AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy,
18 TraitRef, Ty, WhereClause, 17 QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
19}; 18};
20 19
21use super::interner::*; 20use super::interner::*;
@@ -95,10 +94,10 @@ impl ToChalk for Ty {
95 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), 94 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
96 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 95 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
97 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), 96 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
98 TyKind::Dyn(predicates) => { 97 TyKind::Dyn(dyn_ty) => {
99 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 98 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
100 &Interner, 99 &Interner,
101 predicates.iter().cloned().map(|p| p.to_chalk(db)), 100 dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)),
102 ); 101 );
103 let bounded_ty = chalk_ir::DynTy { 102 let bounded_ty = chalk_ir::DynTy {
104 bounds: make_binders(where_clauses, 1), 103 bounds: make_binders(where_clauses, 1),
@@ -144,13 +143,17 @@ impl ToChalk for Ty {
144 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, 143 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown,
145 chalk_ir::TyKind::Dyn(where_clauses) => { 144 chalk_ir::TyKind::Dyn(where_clauses) => {
146 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); 145 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
147 let predicates = where_clauses 146 let bounds = where_clauses
148 .bounds 147 .bounds
149 .skip_binders() 148 .skip_binders()
150 .iter(&Interner) 149 .iter(&Interner)
151 .map(|c| from_chalk(db, c.clone())) 150 .map(|c| from_chalk(db, c.clone()));
152 .collect(); 151 TyKind::Dyn(crate::DynTy {
153 TyKind::Dyn(predicates) 152 bounds: crate::Binders::new(
153 1,
154 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds),
155 ),
156 })
154 } 157 }
155 158
156 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), 159 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
@@ -305,33 +308,22 @@ impl ToChalk for TypeAliasAsValue {
305} 308}
306 309
307impl ToChalk for WhereClause { 310impl ToChalk for WhereClause {
308 type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; 311 type Chalk = chalk_ir::WhereClause<Interner>;
309 312
310 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { 313 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> {
311 match self { 314 match self {
312 WhereClause::Implemented(trait_ref) => { 315 WhereClause::Implemented(trait_ref) => {
313 let chalk_trait_ref = trait_ref.to_chalk(db); 316 chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db))
314 let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner);
315 make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0)
316 } 317 }
317 WhereClause::AliasEq(alias_eq) => make_binders( 318 WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)),
318 chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db).shifted_in(&Interner)),
319 0,
320 ),
321 } 319 }
322 } 320 }
323 321
324 fn from_chalk( 322 fn from_chalk(
325 db: &dyn HirDatabase, 323 db: &dyn HirDatabase,
326 where_clause: chalk_ir::QuantifiedWhereClause<Interner>, 324 where_clause: chalk_ir::WhereClause<Interner>,
327 ) -> WhereClause { 325 ) -> WhereClause {
328 // we don't produce any where clauses with binders and can't currently deal with them 326 match where_clause {
329 match where_clause
330 .skip_binders()
331 .clone()
332 .shifted_out(&Interner)
333 .expect("unexpected bound vars in where clause")
334 {
335 chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), 327 chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
336 chalk_ir::WhereClause::AliasEq(alias_eq) => { 328 chalk_ir::WhereClause::AliasEq(alias_eq) => {
337 WhereClause::AliasEq(from_chalk(db, alias_eq)) 329 WhereClause::AliasEq(from_chalk(db, alias_eq))
@@ -500,6 +492,29 @@ where
500 } 492 }
501} 493}
502 494
495impl<T: ToChalk> ToChalk for crate::Binders<T>
496where
497 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
498{
499 type Chalk = chalk_ir::Binders<T::Chalk>;
500
501 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
502 chalk_ir::Binders::new(
503 chalk_ir::VariableKinds::from_iter(
504 &Interner,
505 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
506 .take(self.num_binders),
507 ),
508 self.value.to_chalk(db),
509 )
510 }
511
512 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
513 let (v, b) = binders.into_value_and_skipped_binders();
514 crate::Binders::new(b.len(&Interner), from_chalk(db, v))
515 }
516}
517
503pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 518pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
504where 519where
505 T: HasInterner<Interner = Interner>, 520 T: HasInterner<Interner = Interner>,
@@ -522,21 +537,22 @@ pub(super) fn convert_where_clauses(
522 let generic_predicates = db.generic_predicates(def); 537 let generic_predicates = db.generic_predicates(def);
523 let mut result = Vec::with_capacity(generic_predicates.len()); 538 let mut result = Vec::with_capacity(generic_predicates.len());
524 for pred in generic_predicates.iter() { 539 for pred in generic_predicates.iter() {
525 result.push(pred.clone().subst(substs).to_chalk(db)); 540 result.push(crate::Binders::wrap_empty(pred.clone().subst(substs)).to_chalk(db));
526 } 541 }
527 result 542 result
528} 543}
529 544
530pub(super) fn generic_predicate_to_inline_bound( 545pub(super) fn generic_predicate_to_inline_bound(
531 db: &dyn HirDatabase, 546 db: &dyn HirDatabase,
532 pred: &WhereClause, 547 pred: &QuantifiedWhereClause,
533 self_ty: &Ty, 548 self_ty: &Ty,
534) -> Option<rust_ir::InlineBound<Interner>> { 549) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
535 // An InlineBound is like a GenericPredicate, except the self type is left out. 550 // An InlineBound is like a GenericPredicate, except the self type is left out.
536 // We don't have a special type for this, but Chalk does. 551 // We don't have a special type for this, but Chalk does.
537 match pred { 552 let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE);
553 match &pred.value {
538 WhereClause::Implemented(trait_ref) => { 554 WhereClause::Implemented(trait_ref) => {
539 if &trait_ref.substitution[0] != self_ty { 555 if trait_ref.self_type_parameter() != &self_ty_shifted_in {
540 // we can only convert predicates back to type bounds if they 556 // we can only convert predicates back to type bounds if they
541 // have the expected self type 557 // have the expected self type
542 return None; 558 return None;
@@ -546,19 +562,13 @@ pub(super) fn generic_predicate_to_inline_bound(
546 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 562 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
547 .collect(); 563 .collect();
548 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; 564 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
549 Some(rust_ir::InlineBound::TraitBound(trait_bound)) 565 Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders))
550 } 566 }
551 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 567 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
552 if &projection_ty.substitution[0] != self_ty { 568 if projection_ty.self_type_parameter() != &self_ty_shifted_in {
553 return None; 569 return None;
554 } 570 }
555 let trait_ = match from_assoc_type_id(projection_ty.associated_ty_id) 571 let trait_ = projection_ty.trait_(db);
556 .lookup(db.upcast())
557 .container
558 {
559 AssocContainerId::TraitId(t) => t,
560 _ => panic!("associated type not in trait"),
561 };
562 let args_no_self = projection_ty.substitution[1..] 572 let args_no_self = projection_ty.substitution[1..]
563 .iter() 573 .iter()
564 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 574 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
@@ -569,7 +579,7 @@ pub(super) fn generic_predicate_to_inline_bound(
569 associated_ty_id: projection_ty.associated_ty_id, 579 associated_ty_id: projection_ty.associated_ty_id,
570 parameters: Vec::new(), // FIXME we don't support generic associated types yet 580 parameters: Vec::new(), // FIXME we don't support generic associated types yet
571 }; 581 };
572 Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) 582 Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders))
573 } 583 }
574 _ => None, 584 _ => None,
575 } 585 }