diff options
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 2 | ||||
-rw-r--r-- | crates/hir_ty/src/chalk_ext.rs | 28 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 16 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 89 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 8 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 14 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 6 | ||||
-rw-r--r-- | crates/hir_ty/src/types.rs | 31 |
10 files changed, 106 insertions, 111 deletions
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 | ||
14 | use crate::{ | 14 | use 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 | ||
19 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 19 | const 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 | ||
3 | use crate::{Interner, Ty, TyKind}; | 3 | use hir_def::{AssocContainerId, Lookup, TraitId}; |
4 | |||
5 | use crate::{ | ||
6 | db::HirDatabase, from_assoc_type_id, to_chalk_trait_id, Interner, ProjectionTy, TraitRef, Ty, | ||
7 | TyKind, | ||
8 | }; | ||
4 | 9 | ||
5 | pub trait TyExt { | 10 | pub 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 | |||
20 | pub trait ProjectionTyExt { | ||
21 | fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef; | ||
22 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId; | ||
23 | } | ||
24 | |||
25 | impl 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 | ||
20 | use crate::{ | 20 | use 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 | ||
28 | pub struct HirFormatter<'a> { | 29 | pub 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, ¶meters.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 | ||
29 | use super::{ | 29 | use 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; | |||
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | 32 | ||
33 | use itertools::Itertools; | 33 | use itertools::Itertools; |
34 | use smallvec::SmallVec; | ||
35 | 34 | ||
36 | use base_db::salsa; | 35 | use base_db::salsa; |
37 | use hir_def::{ | 36 | use hir_def::{ |
@@ -43,13 +42,13 @@ use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; | |||
43 | 42 | ||
44 | pub use autoderef::autoderef; | 43 | pub use autoderef::autoderef; |
45 | pub use builder::TyBuilder; | 44 | pub use builder::TyBuilder; |
46 | pub use chalk_ext::TyExt; | 45 | pub use chalk_ext::{ProjectionTyExt, TyExt}; |
47 | pub use infer::{could_unify, InferenceResult, InferenceVar}; | 46 | pub use infer::{could_unify, InferenceResult, InferenceVar}; |
48 | pub use lower::{ | 47 | pub 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 | }; |
52 | pub use traits::TraitEnvironment; | 51 | pub use traits::{chalk::Interner, TraitEnvironment}; |
53 | pub use types::*; | 52 | pub use types::*; |
54 | pub use walk::TypeWalk; | 53 | pub 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 | ||
60 | pub use crate::traits::chalk::Interner; | ||
61 | |||
62 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; | 59 | pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; |
63 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; | 60 | pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; |
64 | pub type FnDefId = chalk_ir::FnDefId<Interner>; | 61 | pub type FnDefId = chalk_ir::FnDefId<Interner>; |
@@ -76,46 +73,11 @@ pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; | |||
76 | 73 | ||
77 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 74 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
78 | 75 | ||
79 | impl 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 | |||
99 | pub type FnSig = chalk_ir::FnSig<Interner>; | 76 | pub type FnSig = chalk_ir::FnSig<Interner>; |
100 | 77 | ||
101 | impl Substitution { | 78 | // FIXME: get rid of this |
102 | pub fn single(ty: Ty) -> Substitution { | 79 | pub 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 | ||
126 | impl<T> Binders<T> { | 88 | pub fn wrap_empty_binders<T>(value: T) -> Binders<T> |
127 | pub fn wrap_empty(value: T) -> Self | 89 | where |
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 | |||
135 | impl<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 | ||
144 | pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { | 95 | pub 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 | ||
155 | impl TraitRef { | 106 | impl 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 | ||
165 | impl 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 | |||
181 | impl<T> Canonical<T> { | 112 | impl<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 | |||
725 | fn 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; | |||
10 | use hir_def::{GenericDefId, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | ||
18 | use super::interner::*; | 18 | use 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 @@ | |||
4 | use std::sync::Arc; | 4 | use std::sync::Arc; |
5 | 5 | ||
6 | use chalk_ir::{ | 6 | use chalk_ir::{ |
7 | cast::{CastTo, Caster}, | 7 | cast::{Cast, CastTo, Caster}, |
8 | BoundVar, Mutability, Scalar, TyVariableKind, | 8 | BoundVar, Mutability, Scalar, TyVariableKind, |
9 | }; | 9 | }; |
10 | use smallvec::SmallVec; | 10 | use smallvec::SmallVec; |
@@ -29,6 +29,12 @@ pub struct ProjectionTy { | |||
29 | pub substitution: Substitution, | 29 | pub substitution: Substitution, |
30 | } | 30 | } |
31 | 31 | ||
32 | impl 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)] |
33 | pub struct DynTy { | 39 | pub 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 | ||
363 | impl<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 | |||
349 | impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> { | 372 | impl<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 | ||
387 | impl 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)] |