aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-04-05 20:59:25 +0100
committerGitHub <[email protected]>2021-04-05 20:59:25 +0100
commitf25c1e7c6a119a1035ba226f0735a0d6667a5db8 (patch)
tree0f666c5b917de8a0f2ebf5fba185500d153036f3
parent8c96a7d81e29061537d78b5670a3474cb136422d (diff)
parentb67148daea86d85d211c4243f22635d6ac7e1983 (diff)
Merge #8356
8356: Align more methods to Chalk r=flodiebold a=flodiebold Related to #8313. Move some inherent methods that don't exist in Chalk to an extension trait, remove some others. Co-authored-by: Florian Diebold <[email protected]>
-rw-r--r--crates/hir/src/lib.rs3
-rw-r--r--crates/hir_ty/src/autoderef.rs2
-rw-r--r--crates/hir_ty/src/chalk_ext.rs28
-rw-r--r--crates/hir_ty/src/display.rs13
-rw-r--r--crates/hir_ty/src/infer/expr.rs16
-rw-r--r--crates/hir_ty/src/lib.rs89
-rw-r--r--crates/hir_ty/src/lower.rs8
-rw-r--r--crates/hir_ty/src/method_resolution.rs10
-rw-r--r--crates/hir_ty/src/traits/chalk.rs14
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs6
-rw-r--r--crates/hir_ty/src/types.rs31
11 files changed, 108 insertions, 112 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 003821981..db4ebada4 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -55,6 +55,7 @@ use hir_ty::{
55 autoderef, could_unify, 55 autoderef, could_unify,
56 method_resolution::{self, TyFingerprint}, 56 method_resolution::{self, TyFingerprint},
57 primitive::UintTy, 57 primitive::UintTy,
58 subst_prefix,
58 traits::FnTrait, 59 traits::FnTrait,
59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
60 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution,
@@ -1503,7 +1504,7 @@ impl TypeParam {
1503 let krate = self.id.parent.module(db.upcast()).krate(); 1504 let krate = self.id.parent.module(db.upcast()).krate();
1504 let ty = params.get(local_idx)?.clone(); 1505 let ty = params.get(local_idx)?.clone();
1505 let subst = TyBuilder::type_params_subst(db, self.id.parent); 1506 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1506 let ty = ty.substitute(&Interner, &subst.prefix(local_idx)); 1507 let ty = ty.substitute(&Interner, &subst_prefix(&subst, local_idx));
1507 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1508 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1508 } 1509 }
1509} 1510}
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 7ca4af80e..c5890e24d 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -13,7 +13,7 @@ use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, 15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, 16 InEnvironment, Interner, ProjectionTyExt, Solution, Ty, TyBuilder, TyKind,
17}; 17};
18 18
19const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const AUTODEREF_RECURSION_LIMIT: usize = 10;
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index b7463366b..0f4cb43e9 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,6 +1,11 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use crate::{Interner, Ty, TyKind}; 3use hir_def::{AssocContainerId, Lookup, TraitId};
4
5use crate::{
6 db::HirDatabase, from_assoc_type_id, to_chalk_trait_id, Interner, ProjectionTy, TraitRef, Ty,
7 TyKind,
8};
4 9
5pub trait TyExt { 10pub trait TyExt {
6 fn is_unit(&self) -> bool; 11 fn is_unit(&self) -> bool;
@@ -11,3 +16,24 @@ impl TyExt for Ty {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _)) 16 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 } 17 }
13} 18}
19
20pub trait ProjectionTyExt {
21 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
22 fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
23}
24
25impl ProjectionTyExt for ProjectionTy {
26 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
27 TraitRef {
28 trait_id: to_chalk_trait_id(self.trait_(db)),
29 substitution: self.substitution.clone(),
30 }
31 }
32
33 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
34 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
35 AssocContainerId::TraitId(it) => it,
36 _ => panic!("projection ty without parent trait"),
37 }
38 }
39}
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 01c7ef91f..4ef8024d0 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -19,10 +19,11 @@ use hir_expand::name::Name;
19 19
20use crate::{ 20use crate::{
21 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, 21 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx,
22 lt_from_placeholder_idx, primitive, to_assoc_type_id, traits::chalk::from_chalk, 22 lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id, traits::chalk::from_chalk,
23 utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg, 23 utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg,
24 ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, 24 ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability, OpaqueTy,
25 ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, 25 ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind,
26 WhereClause,
26}; 27};
27 28
28pub struct HirFormatter<'a> { 29pub struct HirFormatter<'a> {
@@ -483,9 +484,11 @@ impl HirDisplay for Ty {
483 default_from = i + 1; 484 default_from = i + 1;
484 } 485 }
485 (_, Some(default_parameter)) => { 486 (_, Some(default_parameter)) => {
486 let actual_default = default_parameter 487 let actual_default =
487 .clone() 488 default_parameter.clone().substitute(
488 .substitute(&Interner, &parameters.prefix(i)); 489 &Interner,
490 &subst_prefix(parameters, i),
491 );
489 if parameter.assert_ty_ref(&Interner) != &actual_default 492 if parameter.assert_ty_ref(&Interner) != &actual_default
490 { 493 {
491 default_from = i + 1; 494 default_from = i + 1;
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 6966d26e7..185a2dfc3 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -22,8 +22,8 @@ use crate::{
22 to_chalk_trait_id, 22 to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait}, 23 traits::{chalk::from_chalk, FnTrait},
24 utils::{generics, variant_data, Generics}, 24 utils::{generics, variant_data, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar, 25 AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, ProjectionTyExt,
26 Substitution, TraitRef, Ty, TyBuilder, TyKind, 26 Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyKind,
27}; 27};
28 28
29use super::{ 29use super::{
@@ -180,7 +180,8 @@ impl<'a> InferenceContext<'a> {
180 let inner_ty = self.infer_expr(*body, &Expectation::none()); 180 let inner_ty = self.infer_expr(*body, &Expectation::none());
181 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); 181 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
182 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); 182 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
183 TyKind::OpaqueType(opaque_ty_id, Substitution::single(inner_ty)).intern(&Interner) 183 TyKind::OpaqueType(opaque_ty_id, Substitution::from1(&Interner, inner_ty))
184 .intern(&Interner)
184 } 185 }
185 Expr::Loop { body, label } => { 186 Expr::Loop { body, label } => {
186 self.breakables.push(BreakableContext { 187 self.breakables.push(BreakableContext {
@@ -266,7 +267,8 @@ impl<'a> InferenceContext<'a> {
266 .intern(&Interner); 267 .intern(&Interner);
267 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); 268 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
268 let closure_ty = 269 let closure_ty =
269 TyKind::Closure(closure_id, Substitution::single(sig_ty)).intern(&Interner); 270 TyKind::Closure(closure_id, Substitution::from1(&Interner, sig_ty))
271 .intern(&Interner);
270 272
271 // Eagerly try to relate the closure type with the expected 273 // Eagerly try to relate the closure type with the expected
272 // type, otherwise we often won't have enough information to 274 // type, otherwise we often won't have enough information to
@@ -962,8 +964,10 @@ impl<'a> InferenceContext<'a> {
962 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container 964 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
963 { 965 {
964 // construct a TraitRef 966 // construct a TraitRef
965 let substs = 967 let substs = crate::subst_prefix(
966 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 968 &*parameters,
969 generics(self.db.upcast(), trait_.into()).len(),
970 );
967 self.push_obligation( 971 self.push_obligation(
968 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } 972 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
969 .cast(&Interner), 973 .cast(&Interner),
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index a3addc8e9..f74b22b58 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -31,7 +31,6 @@ mod test_db;
31use std::sync::Arc; 31use std::sync::Arc;
32 32
33use itertools::Itertools; 33use itertools::Itertools;
34use smallvec::SmallVec;
35 34
36use base_db::salsa; 35use base_db::salsa;
37use hir_def::{ 36use hir_def::{
@@ -43,13 +42,13 @@ use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43 42
44pub use autoderef::autoderef; 43pub use autoderef::autoderef;
45pub use builder::TyBuilder; 44pub use builder::TyBuilder;
46pub use chalk_ext::TyExt; 45pub use chalk_ext::{ProjectionTyExt, TyExt};
47pub use infer::{could_unify, InferenceResult, InferenceVar}; 46pub use infer::{could_unify, InferenceResult, InferenceVar};
48pub use lower::{ 47pub use lower::{
49 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 48 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
50 TyDefId, TyLoweringContext, ValueTyDefId, 49 TyDefId, TyLoweringContext, ValueTyDefId,
51}; 50};
52pub use traits::TraitEnvironment; 51pub use traits::{chalk::Interner, TraitEnvironment};
53pub use types::*; 52pub use types::*;
54pub use walk::TypeWalk; 53pub use walk::TypeWalk;
55 54
@@ -57,8 +56,6 @@ pub use chalk_ir::{
57 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, 56 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
58}; 57};
59 58
60pub use crate::traits::chalk::Interner;
61
62pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; 59pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
63pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 60pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
64pub type FnDefId = chalk_ir::FnDefId<Interner>; 61pub type FnDefId = chalk_ir::FnDefId<Interner>;
@@ -76,46 +73,11 @@ pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
76 73
77pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 74pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
78 75
79impl ProjectionTy {
80 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
81 TraitRef {
82 trait_id: to_chalk_trait_id(self.trait_(db)),
83 substitution: self.substitution.clone(),
84 }
85 }
86
87 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
88 &self.substitution.interned()[0].assert_ty_ref(interner)
89 }
90
91 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
92 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
93 AssocContainerId::TraitId(it) => it,
94 _ => panic!("projection ty without parent trait"),
95 }
96 }
97}
98
99pub type FnSig = chalk_ir::FnSig<Interner>; 76pub type FnSig = chalk_ir::FnSig<Interner>;
100 77
101impl Substitution { 78// FIXME: get rid of this
102 pub fn single(ty: Ty) -> Substitution { 79pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
103 Substitution::intern({ 80 Substitution::intern(s.interned()[..std::cmp::min(s.len(&Interner), n)].into())
104 let mut v = SmallVec::new();
105 v.push(ty.cast(&Interner));
106 v
107 })
108 }
109
110 pub fn prefix(&self, n: usize) -> Substitution {
111 Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into())
112 }
113
114 pub fn suffix(&self, n: usize) -> Substitution {
115 Substitution::intern(
116 self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(),
117 )
118 }
119} 81}
120 82
121/// Return an index of a parameter in the generic type parameter list by it's id. 83/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -123,22 +85,11 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
123 generics(db.upcast(), id.parent).param_idx(id) 85 generics(db.upcast(), id.parent).param_idx(id)
124} 86}
125 87
126impl<T> Binders<T> { 88pub fn wrap_empty_binders<T>(value: T) -> Binders<T>
127 pub fn wrap_empty(value: T) -> Self 89where
128 where 90 T: TypeWalk,
129 T: TypeWalk, 91{
130 { 92 Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
131 Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
132 }
133}
134
135impl<T: TypeWalk> Binders<T> {
136 /// Substitutes all variables.
137 pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
138 let (value, binders) = self.into_value_and_skipped_binders();
139 assert_eq!(subst.len(interner), binders.len(interner));
140 value.subst_bound_vars(subst)
141 }
142} 93}
143 94
144pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { 95pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
@@ -153,31 +104,11 @@ pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
153} 104}
154 105
155impl TraitRef { 106impl TraitRef {
156 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
157 &self.substitution.at(interner, 0).assert_ty_ref(interner)
158 }
159
160 pub fn hir_trait_id(&self) -> TraitId { 107 pub fn hir_trait_id(&self) -> TraitId {
161 from_chalk_trait_id(self.trait_id) 108 from_chalk_trait_id(self.trait_id)
162 } 109 }
163} 110}
164 111
165impl WhereClause {
166 pub fn is_implemented(&self) -> bool {
167 matches!(self, WhereClause::Implemented(_))
168 }
169
170 pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
171 match self {
172 WhereClause::Implemented(tr) => Some(tr.clone()),
173 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
174 Some(proj.trait_ref(db))
175 }
176 WhereClause::AliasEq(_) => None,
177 }
178 }
179}
180
181impl<T> Canonical<T> { 112impl<T> Canonical<T> {
182 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { 113 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
183 let kinds = kinds.into_iter().map(|tk| { 114 let kinds = kinds.into_iter().map(|tk| {
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 48c26f471..6cef8095f 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -384,7 +384,9 @@ impl<'a> TyLoweringContext<'a> {
384 1, 384 1,
385 QuantifiedWhereClauses::from_iter( 385 QuantifiedWhereClauses::from_iter(
386 &Interner, 386 &Interner,
387 Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), 387 Some(crate::wrap_empty_binders(WhereClause::Implemented(
388 trait_ref,
389 ))),
388 ), 390 ),
389 ), 391 ),
390 }; 392 };
@@ -720,7 +722,7 @@ impl<'a> TyLoweringContext<'a> {
720 let trait_ref = match bound { 722 let trait_ref = match bound {
721 TypeBound::Path(path) => { 723 TypeBound::Path(path) => {
722 bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); 724 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
723 bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) 725 bindings.clone().map(WhereClause::Implemented).map(|b| crate::wrap_empty_binders(b))
724 } 726 }
725 TypeBound::Lifetime(_) => None, 727 TypeBound::Lifetime(_) => None,
726 TypeBound::Error => None, 728 TypeBound::Error => None,
@@ -767,7 +769,7 @@ impl<'a> TyLoweringContext<'a> {
767 let ty = self.lower_ty(type_ref); 769 let ty = self.lower_ty(type_ref);
768 let alias_eq = 770 let alias_eq =
769 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; 771 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
770 preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); 772 preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
771 } 773 }
772 for bound in &binding.bounds { 774 for bound in &binding.bounds {
773 preds.extend(self.lower_type_bound( 775 preds.extend(self.lower_type_bound(
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 19a1fa793..d6de844a8 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -709,8 +709,9 @@ pub(crate) fn inherent_impl_substs(
709) -> Option<Substitution> { 709) -> Option<Substitution> {
710 // we create a var for each type parameter of the impl; we need to keep in 710 // we create a var for each type parameter of the impl; we need to keep in
711 // mind here that `self_ty` might have vars of its own 711 // mind here that `self_ty` might have vars of its own
712 let self_ty_vars = self_ty.binders.len(&Interner);
712 let vars = TyBuilder::subst_for_def(db, impl_id) 713 let vars = TyBuilder::subst_for_def(db, impl_id)
713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) 714 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty_vars)
714 .build(); 715 .build();
715 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars); 716 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars);
716 let mut kinds = self_ty.binders.interned().to_vec(); 717 let mut kinds = self_ty.binders.interned().to_vec();
@@ -725,14 +726,15 @@ pub(crate) fn inherent_impl_substs(
725 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 726 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
726 value: (self_ty_with_vars, self_ty.value.clone()), 727 value: (self_ty_with_vars, self_ty.value.clone()),
727 }; 728 };
728 let substs = super::infer::unify(&tys); 729 let substs = super::infer::unify(&tys)?;
729 // We only want the substs for the vars we added, not the ones from self_ty. 730 // We only want the substs for the vars we added, not the ones from self_ty.
730 // Also, if any of the vars we added are still in there, we replace them by 731 // Also, if any of the vars we added are still in there, we replace them by
731 // Unknown. I think this can only really happen if self_ty contained 732 // Unknown. I think this can only really happen if self_ty contained
732 // Unknown, and in that case we want the result to contain Unknown in those 733 // Unknown, and in that case we want the result to contain Unknown in those
733 // places again. 734 // places again.
734 substs 735 let suffix =
735 .map(|s| fallback_bound_vars(s.suffix(vars.len(&Interner)), self_ty.binders.len(&Interner))) 736 Substitution::from_iter(&Interner, substs.iter(&Interner).cloned().skip(self_ty_vars));
737 Some(fallback_bound_vars(suffix, self_ty_vars))
736} 738}
737 739
738/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 740/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index dff87ef70..5a8b5cd86 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -220,7 +220,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
220 let impl_bound = WhereClause::Implemented(TraitRef { 220 let impl_bound = WhereClause::Implemented(TraitRef {
221 trait_id: to_chalk_trait_id(future_trait), 221 trait_id: to_chalk_trait_id(future_trait),
222 // Self type as the first parameter. 222 // Self type as the first parameter.
223 substitution: Substitution::single( 223 substitution: Substitution::from1(
224 &Interner,
224 TyKind::BoundVar(BoundVar { 225 TyKind::BoundVar(BoundVar {
225 debruijn: DebruijnIndex::INNERMOST, 226 debruijn: DebruijnIndex::INNERMOST,
226 index: 0, 227 index: 0,
@@ -232,7 +233,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
232 alias: AliasTy::Projection(ProjectionTy { 233 alias: AliasTy::Projection(ProjectionTy {
233 associated_ty_id: to_assoc_type_id(future_output), 234 associated_ty_id: to_assoc_type_id(future_output),
234 // Self type as the first parameter. 235 // Self type as the first parameter.
235 substitution: Substitution::single( 236 substitution: Substitution::from1(
237 &Interner,
236 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 238 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
237 .intern(&Interner), 239 .intern(&Interner),
238 ), 240 ),
@@ -244,8 +246,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
244 let bound = OpaqueTyDatumBound { 246 let bound = OpaqueTyDatumBound {
245 bounds: make_binders( 247 bounds: make_binders(
246 vec![ 248 vec![
247 wrap_in_empty_binders(impl_bound).to_chalk(self.db), 249 crate::wrap_empty_binders(impl_bound).to_chalk(self.db),
248 wrap_in_empty_binders(proj_bound).to_chalk(self.db), 250 crate::wrap_empty_binders(proj_bound).to_chalk(self.db),
249 ], 251 ],
250 1, 252 1,
251 ), 253 ),
@@ -721,7 +723,3 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
721 chalk_ir::ClosureId(id.as_intern_id()) 723 chalk_ir::ClosureId(id.as_intern_id())
722 } 724 }
723} 725}
724
725fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
726 crate::Binders::wrap_empty(value)
727}
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index c3b148cab..9f10b889f 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -10,9 +10,9 @@ use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer, 13 chalk_ext::ProjectionTyExt, db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId,
14 GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, 14 Canonical, DomainGoal, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy,
15 TraitRef, Ty, TypeWalk, WhereClause, 15 QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
16}; 16};
17 17
18use super::interner::*; 18use super::interner::*;
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index dc64e6e2b..4a626d5e7 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -4,7 +4,7 @@
4use std::sync::Arc; 4use std::sync::Arc;
5 5
6use chalk_ir::{ 6use chalk_ir::{
7 cast::{CastTo, Caster}, 7 cast::{Cast, CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind, 8 BoundVar, Mutability, Scalar, TyVariableKind,
9}; 9};
10use smallvec::SmallVec; 10use smallvec::SmallVec;
@@ -29,6 +29,12 @@ pub struct ProjectionTy {
29 pub substitution: Substitution, 29 pub substitution: Substitution,
30} 30}
31 31
32impl ProjectionTy {
33 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
34 &self.substitution.interned()[0].assert_ty_ref(interner)
35 }
36}
37
32#[derive(Clone, PartialEq, Eq, Debug, Hash)] 38#[derive(Clone, PartialEq, Eq, Debug, Hash)]
33pub struct DynTy { 39pub struct DynTy {
34 /// The unknown self type. 40 /// The unknown self type.
@@ -272,6 +278,14 @@ impl Substitution {
272 self.0.iter() 278 self.0.iter()
273 } 279 }
274 280
281 pub fn from1(_interner: &Interner, ty: Ty) -> Substitution {
282 Substitution::intern({
283 let mut v = SmallVec::new();
284 v.push(ty.cast(&Interner));
285 v
286 })
287 }
288
275 pub fn from_iter( 289 pub fn from_iter(
276 interner: &Interner, 290 interner: &Interner,
277 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, 291 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
@@ -346,6 +360,15 @@ impl<T: Clone> Binders<&T> {
346 } 360 }
347} 361}
348 362
363impl<T: TypeWalk> Binders<T> {
364 /// Substitutes all variables.
365 pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
366 let (value, binders) = self.into_value_and_skipped_binders();
367 assert_eq!(subst.len(interner), binders.len(interner));
368 value.subst_bound_vars(subst)
369 }
370}
371
349impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> { 372impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> {
350 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> { 373 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
351 let Binders { ref binders, ref value } = *self; 374 let Binders { ref binders, ref value } = *self;
@@ -361,6 +384,12 @@ pub struct TraitRef {
361 pub substitution: Substitution, 384 pub substitution: Substitution,
362} 385}
363 386
387impl TraitRef {
388 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
389 &self.substitution.at(interner, 0).assert_ty_ref(interner)
390 }
391}
392
364/// Like `generics::WherePredicate`, but with resolved types: A condition on the 393/// Like `generics::WherePredicate`, but with resolved types: A condition on the
365/// parameters of a generic item. 394/// parameters of a generic item.
366#[derive(Debug, Clone, PartialEq, Eq, Hash)] 395#[derive(Debug, Clone, PartialEq, Eq, Hash)]