aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-05 18:25:19 +0100
committerGitHub <[email protected]>2021-04-05 18:25:19 +0100
commitc91b5376835ab54cd4bca02953625ef1f1fabeba (patch)
tree390be0ec3c0a57db5188b06c86f0a7df0242b01c /crates/hir_ty
parent467a5c6cd13af6ccb76e9ebdb35f96fc10fb438f (diff)
parenta316d583600e11ee1fcc8027a838efafe435f03c (diff)
Merge #8348
8348: Make `Binders` more like Chalk r=flodiebold a=flodiebold Working towards #8313. - hide `value` - use `VariableKinds` - adjust `subst` to be like Chalk's `substitute` - also clean up some other `TypeWalk` stuff to prepare for it being replaced by Chalk's `Fold` Co-authored-by: Florian Diebold <[email protected]>
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/builder.rs7
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs3
-rw-r--r--crates/hir_ty/src/display.rs18
-rw-r--r--crates/hir_ty/src/infer.rs8
-rw-r--r--crates/hir_ty/src/infer/expr.rs18
-rw-r--r--crates/hir_ty/src/infer/pat.rs9
-rw-r--r--crates/hir_ty/src/infer/path.rs7
-rw-r--r--crates/hir_ty/src/infer/unify.rs21
-rw-r--r--crates/hir_ty/src/lib.rs75
-rw-r--r--crates/hir_ty/src/lower.rs135
-rw-r--r--crates/hir_ty/src/method_resolution.rs10
-rw-r--r--crates/hir_ty/src/traits/chalk.rs47
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs33
-rw-r--r--crates/hir_ty/src/types.rs69
-rw-r--r--crates/hir_ty/src/utils.rs12
-rw-r--r--crates/hir_ty/src/walk.rs30
16 files changed, 284 insertions, 218 deletions
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index 372621f73..9b2c6975a 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -139,7 +139,8 @@ impl TyBuilder<hir_def::AdtId> {
139 } else { 139 } else {
140 // each default can depend on the previous parameters 140 // each default can depend on the previous parameters
141 let subst_so_far = Substitution::intern(self.vec.clone()); 141 let subst_so_far = Substitution::intern(self.vec.clone());
142 self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); 142 self.vec
143 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
143 } 144 }
144 } 145 }
145 self 146 self
@@ -194,13 +195,13 @@ impl TyBuilder<TypeAliasId> {
194 195
195impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { 196impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
196 fn subst_binders(b: Binders<T>) -> Self { 197 fn subst_binders(b: Binders<T>) -> Self {
197 let param_count = b.num_binders; 198 let param_count = b.binders.len(&Interner);
198 TyBuilder::new(b, param_count) 199 TyBuilder::new(b, param_count)
199 } 200 }
200 201
201 pub fn build(self) -> T { 202 pub fn build(self) -> T {
202 let (b, subst) = self.build_internal(); 203 let (b, subst) = self.build_internal();
203 b.subst(&subst) 204 b.substitute(&Interner, &subst)
204 } 205 }
205} 206}
206 207
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..f31e6b108 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -352,8 +352,8 @@ impl HirDisplay for Ty {
352 let data = (*datas) 352 let data = (*datas)
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.substitute(&Interner, parameters);
356 bounds.value 356 bounds.into_value_and_skipped_binders().0
357 } else { 357 } else {
358 Vec::new() 358 Vec::new()
359 } 359 }
@@ -397,7 +397,7 @@ impl HirDisplay for Ty {
397 } 397 }
398 TyKind::FnDef(def, parameters) => { 398 TyKind::FnDef(def, parameters) => {
399 let def = from_chalk(f.db, *def); 399 let def = from_chalk(f.db, *def);
400 let sig = f.db.callable_item_signature(def).subst(parameters); 400 let sig = f.db.callable_item_signature(def).substitute(&Interner, parameters);
401 match def { 401 match def {
402 CallableDefId::FunctionId(ff) => { 402 CallableDefId::FunctionId(ff) => {
403 write!(f, "fn {}", f.db.function_data(ff).name)? 403 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -482,7 +482,7 @@ impl HirDisplay for Ty {
482 (_, Some(default_parameter)) => { 482 (_, Some(default_parameter)) => {
483 let actual_default = default_parameter 483 let actual_default = default_parameter
484 .clone() 484 .clone()
485 .subst(&parameters.prefix(i)); 485 .substitute(&Interner, &parameters.prefix(i));
486 if parameter.assert_ty_ref(&Interner) != &actual_default 486 if parameter.assert_ty_ref(&Interner) != &actual_default
487 { 487 {
488 default_from = i + 1; 488 default_from = i + 1;
@@ -542,8 +542,8 @@ impl HirDisplay for Ty {
542 let data = (*datas) 542 let data = (*datas)
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.substitute(&Interner, &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(..) => {
@@ -595,7 +595,7 @@ impl HirDisplay for Ty {
595 let bounds = 595 let bounds =
596 f.db.generic_predicates(id.parent) 596 f.db.generic_predicates(id.parent)
597 .into_iter() 597 .into_iter()
598 .map(|pred| pred.clone().subst(&substs)) 598 .map(|pred| pred.clone().substitute(&Interner, &substs))
599 .filter(|wc| match &wc.skip_binders() { 599 .filter(|wc| match &wc.skip_binders() {
600 WhereClause::Implemented(tr) => { 600 WhereClause::Implemented(tr) => {
601 tr.self_type_parameter(&Interner) == self 601 tr.self_type_parameter(&Interner) == self
@@ -629,8 +629,8 @@ impl HirDisplay for Ty {
629 let data = (*datas) 629 let data = (*datas)
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.substitute(&Interner, &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/infer.rs b/crates/hir_ty/src/infer.rs
index 6151e48cd..1c3faf5cb 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -470,25 +470,25 @@ impl<'a> InferenceContext<'a> {
470 TypeNs::AdtId(AdtId::StructId(strukt)) => { 470 TypeNs::AdtId(AdtId::StructId(strukt)) => {
471 let substs = ctx.substs_from_path(path, strukt.into(), true); 471 let substs = ctx.substs_from_path(path, strukt.into(), true);
472 let ty = self.db.ty(strukt.into()); 472 let ty = self.db.ty(strukt.into());
473 let ty = self.insert_type_vars(ty.subst(&substs)); 473 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
474 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) 474 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
475 } 475 }
476 TypeNs::AdtId(AdtId::UnionId(u)) => { 476 TypeNs::AdtId(AdtId::UnionId(u)) => {
477 let substs = ctx.substs_from_path(path, u.into(), true); 477 let substs = ctx.substs_from_path(path, u.into(), true);
478 let ty = self.db.ty(u.into()); 478 let ty = self.db.ty(u.into());
479 let ty = self.insert_type_vars(ty.subst(&substs)); 479 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
480 forbid_unresolved_segments((ty, Some(u.into())), unresolved) 480 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
481 } 481 }
482 TypeNs::EnumVariantId(var) => { 482 TypeNs::EnumVariantId(var) => {
483 let substs = ctx.substs_from_path(path, var.into(), true); 483 let substs = ctx.substs_from_path(path, var.into(), true);
484 let ty = self.db.ty(var.parent.into()); 484 let ty = self.db.ty(var.parent.into());
485 let ty = self.insert_type_vars(ty.subst(&substs)); 485 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
486 forbid_unresolved_segments((ty, Some(var.into())), unresolved) 486 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
487 } 487 }
488 TypeNs::SelfType(impl_id) => { 488 TypeNs::SelfType(impl_id) => {
489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
490 let substs = generics.type_params_subst(self.db); 490 let substs = generics.type_params_subst(self.db);
491 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 491 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
492 match unresolved { 492 match unresolved {
493 None => { 493 None => {
494 let variant = ty_variant(&ty); 494 let variant = ty_variant(&ty);
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index ccaae53e9..6966d26e7 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -419,7 +419,7 @@ impl<'a> InferenceContext<'a> {
419 self.result.record_field_resolutions.insert(field.expr, field_def); 419 self.result.record_field_resolutions.insert(field.expr, field_def);
420 } 420 }
421 let field_ty = field_def.map_or(self.err_ty(), |it| { 421 let field_ty = field_def.map_or(self.err_ty(), |it| {
422 field_types[it.local_id].clone().subst(&substs) 422 field_types[it.local_id].clone().substitute(&Interner, &substs)
423 }); 423 });
424 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 424 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
425 } 425 }
@@ -462,7 +462,7 @@ impl<'a> InferenceContext<'a> {
462 Some( 462 Some(
463 self.db.field_types((*s).into())[field.local_id] 463 self.db.field_types((*s).into())[field.local_id]
464 .clone() 464 .clone()
465 .subst(&parameters), 465 .substitute(&Interner, &parameters),
466 ) 466 )
467 } else { 467 } else {
468 None 468 None
@@ -476,7 +476,7 @@ impl<'a> InferenceContext<'a> {
476 Some( 476 Some(
477 self.db.field_types((*u).into())[field.local_id] 477 self.db.field_types((*u).into())[field.local_id]
478 .clone() 478 .clone()
479 .subst(&parameters), 479 .substitute(&Interner, &parameters),
480 ) 480 )
481 } else { 481 } else {
482 None 482 None
@@ -849,10 +849,10 @@ impl<'a> InferenceContext<'a> {
849 self.write_method_resolution(tgt_expr, func); 849 self.write_method_resolution(tgt_expr, func);
850 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) 850 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
851 } 851 }
852 None => (receiver_ty, Binders::new(0, self.err_ty()), None), 852 None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None),
853 }; 853 };
854 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); 854 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
855 let method_ty = method_ty.subst(&substs); 855 let method_ty = method_ty.substitute(&Interner, &substs);
856 let method_ty = self.insert_type_vars(method_ty); 856 let method_ty = self.insert_type_vars(method_ty);
857 self.register_obligations_for_call(&method_ty); 857 self.register_obligations_for_call(&method_ty);
858 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { 858 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) {
@@ -949,9 +949,11 @@ impl<'a> InferenceContext<'a> {
949 let def: CallableDefId = from_chalk(self.db, *fn_def); 949 let def: CallableDefId = from_chalk(self.db, *fn_def);
950 let generic_predicates = self.db.generic_predicates(def.into()); 950 let generic_predicates = self.db.generic_predicates(def.into());
951 for predicate in generic_predicates.iter() { 951 for predicate in generic_predicates.iter() {
952 let (predicate, binders) = 952 let (predicate, binders) = predicate
953 predicate.clone().subst(parameters).into_value_and_skipped_binders(); 953 .clone()
954 always!(binders == 0); // quantified where clauses not yet handled 954 .substitute(&Interner, parameters)
955 .into_value_and_skipped_binders();
956 always!(binders.len(&Interner) == 0); // quantified where clauses not yet handled
955 self.push_obligation(predicate.cast(&Interner)); 957 self.push_obligation(predicate.cast(&Interner));
956 } 958 }
957 // add obligation for trait implementation, if this is a trait method 959 // add obligation for trait implementation, if this is a trait method
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 469f37dd9..252ae914a 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -49,7 +49,9 @@ impl<'a> InferenceContext<'a> {
49 let expected_ty = var_data 49 let expected_ty = var_data
50 .as_ref() 50 .as_ref()
51 .and_then(|d| d.field(&Name::new_tuple_field(i))) 51 .and_then(|d| d.field(&Name::new_tuple_field(i)))
52 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs)); 52 .map_or(self.err_ty(), |field| {
53 field_tys[field].clone().substitute(&Interner, &substs)
54 });
53 let expected_ty = self.normalize_associated_types_in(expected_ty); 55 let expected_ty = self.normalize_associated_types_in(expected_ty);
54 self.infer_pat(subpat, &expected_ty, default_bm); 56 self.infer_pat(subpat, &expected_ty, default_bm);
55 } 57 }
@@ -83,8 +85,9 @@ impl<'a> InferenceContext<'a> {
83 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def); 85 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
84 } 86 }
85 87
86 let expected_ty = matching_field 88 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
87 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs)); 89 field_tys[field].clone().substitute(&Interner, &substs)
90 });
88 let expected_ty = self.normalize_associated_types_in(expected_ty); 91 let expected_ty = self.normalize_associated_types_in(expected_ty);
89 self.infer_pat(subpat.pat, &expected_ty, default_bm); 92 self.infer_pat(subpat.pat, &expected_ty, default_bm);
90 } 93 }
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 89d78e781..14f705173 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -81,9 +81,9 @@ impl<'a> InferenceContext<'a> {
81 ValueNs::ImplSelf(impl_id) => { 81 ValueNs::ImplSelf(impl_id) => {
82 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 82 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
83 let substs = generics.type_params_subst(self.db); 83 let substs = generics.type_params_subst(self.db);
84 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 84 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
85 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { 85 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
86 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 86 let ty = self.db.value_ty(struct_id.into()).substitute(&Interner, &substs);
87 return Some(ty); 87 return Some(ty);
88 } else { 88 } else {
89 // FIXME: diagnostic, invalid Self reference 89 // FIXME: diagnostic, invalid Self reference
@@ -243,7 +243,8 @@ impl<'a> InferenceContext<'a> {
243 let impl_substs = TyBuilder::subst_for_def(self.db, impl_id) 243 let impl_substs = TyBuilder::subst_for_def(self.db, impl_id)
244 .fill(iter::repeat_with(|| self.table.new_type_var())) 244 .fill(iter::repeat_with(|| self.table.new_type_var()))
245 .build(); 245 .build();
246 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); 246 let impl_self_ty =
247 self.db.impl_self_ty(impl_id).substitute(&Interner, &impl_substs);
247 self.unify(&impl_self_ty, &ty); 248 self.unify(&impl_self_ty, &ty);
248 Some(impl_substs) 249 Some(impl_substs)
249 } 250 }
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index 8370f2e1c..c90a16720 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -108,19 +108,22 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
108} 108}
109 109
110impl<T> Canonicalized<T> { 110impl<T> Canonicalized<T> {
111 pub(super) fn decanonicalize_ty(&self, mut ty: Ty) -> Ty { 111 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
112 ty.walk_mut_binders( 112 ty.fold_binders(
113 &mut |ty, binders| { 113 &mut |ty, binders| {
114 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { 114 if let TyKind::BoundVar(bound) = ty.kind(&Interner) {
115 if bound.debruijn >= binders { 115 if bound.debruijn >= binders {
116 let (v, k) = self.free_vars[bound.index]; 116 let (v, k) = self.free_vars[bound.index];
117 *ty = TyKind::InferenceVar(v, k).intern(&Interner); 117 TyKind::InferenceVar(v, k).intern(&Interner)
118 } else {
119 ty
118 } 120 }
121 } else {
122 ty
119 } 123 }
120 }, 124 },
121 DebruijnIndex::INNERMOST, 125 DebruijnIndex::INNERMOST,
122 ); 126 )
123 ty
124 } 127 }
125 128
126 pub(super) fn apply_solution( 129 pub(super) fn apply_solution(
@@ -149,7 +152,7 @@ impl<T> Canonicalized<T> {
149 // eagerly replace projections in the type; we may be getting types 152 // eagerly replace projections in the type; we may be getting types
150 // e.g. from where clauses where this hasn't happened yet 153 // e.g. from where clauses where this hasn't happened yet
151 let ty = ctx.normalize_associated_types_in( 154 let ty = ctx.normalize_associated_types_in(
152 ty.assert_ty_ref(&Interner).clone().subst_bound_vars(&new_vars), 155 new_vars.apply(ty.assert_ty_ref(&Interner).clone(), &Interner),
153 ); 156 );
154 ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty); 157 ctx.table.unify(&TyKind::InferenceVar(v, k).intern(&Interner), &ty);
155 } 158 }
@@ -170,8 +173,8 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
170 // fallback to Unknown in the end (kind of hacky, as below) 173 // fallback to Unknown in the end (kind of hacky, as below)
171 .map(|_| table.new_type_var()), 174 .map(|_| table.new_type_var()),
172 ); 175 );
173 let ty1_with_vars = tys.value.0.clone().subst_bound_vars(&vars); 176 let ty1_with_vars = vars.apply(tys.value.0.clone(), &Interner);
174 let ty2_with_vars = tys.value.1.clone().subst_bound_vars(&vars); 177 let ty2_with_vars = vars.apply(tys.value.1.clone(), &Interner);
175 if !table.unify(&ty1_with_vars, &ty2_with_vars) { 178 if !table.unify(&ty1_with_vars, &ty2_with_vars) {
176 return None; 179 return None;
177 } 180 }
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index adfdcaa37..daf379ef8 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -66,6 +66,8 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
66pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 66pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
67pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 67pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
68 68
69pub type VariableKind = chalk_ir::VariableKind<Interner>;
70pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
69pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; 71pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
70 72
71pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 73pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
@@ -118,52 +120,34 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
118} 120}
119 121
120impl<T> Binders<T> { 122impl<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 123 pub fn wrap_empty(value: T) -> Self
126 where 124 where
127 T: TypeWalk, 125 T: TypeWalk,
128 { 126 {
129 Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } 127 Binders::empty(&Interner, value.shifted_in_from(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 }
151}
152
153impl<T: Clone> Binders<&T> {
154 pub fn cloned(&self) -> Binders<T> {
155 Binders { num_binders: self.num_binders, value: self.value.clone() }
156 } 128 }
157} 129}
158 130
159impl<T: TypeWalk> Binders<T> { 131impl<T: TypeWalk> Binders<T> {
160 /// Substitutes all variables. 132 /// Substitutes all variables.
161 pub fn subst(self, subst: &Substitution) -> T { 133 pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
162 assert_eq!(subst.len(&Interner), self.num_binders); 134 let (value, binders) = self.into_value_and_skipped_binders();
163 self.value.subst_bound_vars(subst) 135 assert_eq!(subst.len(interner), binders.len(interner));
136 value.subst_bound_vars(subst)
164 } 137 }
165} 138}
166 139
140pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
141 Binders::new(
142 VariableKinds::from_iter(
143 &Interner,
144 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
145 .take(num_vars),
146 ),
147 value,
148 )
149}
150
167impl TraitRef { 151impl TraitRef {
168 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty { 152 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
169 &self.substitution.at(interner, 0).assert_ty_ref(interner) 153 &self.substitution.at(interner, 0).assert_ty_ref(interner)
@@ -225,7 +209,8 @@ impl CallableSig {
225 params_and_return: fn_ptr 209 params_and_return: fn_ptr
226 .substs 210 .substs
227 .clone() 211 .clone()
228 .shift_bound_vars_out(DebruijnIndex::ONE) 212 .shifted_out_to(DebruijnIndex::ONE)
213 .expect("unexpected lifetime vars in fn ptr")
229 .interned() 214 .interned()
230 .iter() 215 .iter()
231 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 216 .map(|arg| arg.assert_ty_ref(&Interner).clone())
@@ -334,12 +319,12 @@ impl Ty {
334 /// If this is a `dyn Trait` type, this returns the `Trait` part. 319 /// If this is a `dyn Trait` type, this returns the `Trait` part.
335 fn dyn_trait_ref(&self) -> Option<&TraitRef> { 320 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
336 match self.kind(&Interner) { 321 match self.kind(&Interner) {
337 TyKind::Dyn(dyn_ty) => { 322 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() { 323 match b.skip_binders() {
339 WhereClause::Implemented(trait_ref) => Some(trait_ref), 324 WhereClause::Implemented(trait_ref) => Some(trait_ref),
340 _ => None, 325 _ => None,
341 }) 326 }
342 } 327 }),
343 _ => None, 328 _ => None,
344 } 329 }
345 } 330 }
@@ -378,7 +363,7 @@ impl Ty {
378 TyKind::FnDef(def, parameters) => { 363 TyKind::FnDef(def, parameters) => {
379 let callable_def = db.lookup_intern_callable_def((*def).into()); 364 let callable_def = db.lookup_intern_callable_def((*def).into());
380 let sig = db.callable_item_signature(callable_def); 365 let sig = db.callable_item_signature(callable_def);
381 Some(sig.subst(&parameters)) 366 Some(sig.substitute(&Interner, &parameters))
382 } 367 }
383 TyKind::Closure(.., substs) => { 368 TyKind::Closure(.., substs) => {
384 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner); 369 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
@@ -429,8 +414,8 @@ impl Ty {
429 // This is only used by type walking. 414 // This is only used by type walking.
430 // Parameters will be walked outside, and projection predicate is not used. 415 // Parameters will be walked outside, and projection predicate is not used.
431 // So just provide the Future trait. 416 // So just provide the Future trait.
432 let impl_bound = Binders::new( 417 let impl_bound = Binders::empty(
433 0, 418 &Interner,
434 WhereClause::Implemented(TraitRef { 419 WhereClause::Implemented(TraitRef {
435 trait_id: to_chalk_trait_id(future_trait), 420 trait_id: to_chalk_trait_id(future_trait),
436 substitution: Substitution::empty(&Interner), 421 substitution: Substitution::empty(&Interner),
@@ -452,14 +437,14 @@ impl Ty {
452 let data = (*it) 437 let data = (*it)
453 .as_ref() 438 .as_ref()
454 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 439 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
455 data.subst(&opaque_ty.substitution) 440 data.substitute(&Interner, &opaque_ty.substitution)
456 }) 441 })
457 } 442 }
458 // It always has an parameter for Future::Output type. 443 // It always has an parameter for Future::Output type.
459 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(), 444 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
460 }; 445 };
461 446
462 predicates.map(|it| it.value) 447 predicates.map(|it| it.into_value_and_skipped_binders().0)
463 } 448 }
464 TyKind::Placeholder(idx) => { 449 TyKind::Placeholder(idx) => {
465 let id = from_placeholder_idx(db, *idx); 450 let id = from_placeholder_idx(db, *idx);
@@ -471,7 +456,7 @@ impl Ty {
471 let predicates = db 456 let predicates = db
472 .generic_predicates(id.parent) 457 .generic_predicates(id.parent)
473 .into_iter() 458 .into_iter()
474 .map(|pred| pred.clone().subst(&substs)) 459 .map(|pred| pred.clone().substitute(&Interner, &substs))
475 .filter(|wc| match &wc.skip_binders() { 460 .filter(|wc| match &wc.skip_binders() {
476 WhereClause::Implemented(tr) => { 461 WhereClause::Implemented(tr) => {
477 tr.self_type_parameter(&Interner) == self 462 tr.self_type_parameter(&Interner) == self
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index e9e4e69ad..48c26f471 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -31,7 +31,7 @@ use crate::{
31 traits::chalk::{Interner, ToChalk}, 31 traits::chalk::{Interner, ToChalk},
32 utils::{ 32 utils::{
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, Generics,
35 }, 35 },
36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, 37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
@@ -196,7 +196,7 @@ impl<'a> TyLoweringContext<'a> {
196 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), 196 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)),
197 ) 197 )
198 }); 198 });
199 let bounds = Binders::new(1, bounds); 199 let bounds = crate::make_only_type_binders(1, bounds);
200 TyKind::Dyn(DynTy { bounds }).intern(&Interner) 200 TyKind::Dyn(DynTy { bounds }).intern(&Interner)
201 } 201 }
202 TypeRef::ImplTrait(bounds) => { 202 TypeRef::ImplTrait(bounds) => {
@@ -209,9 +209,9 @@ impl<'a> TyLoweringContext<'a> {
209 // this dance is to make sure the data is in the right 209 // this dance is to make sure the data is in the right
210 // place even if we encounter more opaque types while 210 // place even if we encounter more opaque types while
211 // lowering the bounds 211 // lowering the bounds
212 self.opaque_type_data 212 self.opaque_type_data.borrow_mut().push(ReturnTypeImplTrait {
213 .borrow_mut() 213 bounds: crate::make_only_type_binders(1, Vec::new()),
214 .push(ReturnTypeImplTrait { bounds: Binders::new(1, Vec::new()) }); 214 });
215 // We don't want to lower the bounds inside the binders 215 // We don't want to lower the bounds inside the binders
216 // we're currently in, because they don't end up inside 216 // we're currently in, because they don't end up inside
217 // those binders. E.g. when we have `impl Trait<impl 217 // those binders. E.g. when we have `impl Trait<impl
@@ -380,7 +380,7 @@ impl<'a> TyLoweringContext<'a> {
380 TyKind::Error.intern(&Interner) 380 TyKind::Error.intern(&Interner)
381 } else { 381 } else {
382 let dyn_ty = DynTy { 382 let dyn_ty = DynTy {
383 bounds: Binders::new( 383 bounds: crate::make_only_type_binders(
384 1, 384 1,
385 QuantifiedWhereClauses::from_iter( 385 QuantifiedWhereClauses::from_iter(
386 &Interner, 386 &Interner,
@@ -414,7 +414,7 @@ impl<'a> TyLoweringContext<'a> {
414 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), 414 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db),
415 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), 415 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders),
416 }; 416 };
417 self.db.impl_self_ty(impl_id).subst(&substs) 417 self.db.impl_self_ty(impl_id).substitute(&Interner, &substs)
418 } 418 }
419 TypeNs::AdtSelfType(adt) => { 419 TypeNs::AdtSelfType(adt) => {
420 let generics = generics(self.db.upcast(), adt.into()); 420 let generics = generics(self.db.upcast(), adt.into());
@@ -422,7 +422,7 @@ impl<'a> TyLoweringContext<'a> {
422 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), 422 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db),
423 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), 423 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders),
424 }; 424 };
425 self.db.ty(adt.into()).subst(&substs) 425 self.db.ty(adt.into()).substitute(&Interner, &substs)
426 } 426 }
427 427
428 TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args), 428 TypeNs::AdtId(it) => self.lower_path_inner(resolved_segment, it.into(), infer_args),
@@ -477,13 +477,13 @@ impl<'a> TyLoweringContext<'a> {
477 ), 477 ),
478 ); 478 );
479 let s = generics.type_params_subst(self.db); 479 let s = generics.type_params_subst(self.db);
480 t.substitution.clone().subst_bound_vars(&s) 480 s.apply(t.substitution.clone(), &Interner)
481 } 481 }
482 TypeParamLoweringMode::Variable => t.substitution.clone(), 482 TypeParamLoweringMode::Variable => t.substitution.clone(),
483 }; 483 };
484 // We need to shift in the bound vars, since 484 // We need to shift in the bound vars, since
485 // associated_type_shorthand_candidates does not do that 485 // associated_type_shorthand_candidates does not do that
486 let substs = substs.shift_bound_vars(self.in_binders); 486 let substs = substs.shifted_in_from(self.in_binders);
487 // FIXME handle type parameters on the segment 487 // FIXME handle type parameters on the segment
488 return Some( 488 return Some(
489 TyKind::Alias(AliasTy::Projection(ProjectionTy { 489 TyKind::Alias(AliasTy::Projection(ProjectionTy {
@@ -516,7 +516,7 @@ impl<'a> TyLoweringContext<'a> {
516 TyDefId::TypeAliasId(it) => Some(it.into()), 516 TyDefId::TypeAliasId(it) => Some(it.into()),
517 }; 517 };
518 let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None); 518 let substs = self.substs_from_path_segment(segment, generic_def, infer_args, None);
519 self.db.ty(typeable).subst(&substs) 519 self.db.ty(typeable).substitute(&Interner, &substs)
520 } 520 }
521 521
522 /// Collect generic arguments from a path into a `Substs`. See also 522 /// Collect generic arguments from a path into a `Substs`. See also
@@ -620,7 +620,7 @@ impl<'a> TyLoweringContext<'a> {
620 for default_ty in defaults.iter().skip(substs.len()) { 620 for default_ty in defaults.iter().skip(substs.len()) {
621 // each default can depend on the previous parameters 621 // each default can depend on the previous parameters
622 let substs_so_far = Substitution::from_iter(&Interner, substs.clone()); 622 let substs_so_far = Substitution::from_iter(&Interner, substs.clone());
623 substs.push(default_ty.clone().subst(&substs_so_far)); 623 substs.push(default_ty.clone().substitute(&Interner, &substs_so_far));
624 } 624 }
625 } 625 }
626 } 626 }
@@ -787,7 +787,7 @@ impl<'a> TyLoweringContext<'a> {
787 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { 787 let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
788 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect() 788 bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect()
789 }); 789 });
790 ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } 790 ReturnTypeImplTrait { bounds: crate::make_only_type_binders(1, predicates) }
791 } 791 }
792} 792}
793 793
@@ -831,17 +831,20 @@ pub fn associated_type_shorthand_candidates<R>(
831 }; 831 };
832 832
833 match res { 833 match res {
834 // FIXME: how to correctly handle higher-ranked bounds here? 834 TypeNs::SelfType(impl_id) => search(
835 TypeNs::SelfType(impl_id) => { 835 // we're _in_ the impl -- the binders get added back later. Correct,
836 search(db.impl_trait(impl_id)?.value.shift_bound_vars_out(DebruijnIndex::ONE)) 836 // but it would be nice to make this more explicit
837 } 837 db.impl_trait(impl_id)?.into_value_and_skipped_binders().0,
838 ),
838 TypeNs::GenericParam(param_id) => { 839 TypeNs::GenericParam(param_id) => {
839 let predicates = db.generic_predicates_for_param(param_id); 840 let predicates = db.generic_predicates_for_param(param_id);
840 let res = predicates.iter().find_map(|pred| match &pred.value.value { 841 let res = predicates.iter().find_map(|pred| match pred.skip_binders().skip_binders() {
841 // FIXME: how to correctly handle higher-ranked bounds here? 842 // FIXME: how to correctly handle higher-ranked bounds here?
842 WhereClause::Implemented(tr) => { 843 WhereClause::Implemented(tr) => search(
843 search(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 844 tr.clone()
844 } 845 .shifted_out_to(DebruijnIndex::ONE)
846 .expect("FIXME unexpected higher-ranked trait bound"),
847 ),
845 _ => None, 848 _ => None,
846 }); 849 });
847 if let res @ Some(_) = res { 850 if let res @ Some(_) = res {
@@ -881,7 +884,7 @@ pub(crate) fn field_types_query(
881 let ctx = 884 let ctx =
882 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 885 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
883 for (field_id, field_data) in var_data.fields().iter() { 886 for (field_id, field_data) in var_data.fields().iter() {
884 res.insert(field_id, Binders::new(generics.len(), ctx.lower_ty(&field_data.type_ref))) 887 res.insert(field_id, make_binders(&generics, ctx.lower_ty(&field_data.type_ref)))
885 } 888 }
886 Arc::new(res) 889 Arc::new(res)
887} 890}
@@ -915,9 +918,7 @@ pub(crate) fn generic_predicates_for_param_query(
915 }, 918 },
916 WherePredicate::Lifetime { .. } => false, 919 WherePredicate::Lifetime { .. } => false,
917 }) 920 })
918 .flat_map(|pred| { 921 .flat_map(|pred| ctx.lower_where_predicate(pred, true).map(|p| make_binders(&generics, p)))
919 ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p))
920 })
921 .collect() 922 .collect()
922} 923}
923 924
@@ -988,9 +989,7 @@ pub(crate) fn generic_predicates_query(
988 let generics = generics(db.upcast(), def); 989 let generics = generics(db.upcast(), def);
989 resolver 990 resolver
990 .where_predicates_in_scope() 991 .where_predicates_in_scope()
991 .flat_map(|pred| { 992 .flat_map(|pred| ctx.lower_where_predicate(pred, false).map(|p| make_binders(&generics, p)))
992 ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p))
993 })
994 .collect() 993 .collect()
995} 994}
996 995
@@ -1012,22 +1011,24 @@ pub(crate) fn generic_defaults_query(
1012 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t)); 1011 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t));
1013 1012
1014 // Each default can only refer to previous parameters. 1013 // Each default can only refer to previous parameters.
1015 ty.walk_mut_binders( 1014 ty = ty.fold_binders(
1016 &mut |ty, binders| match ty.interned_mut() { 1015 &mut |ty, binders| match ty.kind(&Interner) {
1017 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 1016 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => {
1018 if *index >= idx { 1017 if *index >= idx {
1019 // type variable default referring to parameter coming 1018 // type variable default referring to parameter coming
1020 // after it. This is forbidden (FIXME: report 1019 // after it. This is forbidden (FIXME: report
1021 // diagnostic) 1020 // diagnostic)
1022 *ty = TyKind::Error.intern(&Interner); 1021 TyKind::Error.intern(&Interner)
1022 } else {
1023 ty
1023 } 1024 }
1024 } 1025 }
1025 _ => {} 1026 _ => ty,
1026 }, 1027 },
1027 DebruijnIndex::INNERMOST, 1028 DebruijnIndex::INNERMOST,
1028 ); 1029 );
1029 1030
1030 Binders::new(idx, ty) 1031 crate::make_only_type_binders(idx, ty)
1031 }) 1032 })
1032 .collect(); 1033 .collect();
1033 1034
@@ -1040,14 +1041,13 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1040 let ctx_params = TyLoweringContext::new(db, &resolver) 1041 let ctx_params = TyLoweringContext::new(db, &resolver)
1041 .with_impl_trait_mode(ImplTraitLoweringMode::Variable) 1042 .with_impl_trait_mode(ImplTraitLoweringMode::Variable)
1042 .with_type_param_mode(TypeParamLoweringMode::Variable); 1043 .with_type_param_mode(TypeParamLoweringMode::Variable);
1043 let params = data.params.iter().map(|tr| (&ctx_params).lower_ty(tr)).collect::<Vec<_>>(); 1044 let params = data.params.iter().map(|tr| ctx_params.lower_ty(tr)).collect::<Vec<_>>();
1044 let ctx_ret = TyLoweringContext::new(db, &resolver) 1045 let ctx_ret = TyLoweringContext::new(db, &resolver)
1045 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque) 1046 .with_impl_trait_mode(ImplTraitLoweringMode::Opaque)
1046 .with_type_param_mode(TypeParamLoweringMode::Variable); 1047 .with_type_param_mode(TypeParamLoweringMode::Variable);
1047 let ret = (&ctx_ret).lower_ty(&data.ret_type); 1048 let ret = ctx_ret.lower_ty(&data.ret_type);
1048 let generics = generics(db.upcast(), def.into()); 1049 let generics = generics(db.upcast(), def.into());
1049 let num_binders = generics.len(); 1050 make_binders(&generics, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
1050 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
1051} 1051}
1052 1052
1053/// Build the declared type of a function. This should not need to look at the 1053/// Build the declared type of a function. This should not need to look at the
@@ -1055,8 +1055,8 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1055fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 1055fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1056 let generics = generics(db.upcast(), def.into()); 1056 let generics = generics(db.upcast(), def.into());
1057 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); 1057 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1058 Binders::new( 1058 make_binders(
1059 substs.len(&Interner), 1059 &generics,
1060 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), 1060 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner),
1061 ) 1061 )
1062} 1062}
@@ -1069,7 +1069,7 @@ fn type_for_const(db: &dyn HirDatabase, def: ConstId) -> Binders<Ty> {
1069 let ctx = 1069 let ctx =
1070 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1070 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1071 1071
1072 Binders::new(generics.len(), ctx.lower_ty(&data.type_ref)) 1072 make_binders(&generics, ctx.lower_ty(&data.type_ref))
1073} 1073}
1074 1074
1075/// Build the declared type of a static. 1075/// Build the declared type of a static.
@@ -1078,7 +1078,7 @@ fn type_for_static(db: &dyn HirDatabase, def: StaticId) -> Binders<Ty> {
1078 let resolver = def.resolver(db.upcast()); 1078 let resolver = def.resolver(db.upcast());
1079 let ctx = TyLoweringContext::new(db, &resolver); 1079 let ctx = TyLoweringContext::new(db, &resolver);
1080 1080
1081 Binders::new(0, ctx.lower_ty(&data.type_ref)) 1081 Binders::empty(&Interner, ctx.lower_ty(&data.type_ref))
1082} 1082}
1083 1083
1084fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig { 1084fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnSig {
@@ -1088,8 +1088,8 @@ fn fn_sig_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> PolyFnS
1088 let ctx = 1088 let ctx =
1089 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1089 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<_>>(); 1090 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1091 let ret = type_for_adt(db, def.into()); 1091 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)) 1092 Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1093} 1093}
1094 1094
1095/// Build the type of a tuple struct constructor. 1095/// Build the type of a tuple struct constructor.
@@ -1100,8 +1100,8 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
1100 } 1100 }
1101 let generics = generics(db.upcast(), def.into()); 1101 let generics = generics(db.upcast(), def.into());
1102 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); 1102 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1103 Binders::new( 1103 make_binders(
1104 substs.len(&Interner), 1104 &generics,
1105 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner), 1105 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner),
1106 ) 1106 )
1107} 1107}
@@ -1114,8 +1114,8 @@ fn fn_sig_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId)
1114 let ctx = 1114 let ctx =
1115 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1115 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<_>>(); 1116 let params = fields.iter().map(|(_, field)| ctx.lower_ty(&field.type_ref)).collect::<Vec<_>>();
1117 let ret = type_for_adt(db, def.parent.into()); 1117 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)) 1118 Binders::new(binders, CallableSig::from_params_and_return(params, ret, false))
1119} 1119}
1120 1120
1121/// Build the type of a tuple enum variant constructor. 1121/// Build the type of a tuple enum variant constructor.
@@ -1127,17 +1127,17 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1127 } 1127 }
1128 let generics = generics(db.upcast(), def.parent.into()); 1128 let generics = generics(db.upcast(), def.parent.into());
1129 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); 1129 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1130 Binders::new( 1130 make_binders(
1131 substs.len(&Interner), 1131 &generics,
1132 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner), 1132 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner),
1133 ) 1133 )
1134} 1134}
1135 1135
1136fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 1136fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1137 let generics = generics(db.upcast(), adt.into());
1137 let b = TyBuilder::adt(db, adt); 1138 let b = TyBuilder::adt(db, adt);
1138 let num_binders = b.remaining();
1139 let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); 1139 let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
1140 Binders::new(num_binders, ty) 1140 make_binders(&generics, ty)
1141} 1141}
1142 1142
1143fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { 1143fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
@@ -1146,11 +1146,11 @@ fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
1146 let ctx = 1146 let ctx =
1147 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1147 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1148 if db.type_alias_data(t).is_extern { 1148 if db.type_alias_data(t).is_extern {
1149 Binders::new(0, TyKind::Foreign(crate::to_foreign_def_id(t)).intern(&Interner)) 1149 Binders::empty(&Interner, TyKind::Foreign(crate::to_foreign_def_id(t)).intern(&Interner))
1150 } else { 1150 } else {
1151 let type_ref = &db.type_alias_data(t).type_ref; 1151 let type_ref = &db.type_alias_data(t).type_ref;
1152 let inner = ctx.lower_ty(type_ref.as_deref().unwrap_or(&TypeRef::Error)); 1152 let inner = ctx.lower_ty(type_ref.as_deref().unwrap_or(&TypeRef::Error));
1153 Binders::new(generics.len(), inner) 1153 make_binders(&generics, inner)
1154 } 1154 }
1155} 1155}
1156 1156
@@ -1209,19 +1209,21 @@ impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for V
1209/// namespace. 1209/// namespace.
1210pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> { 1210pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
1211 match def { 1211 match def {
1212 TyDefId::BuiltinType(it) => Binders::new(0, TyBuilder::builtin(it)), 1212 TyDefId::BuiltinType(it) => Binders::empty(&Interner, TyBuilder::builtin(it)),
1213 TyDefId::AdtId(it) => type_for_adt(db, it), 1213 TyDefId::AdtId(it) => type_for_adt(db, it),
1214 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), 1214 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
1215 } 1215 }
1216} 1216}
1217 1217
1218pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders<Ty> { 1218pub(crate) fn ty_recover(db: &dyn HirDatabase, _cycle: &[String], def: &TyDefId) -> Binders<Ty> {
1219 let num_binders = match *def { 1219 let generics = match *def {
1220 TyDefId::BuiltinType(_) => 0, 1220 TyDefId::BuiltinType(_) => {
1221 TyDefId::AdtId(it) => generics(db.upcast(), it.into()).len(), 1221 return Binders::empty(&Interner, TyKind::Error.intern(&Interner))
1222 TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()).len(), 1222 }
1223 TyDefId::AdtId(it) => generics(db.upcast(), it.into()),
1224 TyDefId::TypeAliasId(it) => generics(db.upcast(), it.into()),
1223 }; 1225 };
1224 Binders::new(num_binders, TyKind::Error.intern(&Interner)) 1226 make_binders(&generics, TyKind::Error.intern(&Interner))
1225} 1227}
1226 1228
1227pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> { 1229pub(crate) fn value_ty_query(db: &dyn HirDatabase, def: ValueTyDefId) -> Binders<Ty> {
@@ -1241,7 +1243,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde
1241 let generics = generics(db.upcast(), impl_id.into()); 1243 let generics = generics(db.upcast(), impl_id.into());
1242 let ctx = 1244 let ctx =
1243 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1245 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1244 Binders::new(generics.len(), ctx.lower_ty(&impl_data.self_ty)) 1246 make_binders(&generics, ctx.lower_ty(&impl_data.self_ty))
1245} 1247}
1246 1248
1247pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { 1249pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty {
@@ -1259,7 +1261,7 @@ pub(crate) fn impl_self_ty_recover(
1259 impl_id: &ImplId, 1261 impl_id: &ImplId,
1260) -> Binders<Ty> { 1262) -> Binders<Ty> {
1261 let generics = generics(db.upcast(), (*impl_id).into()); 1263 let generics = generics(db.upcast(), (*impl_id).into());
1262 Binders::new(generics.len(), TyKind::Error.intern(&Interner)) 1264 make_binders(&generics, TyKind::Error.intern(&Interner))
1263} 1265}
1264 1266
1265pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> { 1267pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<Binders<TraitRef>> {
@@ -1267,9 +1269,9 @@ pub(crate) fn impl_trait_query(db: &dyn HirDatabase, impl_id: ImplId) -> Option<
1267 let resolver = impl_id.resolver(db.upcast()); 1269 let resolver = impl_id.resolver(db.upcast());
1268 let ctx = 1270 let ctx =
1269 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); 1271 TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable);
1270 let self_ty = db.impl_self_ty(impl_id); 1272 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()?; 1273 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))?)) 1274 Some(Binders::new(binders, ctx.lower_trait_ref(target_trait, Some(self_ty))?))
1273} 1275}
1274 1276
1275pub(crate) fn return_type_impl_traits( 1277pub(crate) fn return_type_impl_traits(
@@ -1284,13 +1286,12 @@ pub(crate) fn return_type_impl_traits(
1284 .with_type_param_mode(TypeParamLoweringMode::Variable); 1286 .with_type_param_mode(TypeParamLoweringMode::Variable);
1285 let _ret = (&ctx_ret).lower_ty(&data.ret_type); 1287 let _ret = (&ctx_ret).lower_ty(&data.ret_type);
1286 let generics = generics(db.upcast(), def.into()); 1288 let generics = generics(db.upcast(), def.into());
1287 let num_binders = generics.len();
1288 let return_type_impl_traits = 1289 let return_type_impl_traits =
1289 ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() }; 1290 ReturnTypeImplTraits { impl_traits: ctx_ret.opaque_type_data.into_inner() };
1290 if return_type_impl_traits.impl_traits.is_empty() { 1291 if return_type_impl_traits.impl_traits.is_empty() {
1291 None 1292 None
1292 } else { 1293 } else {
1293 Some(Arc::new(Binders::new(num_binders, return_type_impl_traits))) 1294 Some(Arc::new(make_binders(&generics, return_type_impl_traits)))
1294 } 1295 }
1295} 1296}
1296 1297
@@ -1300,3 +1301,7 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
1300 hir_def::type_ref::Mutability::Mut => Mutability::Mut, 1301 hir_def::type_ref::Mutability::Mut => Mutability::Mut,
1301 } 1302 }
1302} 1303}
1304
1305fn make_binders<T>(generics: &Generics, value: T) -> Binders<T> {
1306 crate::make_only_type_binders(generics.len(), value)
1307}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 6ace970d1..19a1fa793 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 }
@@ -712,7 +712,7 @@ pub(crate) fn inherent_impl_substs(
712 let vars = TyBuilder::subst_for_def(db, impl_id) 712 let vars = TyBuilder::subst_for_def(db, impl_id)
713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) 713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner))
714 .build(); 714 .build();
715 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 715 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars);
716 let mut kinds = self_ty.binders.interned().to_vec(); 716 let mut kinds = self_ty.binders.interned().to_vec();
717 kinds.extend( 717 kinds.extend(
718 iter::repeat(chalk_ir::WithKind::new( 718 iter::repeat(chalk_ir::WithKind::new(
@@ -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()).substitute(&Interner, &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..dff87ef70 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -184,16 +184,21 @@ 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 (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
188 let data = &datas.impl_traits[idx as usize];
188 let bound = OpaqueTyDatumBound { 189 let bound = OpaqueTyDatumBound {
189 bounds: make_binders( 190 bounds: make_binders(
190 data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(), 191 data.bounds
192 .skip_binders()
193 .iter()
194 .cloned()
195 .map(|b| b.to_chalk(self.db))
196 .collect(),
191 1, 197 1,
192 ), 198 ),
193 where_clauses: make_binders(vec![], 0), 199 where_clauses: make_binders(vec![], 0),
194 }; 200 };
195 let num_vars = datas.num_binders; 201 chalk_ir::Binders::new(binders, bound)
196 make_binders(bound, num_vars)
197 } 202 }
198 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { 203 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
199 if let Some((future_trait, future_output)) = self 204 if let Some((future_trait, future_output)) = self
@@ -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: chalk_ir::Binders::new(binders, value_bound),
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: chalk_ir::Binders::new(binders, bound),
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..c3b148cab 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: chalk_ir::Binders::new(binders, where_clauses),
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)
@@ -148,7 +149,7 @@ impl ToChalk for Ty {
148 .map(|c| from_chalk(db, c.clone())); 149 .map(|c| from_chalk(db, c.clone()));
149 TyKind::Dyn(crate::DynTy { 150 TyKind::Dyn(crate::DynTy {
150 bounds: crate::Binders::new( 151 bounds: crate::Binders::new(
151 1, 152 where_clauses.bounds.binders.clone(),
152 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), 153 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds),
153 ), 154 ),
154 }) 155 })
@@ -486,19 +487,13 @@ 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> {
489 chalk_ir::Binders::new( 490 let (value, binders) = self.into_value_and_skipped_binders();
490 chalk_ir::VariableKinds::from_iter( 491 chalk_ir::Binders::new(binders, value.to_chalk(db))
491 &Interner,
492 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
493 .take(self.num_binders),
494 ),
495 self.value.to_chalk(db),
496 )
497 } 492 }
498 493
499 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { 494 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
500 let (v, b) = binders.into_value_and_skipped_binders(); 495 let (v, b) = binders.into_value_and_skipped_binders();
501 crate::Binders::new(b.len(&Interner), from_chalk(db, v)) 496 crate::Binders::new(b, from_chalk(db, v))
502 } 497 }
503} 498}
504 499
@@ -524,7 +519,7 @@ pub(super) fn convert_where_clauses(
524 let generic_predicates = db.generic_predicates(def); 519 let generic_predicates = db.generic_predicates(def);
525 let mut result = Vec::with_capacity(generic_predicates.len()); 520 let mut result = Vec::with_capacity(generic_predicates.len());
526 for pred in generic_predicates.iter() { 521 for pred in generic_predicates.iter() {
527 result.push(pred.clone().subst(substs).to_chalk(db)); 522 result.push(pred.clone().substitute(&Interner, substs).to_chalk(db));
528 } 523 }
529 result 524 result
530} 525}
@@ -536,8 +531,9 @@ pub(super) fn generic_predicate_to_inline_bound(
536) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { 531) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
537 // An InlineBound is like a GenericPredicate, except the self type is left out. 532 // 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. 533 // 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); 534 let self_ty_shifted_in = self_ty.clone().shifted_in_from(DebruijnIndex::ONE);
540 match &pred.value { 535 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
536 match pred {
541 WhereClause::Implemented(trait_ref) => { 537 WhereClause::Implemented(trait_ref) => {
542 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in { 538 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in {
543 // we can only convert predicates back to type bounds if they 539 // we can only convert predicates back to type bounds if they
@@ -549,7 +545,7 @@ pub(super) fn generic_predicate_to_inline_bound(
549 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 545 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
550 .collect(); 546 .collect();
551 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; 547 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)) 548 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
553 } 549 }
554 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 550 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
555 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in { 551 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in {
@@ -566,7 +562,10 @@ pub(super) fn generic_predicate_to_inline_bound(
566 associated_ty_id: projection_ty.associated_ty_id, 562 associated_ty_id: projection_ty.associated_ty_id,
567 parameters: Vec::new(), // FIXME we don't support generic associated types yet 563 parameters: Vec::new(), // FIXME we don't support generic associated types yet
568 }; 564 };
569 Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) 565 Some(chalk_ir::Binders::new(
566 binders,
567 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
568 ))
570 } 569 }
571 _ => None, 570 _ => None,
572 } 571 }
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index bac086318..46c705a76 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -12,7 +12,7 @@ use smallvec::SmallVec;
12 12
13use crate::{ 13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId, 14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, 15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKinds,
16}; 16};
17 17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)] 18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
@@ -286,7 +286,11 @@ impl Substitution {
286 Substitution(elements.into_iter().casted(interner).collect()) 286 Substitution(elements.into_iter().casted(interner).collect())
287 } 287 }
288 288
289 // We can hopefully add this to Chalk 289 pub fn apply<T: TypeWalk>(&self, value: T, _interner: &Interner) -> T {
290 value.subst_bound_vars(self)
291 }
292
293 // Temporary helper functions, to be removed
290 pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution { 294 pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution {
291 Substitution(interned) 295 Substitution(interned)
292 } 296 }
@@ -296,10 +300,65 @@ impl Substitution {
296 } 300 }
297} 301}
298 302
299#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 303#[derive(Clone, PartialEq, Eq, Hash)]
300pub struct Binders<T> { 304pub struct Binders<T> {
301 pub num_binders: usize, 305 /// The binders that quantify over the value.
302 pub value: T, 306 pub binders: VariableKinds,
307 value: T,
308}
309
310impl<T> Binders<T> {
311 pub fn new(binders: VariableKinds, value: T) -> Self {
312 Self { binders, value }
313 }
314
315 pub fn empty(_interner: &Interner, value: T) -> Self {
316 crate::make_only_type_binders(0, value)
317 }
318
319 pub fn as_ref(&self) -> Binders<&T> {
320 Binders { binders: self.binders.clone(), value: &self.value }
321 }
322
323 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
324 Binders { binders: self.binders, value: f(self.value) }
325 }
326
327 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
328 Some(Binders { binders: self.binders, value: f(self.value)? })
329 }
330
331 pub fn skip_binders(&self) -> &T {
332 &self.value
333 }
334
335 pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds) {
336 (self.value, self.binders)
337 }
338
339 /// Returns the number of binders.
340 pub fn len(&self, interner: &Interner) -> usize {
341 self.binders.len(interner)
342 }
343
344 // Temporary helper function, to be removed
345 pub fn skip_binders_mut(&mut self) -> &mut T {
346 &mut self.value
347 }
348}
349
350impl<T: Clone> Binders<&T> {
351 pub fn cloned(&self) -> Binders<T> {
352 Binders::new(self.binders.clone(), self.value.clone())
353 }
354}
355
356impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> {
357 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
358 let Binders { ref binders, ref value } = *self;
359 write!(fmt, "for{:?} ", binders.inner_debug(&Interner))?;
360 std::fmt::Debug::fmt(value, fmt)
361 }
303} 362}
304 363
305/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. 364/// 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/utils.rs b/crates/hir_ty/src/utils.rs
index df0ea4368..d11708299 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -66,13 +66,15 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
66 .filter_map(|pred| { 66 .filter_map(|pred| {
67 pred.as_ref().filter_map(|pred| match pred.skip_binders() { 67 pred.as_ref().filter_map(|pred| match pred.skip_binders() {
68 // FIXME: how to correctly handle higher-ranked bounds here? 68 // FIXME: how to correctly handle higher-ranked bounds here?
69 WhereClause::Implemented(tr) => { 69 WhereClause::Implemented(tr) => Some(
70 Some(tr.clone().shift_bound_vars_out(DebruijnIndex::ONE)) 70 tr.clone()
71 } 71 .shifted_out_to(DebruijnIndex::ONE)
72 .expect("FIXME unexpected higher-ranked trait bound"),
73 ),
72 _ => None, 74 _ => None,
73 }) 75 })
74 }) 76 })
75 .map(|pred| pred.subst(&trait_ref.substitution)) 77 .map(|pred| pred.substitute(&Interner, &trait_ref.substitution))
76 .collect() 78 .collect()
77} 79}
78 80
@@ -103,6 +105,8 @@ pub(super) fn all_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<Tra
103/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get 105/// we have `Self: Trait<u32, i32>` and `Trait<T, U>: OtherTrait<U>` we'll get
104/// `Self: OtherTrait<i32>`. 106/// `Self: OtherTrait<i32>`.
105pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> { 107pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> Vec<TraitRef> {
108 // FIXME: replace by Chalk's `super_traits`, maybe make this a query
109
106 // we need to take care a bit here to avoid infinite loops in case of cycles 110 // we need to take care a bit here to avoid infinite loops in case of cycles
107 // (i.e. if we have `trait A: B; trait B: A;`) 111 // (i.e. if we have `trait A: B; trait B: A;`)
108 let mut result = vec![trait_ref]; 112 let mut result = vec![trait_ref];
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
index 5dfd59746..b85e6ab4d 100644
--- a/crates/hir_ty/src/walk.rs
+++ b/crates/hir_ty/src/walk.rs
@@ -82,7 +82,7 @@ pub trait TypeWalk {
82 *ty = substs.interned()[bound.index] 82 *ty = substs.interned()[bound.index]
83 .assert_ty_ref(&Interner) 83 .assert_ty_ref(&Interner)
84 .clone() 84 .clone()
85 .shift_bound_vars(binders); 85 .shifted_in_from(binders);
86 } 86 }
87 } 87 }
88 }, 88 },
@@ -92,7 +92,7 @@ pub trait TypeWalk {
92 } 92 }
93 93
94 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. 94 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
95 fn shift_bound_vars(self, n: DebruijnIndex) -> Self 95 fn shifted_in_from(self, n: DebruijnIndex) -> Self
96 where 96 where
97 Self: Sized, 97 Self: Sized,
98 { 98 {
@@ -108,20 +108,22 @@ pub trait TypeWalk {
108 } 108 }
109 109
110 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. 110 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
111 fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self 111 fn shifted_out_to(self, n: DebruijnIndex) -> Option<Self>
112 where 112 where
113 Self: Sized + std::fmt::Debug, 113 Self: Sized + std::fmt::Debug,
114 { 114 {
115 self.fold_binders( 115 Some(self.fold_binders(
116 &mut |ty, binders| match ty.kind(&Interner) { 116 &mut |ty, binders| {
117 TyKind::BoundVar(bound) if bound.debruijn >= binders => { 117 match ty.kind(&Interner) {
118 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) 118 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
119 .intern(&Interner) 119 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
120 .intern(&Interner)
121 }
122 _ => ty,
120 } 123 }
121 _ => ty,
122 }, 124 },
123 DebruijnIndex::INNERMOST, 125 DebruijnIndex::INNERMOST,
124 ) 126 ))
125 } 127 }
126} 128}
127 129
@@ -139,7 +141,7 @@ impl TypeWalk for Ty {
139 } 141 }
140 } 142 }
141 TyKind::Dyn(dyn_ty) => { 143 TyKind::Dyn(dyn_ty) => {
142 for p in dyn_ty.bounds.value.interned().iter() { 144 for p in dyn_ty.bounds.skip_binders().interned().iter() {
143 p.walk(f); 145 p.walk(f);
144 } 146 }
145 } 147 }
@@ -167,7 +169,7 @@ impl TypeWalk for Ty {
167 p_ty.substitution.walk_mut_binders(f, binders); 169 p_ty.substitution.walk_mut_binders(f, binders);
168 } 170 }
169 TyKind::Dyn(dyn_ty) => { 171 TyKind::Dyn(dyn_ty) => {
170 for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { 172 for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) {
171 p.walk_mut_binders(f, binders.shifted_in()); 173 p.walk_mut_binders(f, binders.shifted_in());
172 } 174 }
173 } 175 }
@@ -294,7 +296,7 @@ impl TypeWalk for Substitution {
294 296
295impl<T: TypeWalk> TypeWalk for Binders<T> { 297impl<T: TypeWalk> TypeWalk for Binders<T> {
296 fn walk(&self, f: &mut impl FnMut(&Ty)) { 298 fn walk(&self, f: &mut impl FnMut(&Ty)) {
297 self.value.walk(f); 299 self.skip_binders().walk(f);
298 } 300 }
299 301
300 fn walk_mut_binders( 302 fn walk_mut_binders(
@@ -302,7 +304,7 @@ impl<T: TypeWalk> TypeWalk for Binders<T> {
302 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 304 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
303 binders: DebruijnIndex, 305 binders: DebruijnIndex,
304 ) { 306 ) {
305 self.value.walk_mut_binders(f, binders.shifted_in()) 307 self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in())
306 } 308 }
307} 309}
308 310