aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs3
-rw-r--r--crates/hir_ty/src/display.rs6
-rw-r--r--crates/hir_ty/src/lib.rs44
-rw-r--r--crates/hir_ty/src/lower.rs23
-rw-r--r--crates/hir_ty/src/method_resolution.rs8
-rw-r--r--crates/hir_ty/src/traits/chalk.rs43
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs17
-rw-r--r--crates/hir_ty/src/types.rs36
-rw-r--r--crates/hir_ty/src/walk.rs8
9 files changed, 104 insertions, 84 deletions
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 8169b759f..db278d0db 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -245,7 +245,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
245 Some(callee) => callee, 245 Some(callee) => callee,
246 None => return, 246 None => return,
247 }; 247 };
248 let sig = db.callable_item_signature(callee.into()).value; 248 let sig =
249 db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0;
249 250
250 (sig, args) 251 (sig, args)
251 } 252 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 1108e5a10..2e178e5a8 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -353,7 +353,7 @@ impl HirDisplay for Ty {
353 .as_ref() 353 .as_ref()
354 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 354 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
355 let bounds = data.subst(parameters); 355 let bounds = data.subst(parameters);
356 bounds.value 356 bounds.into_value_and_skipped_binders().0
357 } else { 357 } else {
358 Vec::new() 358 Vec::new()
359 } 359 }
@@ -543,7 +543,7 @@ impl HirDisplay for Ty {
543 .as_ref() 543 .as_ref()
544 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 544 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
545 let bounds = data.subst(&parameters); 545 let bounds = data.subst(&parameters);
546 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 546 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
547 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 547 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
548 } 548 }
549 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 549 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
@@ -630,7 +630,7 @@ impl HirDisplay for Ty {
630 .as_ref() 630 .as_ref()
631 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 631 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
632 let bounds = data.subst(&opaque_ty.substitution); 632 let bounds = data.subst(&opaque_ty.substitution);
633 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 633 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
634 } 634 }
635 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 635 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
636 write!(f, "{{async block}}")?; 636 write!(f, "{{async block}}")?;
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index adfdcaa37..61b5cf269 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -118,49 +118,27 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
118} 118}
119 119
120impl<T> Binders<T> { 120impl<T> Binders<T> {
121 pub fn new(num_binders: usize, value: T) -> Self {
122 Self { num_binders, value }
123 }
124
125 pub fn wrap_empty(value: T) -> Self 121 pub fn wrap_empty(value: T) -> Self
126 where 122 where
127 T: TypeWalk, 123 T: TypeWalk,
128 { 124 {
129 Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } 125 Binders::empty(&Interner, value.shift_bound_vars(DebruijnIndex::ONE))
130 }
131
132 pub fn as_ref(&self) -> Binders<&T> {
133 Binders { num_binders: self.num_binders, value: &self.value }
134 }
135
136 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
137 Binders { num_binders: self.num_binders, value: f(self.value) }
138 }
139
140 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
141 Some(Binders { num_binders: self.num_binders, value: f(self.value)? })
142 }
143
144 pub fn skip_binders(&self) -> &T {
145 &self.value
146 }
147
148 pub fn into_value_and_skipped_binders(self) -> (T, usize) {
149 (self.value, self.num_binders)
150 } 126 }
151} 127}
152 128
153impl<T: Clone> Binders<&T> { 129impl<T: Clone> Binders<&T> {
154 pub fn cloned(&self) -> Binders<T> { 130 pub fn cloned(&self) -> Binders<T> {
155 Binders { num_binders: self.num_binders, value: self.value.clone() } 131 let (value, binders) = self.into_value_and_skipped_binders();
132 Binders::new(binders, value.clone())
156 } 133 }
157} 134}
158 135
159impl<T: TypeWalk> Binders<T> { 136impl<T: TypeWalk> Binders<T> {
160 /// Substitutes all variables. 137 /// Substitutes all variables.
161 pub fn subst(self, subst: &Substitution) -> T { 138 pub fn subst(self, subst: &Substitution) -> T {
162 assert_eq!(subst.len(&Interner), self.num_binders); 139 let (value, binders) = self.into_value_and_skipped_binders();
163 self.value.subst_bound_vars(subst) 140 assert_eq!(subst.len(&Interner), binders);
141 value.subst_bound_vars(subst)
164 } 142 }
165} 143}
166 144
@@ -334,12 +312,12 @@ impl Ty {
334 /// If this is a `dyn Trait` type, this returns the `Trait` part. 312 /// If this is a `dyn Trait` type, this returns the `Trait` part.
335 fn dyn_trait_ref(&self) -> Option<&TraitRef> { 313 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
336 match self.kind(&Interner) { 314 match self.kind(&Interner) {
337 TyKind::Dyn(dyn_ty) => { 315 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
338 dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { 316 match b.skip_binders() {
339 WhereClause::Implemented(trait_ref) => Some(trait_ref), 317 WhereClause::Implemented(trait_ref) => Some(trait_ref),
340 _ => None, 318 _ => None,
341 }) 319 }
342 } 320 }),
343 _ => None, 321 _ => None,
344 } 322 }
345 } 323 }
@@ -459,7 +437,7 @@ impl Ty {
459 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), 437 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
460 }; 438 };
461 439
462 predicates.map(|it| it.value) 440 predicates.map(|it| it.into_value_and_skipped_binders().0)
463 } 441 }
464 TyKind::Placeholder(idx) => { 442 TyKind::Placeholder(idx) => {
465 let id = from_placeholder_idx(db, *idx); 443 let id = from_placeholder_idx(db, *idx);
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index e9e4e69ad..19465b2ed 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -832,12 +832,15 @@ pub fn associated_type_shorthand_candidates<R>(
832 832
833 match res { 833 match res {
834 // FIXME: how to correctly handle higher-ranked bounds here? 834 // FIXME: how to correctly handle higher-ranked bounds here?
835 TypeNs::SelfType(impl_id) => { 835 TypeNs::SelfType(impl_id) => search(
836 search(db.impl_trait(impl_id)?.value.shift_bound_vars_out(DebruijnIndex::ONE)) 836 db.impl_trait(impl_id)?
837 } 837 .into_value_and_skipped_binders()
838 .0
839 .shift_bound_vars_out(DebruijnIndex::ONE),
840 ),
838 TypeNs::GenericParam(param_id) => { 841 TypeNs::GenericParam(param_id) => {
839 let predicates = db.generic_predicates_for_param(param_id); 842 let predicates = db.generic_predicates_for_param(param_id);
840 let res = predicates.iter().find_map(|pred| match &pred.value.value { 843 let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
841 // FIXME: how to correctly handle higher-ranked bounds here? 844 // FIXME: how to correctly handle higher-ranked bounds here?
842 WhereClause::Implemented(tr) => { 845 WhereClause::Implemented(tr) => {
843 search(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 846 search(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE))
@@ -1088,8 +1091,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1088 let ctx = 1091 let ctx =
1089 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1092 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1090 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); 1093 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1091 let ret = type_for_adt(db, def.into()); 1094 let (ret, binders) = type_for_adt(db, def.into()).into_value_and_skipped_binders();
1092 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) 1095 Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1093} 1096}
1094 1097
1095/// Build the type of a tuple struct constructor. 1098/// Build the type of a tuple struct constructor.
@@ -1114,8 +1117,8 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1114 let ctx = 1117 let ctx =
1115 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1118 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1116 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>(); 1119 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1117 let ret = type_for_adt(db, def.parent.into()); 1120 let (ret, binders) = type_for_adt(db, def.parent.into()).into_value_and_skipped_binders();
1118 Binders::new(ret.num_binders, CallableSig::from_params_and_return(params, ret.value, false)) 1121 Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1119} 1122}
1120 1123
1121/// Build the type of a tuple enum variant constructor. 1124/// Build the type of a tuple enum variant constructor.
@@ -1267,9 +1270,9 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1267 let resolver = impl_id.resolver(db.upcast()); 1270 let resolver = impl_id.resolver(db.upcast());
1268 let ctx = 1271 let ctx =
1269 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1272 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1270 let self_ty = db.impl_self_ty(impl_id); 1273 let (self_ty, binders) = db.impl_self_ty(impl_id).into_value_and_skipped_binders();
1271 let target_trait = impl_data.target_trait.as_ref()?; 1274 let target_trait = impl_data.target_trait.as_ref()?;
1272 Some(Binders::new(self_ty.num_binders, ctx.lower_trait_ref(target_trait, Some(self_ty.value))?)) 1275 Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?))
1273} 1276}
1274 1277
1275pub(crate) fn return_type_impl_traits( 1278pub(crate) fn return_type_impl_traits(
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 6ace970d1..ad5022808 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -102,11 +102,11 @@ impl TraitImpls {
102 for (_module_id, module_data) in crate_def_map.modules() { 102 for (_module_id, module_data) in crate_def_map.modules() {
103 for impl_id in module_data.scope.impls() { 103 for impl_id in module_data.scope.impls() {
104 let target_trait = match db.impl_trait(impl_id) { 104 let target_trait = match db.impl_trait(impl_id) {
105 Some(tr) => tr.value.hir_trait_id(), 105 Some(tr) => tr.skip_binders().hir_trait_id(),
106 None => continue, 106 None => continue,
107 }; 107 };
108 let self_ty = db.impl_self_ty(impl_id); 108 let self_ty = db.impl_self_ty(impl_id);
109 let self_ty_fp = TyFingerprint::for_impl(&self_ty.value); 109 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders());
110 impls 110 impls
111 .map 111 .map
112 .entry(target_trait) 112 .entry(target_trait)
@@ -201,7 +201,7 @@ impl InherentImpls {
201 } 201 }
202 202
203 let self_ty = db.impl_self_ty(impl_id); 203 let self_ty = db.impl_self_ty(impl_id);
204 if let Some(fp) = TyFingerprint::for_impl(&self_ty.value) { 204 if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) {
205 map.entry(fp).or_default().push(impl_id); 205 map.entry(fp).or_default().push(impl_id);
206 } 206 }
207 } 207 }
@@ -774,7 +774,7 @@ fn transform_receiver_ty(
774 AssocContainerId::ModuleId(_) => unreachable!(), 774 AssocContainerId::ModuleId(_) => unreachable!(),
775 }; 775 };
776 let sig = db.callable_item_signature(function_id.into()); 776 let sig = db.callable_item_signature(function_id.into());
777 Some(sig.value.params()[0].clone().subst_bound_vars(&substs)) 777 Some(sig.map(|s| s.params()[0].clone()).subst(&substs))
778} 778}
779 779
780pub fn implements_trait( 780pub fn implements_trait(
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index b7388b98c..47867f77e 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -184,10 +184,15 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
184 .db 184 .db
185 .return_type_impl_traits(func) 185 .return_type_impl_traits(func)
186 .expect("impl trait id without impl traits"); 186 .expect("impl trait id without impl traits");
187 let data = &datas.value.impl_traits[idx as usize]; 187 let data = &datas.skip_binders().impl_traits[idx as usize];
188 let bound = OpaqueTyDatumBound { 188 let bound = OpaqueTyDatumBound {
189 bounds: make_binders( 189 bounds: make_binders(
190 data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(), 190 data.bounds
191 .skip_binders()
192 .iter()
193 .cloned()
194 .map(|b| b.to_chalk(self.db))
195 .collect(),
191 1, 196 1,
192 ), 197 ),
193 where_clauses: make_binders(vec![], 0), 198 where_clauses: make_binders(vec![], 0),
@@ -535,7 +540,8 @@ fn impl_def_datum(
535 .impl_trait(impl_id) 540 .impl_trait(impl_id)
536 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk 541 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
537 .expect("invalid impl passed to Chalk") 542 .expect("invalid impl passed to Chalk")
538 .value; 543 .into_value_and_skipped_binders()
544 .0;
539 let impl_data = db.impl_data(impl_id); 545 let impl_data = db.impl_data(impl_id);
540 546
541 let generic_params = generics(db.upcast(), impl_id.into()); 547 let generic_params = generics(db.upcast(), impl_id.into());
@@ -605,18 +611,22 @@ fn type_alias_associated_ty_value(
605 _ => panic!("assoc ty value should be in impl"), 611 _ => panic!("assoc ty value should be in impl"),
606 }; 612 };
607 613
608 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved 614 let trait_ref = db
615 .impl_trait(impl_id)
616 .expect("assoc ty value should not exist")
617 .into_value_and_skipped_binders()
618 .0; // we don't return any assoc ty values if the impl'd trait can't be resolved
609 619
610 let assoc_ty = db 620 let assoc_ty = db
611 .trait_data(trait_ref.hir_trait_id()) 621 .trait_data(trait_ref.hir_trait_id())
612 .associated_type_by_name(&type_alias_data.name) 622 .associated_type_by_name(&type_alias_data.name)
613 .expect("assoc ty value should not exist"); // validated when building the impl data as well 623 .expect("assoc ty value should not exist"); // validated when building the impl data as well
614 let ty = db.ty(type_alias.into()); 624 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
615 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 625 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) };
616 let value = rust_ir::AssociatedTyValue { 626 let value = rust_ir::AssociatedTyValue {
617 impl_id: impl_id.to_chalk(db), 627 impl_id: impl_id.to_chalk(db),
618 associated_ty_id: to_assoc_type_id(assoc_ty), 628 associated_ty_id: to_assoc_type_id(assoc_ty),
619 value: make_binders(value_bound, ty.num_binders), 629 value: make_binders(value_bound, binders),
620 }; 630 };
621 Arc::new(value) 631 Arc::new(value)
622} 632}
@@ -628,20 +638,15 @@ pub(crate) fn fn_def_datum_query(
628) -> Arc<FnDefDatum> { 638) -> Arc<FnDefDatum> {
629 let callable_def: CallableDefId = from_chalk(db, fn_def_id); 639 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
630 let generic_params = generics(db.upcast(), callable_def.into()); 640 let generic_params = generics(db.upcast(), callable_def.into());
631 let sig = db.callable_item_signature(callable_def); 641 let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
632 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); 642 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 643 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
634 let bound = rust_ir::FnDefDatumBound { 644 let bound = rust_ir::FnDefDatumBound {
635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 645 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
636 inputs_and_output: make_binders( 646 inputs_and_output: make_binders(
637 rust_ir::FnDefInputsAndOutputDatum { 647 rust_ir::FnDefInputsAndOutputDatum {
638 argument_types: sig 648 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(),
639 .value 649 return_type: sig.ret().clone().to_chalk(db),
640 .params()
641 .iter()
642 .map(|ty| ty.clone().to_chalk(db))
643 .collect(),
644 return_type: sig.value.ret().clone().to_chalk(db),
645 } 650 }
646 .shifted_in(&Interner), 651 .shifted_in(&Interner),
647 0, 652 0,
@@ -650,12 +655,8 @@ pub(crate) fn fn_def_datum_query(
650 }; 655 };
651 let datum = FnDefDatum { 656 let datum = FnDefDatum {
652 id: fn_def_id, 657 id: fn_def_id,
653 sig: chalk_ir::FnSig { 658 sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs },
654 abi: (), 659 binders: make_binders(bound, binders),
655 safety: chalk_ir::Safety::Safe,
656 variadic: sig.value.is_varargs,
657 },
658 binders: make_binders(bound, sig.num_binders),
659 }; 660 };
660 Arc::new(datum) 661 Arc::new(datum)
661} 662}
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 67e88ebf4..72458f367 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -93,12 +93,13 @@ impl ToChalk for Ty {
93 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), 93 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
94 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), 94 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
95 TyKind::Dyn(dyn_ty) => { 95 TyKind::Dyn(dyn_ty) => {
96 let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
96 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( 97 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
97 &Interner, 98 &Interner,
98 dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), 99 bounds.interned().iter().cloned().map(|p| p.to_chalk(db)),
99 ); 100 );
100 let bounded_ty = chalk_ir::DynTy { 101 let bounded_ty = chalk_ir::DynTy {
101 bounds: make_binders(where_clauses, 1), 102 bounds: make_binders(where_clauses, binders),
102 lifetime: LifetimeData::Static.intern(&Interner), 103 lifetime: LifetimeData::Static.intern(&Interner),
103 }; 104 };
104 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner) 105 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
@@ -486,13 +487,14 @@ where
486 type Chalk = chalk_ir::Binders<T::Chalk>; 487 type Chalk = chalk_ir::Binders<T::Chalk>;
487 488
488 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { 489 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
490 let (value, binders) = self.into_value_and_skipped_binders();
489 chalk_ir::Binders::new( 491 chalk_ir::Binders::new(
490 chalk_ir::VariableKinds::from_iter( 492 chalk_ir::VariableKinds::from_iter(
491 &Interner, 493 &Interner,
492 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) 494 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
493 .take(self.num_binders), 495 .take(binders),
494 ), 496 ),
495 self.value.to_chalk(db), 497 value.to_chalk(db),
496 ) 498 )
497 } 499 }
498 500
@@ -537,7 +539,8 @@ pub(super) fn generic_predicate_to_inline_bound(
537 // An InlineBound is like a GenericPredicate, except the self type is left out. 539 // An InlineBound is like a GenericPredicate, except the self type is left out.
538 // We don't have a special type for this, but Chalk does. 540 // We don't have a special type for this, but Chalk does.
539 let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); 541 let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE);
540 match &pred.value { 542 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
543 match pred {
541 WhereClause::Implemented(trait_ref) => { 544 WhereClause::Implemented(trait_ref) => {
542 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in { 545 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in {
543 // we can only convert predicates back to type bounds if they 546 // we can only convert predicates back to type bounds if they
@@ -549,7 +552,7 @@ pub(super) fn generic_predicate_to_inline_bound(
549 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 552 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
550 .collect(); 553 .collect();
551 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; 554 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
552 Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) 555 Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), binders))
553 } 556 }
554 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 557 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
555 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in { 558 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in {
@@ -566,7 +569,7 @@ pub(super) fn generic_predicate_to_inline_bound(
566 associated_ty_id: projection_ty.associated_ty_id, 569 associated_ty_id: projection_ty.associated_ty_id,
567 parameters: Vec::new(), // FIXME we don't support generic associated types yet 570 parameters: Vec::new(), // FIXME we don't support generic associated types yet
568 }; 571 };
569 Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) 572 Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), binders))
570 } 573 }
571 _ => None, 574 _ => None,
572 } 575 }
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index bac086318..0e3dd511f 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -299,7 +299,41 @@ impl Substitution {
299#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 299#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
300pub struct Binders<T> { 300pub struct Binders<T> {
301 pub num_binders: usize, 301 pub num_binders: usize,
302 pub value: T, 302 value: T,
303}
304
305impl<T> Binders<T> {
306 pub fn new(num_binders: usize, value: T) -> Self {
307 Self { num_binders, value }
308 }
309
310 pub fn empty(_interner: &Interner, value: T) -> Self {
311 Self { num_binders: 0, value }
312 }
313
314 pub fn as_ref(&self) -> Binders<&T> {
315 Binders { num_binders: self.num_binders, value: &self.value }
316 }
317
318 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
319 Binders { num_binders: self.num_binders, value: f(self.value) }
320 }
321
322 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
323 Some(Binders { num_binders: self.num_binders, value: f(self.value)? })
324 }
325
326 pub fn skip_binders(&self) -> &T {
327 &self.value
328 }
329
330 pub fn into_value_and_skipped_binders(self) -> (T, usize) {
331 (self.value, self.num_binders)
332 }
333
334 pub fn skip_binders_mut(&mut self) -> &mut T {
335 &mut self.value
336 }
303} 337}
304 338
305/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 339/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
index 5dfd59746..b1e22da0a 100644
--- a/crates/hir_ty/src/walk.rs
+++ b/crates/hir_ty/src/walk.rs
@@ -139,7 +139,7 @@ impl TypeWalk for Ty {
139 } 139 }
140 } 140 }
141 TyKind::Dyn(dyn_ty) => { 141 TyKind::Dyn(dyn_ty) => {
142 for p in dyn_ty.bounds.value.interned().iter() { 142 for p in dyn_ty.bounds.skip_binders().interned().iter() {
143 p.walk(f); 143 p.walk(f);
144 } 144 }
145 } 145 }
@@ -167,7 +167,7 @@ impl TypeWalk for Ty {
167 p_ty.substitution.walk_mut_binders(f, binders); 167 p_ty.substitution.walk_mut_binders(f, binders);
168 } 168 }
169 TyKind::Dyn(dyn_ty) => { 169 TyKind::Dyn(dyn_ty) => {
170 for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { 170 for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) {
171 p.walk_mut_binders(f, binders.shifted_in()); 171 p.walk_mut_binders(f, binders.shifted_in());
172 } 172 }
173 } 173 }
@@ -294,7 +294,7 @@ impl TypeWalk for Substitution {
294 294
295impl<T: TypeWalk> TypeWalk for Binders<T> { 295impl<T: TypeWalk> TypeWalk for Binders<T> {
296 fn walk(&self, f: &mut impl FnMut(&Ty)) { 296 fn walk(&self, f: &mut impl FnMut(&Ty)) {
297 self.value.walk(f); 297 self.skip_binders().walk(f);
298 } 298 }
299 299
300 fn walk_mut_binders( 300 fn walk_mut_binders(
@@ -302,7 +302,7 @@ impl<T: TypeWalk> TypeWalk for Binders<T> {
302 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 302 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
303 binders: DebruijnIndex, 303 binders: DebruijnIndex,
304 ) { 304 ) {
305 self.value.walk_mut_binders(f, binders.shifted_in()) 305 self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in())
306 } 306 }
307} 307}
308 308