diff options
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r-- | crates/hir_ty/src/autoderef.rs | 62 | ||||
-rw-r--r-- | crates/hir_ty/src/chalk_cast.rs | 53 | ||||
-rw-r--r-- | crates/hir_ty/src/db.rs | 10 | ||||
-rw-r--r-- | crates/hir_ty/src/diagnostics/decl_check.rs | 15 | ||||
-rw-r--r-- | crates/hir_ty/src/display.rs | 152 | ||||
-rw-r--r-- | crates/hir_ty/src/infer.rs | 29 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/coerce.rs | 13 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/expr.rs | 49 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/pat.rs | 34 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/path.rs | 20 | ||||
-rw-r--r-- | crates/hir_ty/src/infer/unify.rs | 119 | ||||
-rw-r--r-- | crates/hir_ty/src/lib.rs | 217 | ||||
-rw-r--r-- | crates/hir_ty/src/lower.rs | 111 | ||||
-rw-r--r-- | crates/hir_ty/src/method_resolution.rs | 62 | ||||
-rw-r--r-- | crates/hir_ty/src/tests.rs | 69 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/macros.rs | 45 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/patterns.rs | 22 | ||||
-rw-r--r-- | crates/hir_ty/src/tests/traits.rs | 54 | ||||
-rw-r--r-- | crates/hir_ty/src/traits.rs | 75 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk.rs | 48 | ||||
-rw-r--r-- | crates/hir_ty/src/traits/chalk/mapping.rs | 238 | ||||
-rw-r--r-- | crates/hir_ty/src/utils.rs | 16 |
22 files changed, 996 insertions, 517 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index bd2ff5d38..dc5fc759a 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -6,16 +6,18 @@ | |||
6 | use std::iter::successors; | 6 | use std::iter::successors; |
7 | 7 | ||
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::cast::Cast; | ||
9 | use hir_def::lang_item::LangItemTarget; | 10 | use hir_def::lang_item::LangItemTarget; |
10 | use hir_expand::name::name; | 11 | use hir_expand::name::name; |
11 | use log::{info, warn}; | 12 | use log::{info, warn}; |
12 | 13 | ||
13 | use crate::{ | 14 | use crate::{ |
14 | db::HirDatabase, | 15 | db::HirDatabase, |
15 | to_assoc_type_id, | 16 | to_assoc_type_id, to_chalk_trait_id, |
16 | traits::{InEnvironment, Solution}, | 17 | traits::{InEnvironment, Solution}, |
17 | utils::generics, | 18 | utils::generics, |
18 | BoundVar, Canonical, DebruijnIndex, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, | 19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, |
20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, | ||
19 | }; | 21 | }; |
20 | 22 | ||
21 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -25,9 +27,9 @@ pub fn autoderef<'a>( | |||
25 | krate: Option<CrateId>, | 27 | krate: Option<CrateId>, |
26 | ty: InEnvironment<Canonical<Ty>>, | 28 | ty: InEnvironment<Canonical<Ty>>, |
27 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { | 29 | ) -> impl Iterator<Item = Canonical<Ty>> + 'a { |
28 | let InEnvironment { value: ty, environment } = ty; | 30 | let InEnvironment { goal: ty, environment } = ty; |
29 | successors(Some(ty), move |ty| { | 31 | successors(Some(ty), move |ty| { |
30 | deref(db, krate?, InEnvironment { value: ty, environment: environment.clone() }) | 32 | deref(db, krate?, InEnvironment { goal: ty, environment: environment.clone() }) |
31 | }) | 33 | }) |
32 | .take(AUTODEREF_RECURSION_LIMIT) | 34 | .take(AUTODEREF_RECURSION_LIMIT) |
33 | } | 35 | } |
@@ -37,8 +39,8 @@ pub(crate) fn deref( | |||
37 | krate: CrateId, | 39 | krate: CrateId, |
38 | ty: InEnvironment<&Canonical<Ty>>, | 40 | ty: InEnvironment<&Canonical<Ty>>, |
39 | ) -> Option<Canonical<Ty>> { | 41 | ) -> Option<Canonical<Ty>> { |
40 | if let Some(derefed) = ty.value.value.builtin_deref() { | 42 | if let Some(derefed) = ty.goal.value.builtin_deref() { |
41 | Some(Canonical { value: derefed, kinds: ty.value.kinds.clone() }) | 43 | Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) |
42 | } else { | 44 | } else { |
43 | deref_by_trait(db, krate, ty) | 45 | deref_by_trait(db, krate, ty) |
44 | } | 46 | } |
@@ -65,14 +67,15 @@ fn deref_by_trait( | |||
65 | // FIXME make the Canonical / bound var handling nicer | 67 | // FIXME make the Canonical / bound var handling nicer |
66 | 68 | ||
67 | let parameters = | 69 | let parameters = |
68 | Substitution::build_for_generics(&generic_params).push(ty.value.value.clone()).build(); | 70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); |
69 | 71 | ||
70 | // Check that the type implements Deref at all | 72 | // Check that the type implements Deref at all |
71 | let trait_ref = TraitRef { trait_: deref_trait, substs: parameters.clone() }; | 73 | let trait_ref = |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | ||
72 | let implements_goal = Canonical { | 75 | let implements_goal = Canonical { |
73 | kinds: ty.value.kinds.clone(), | 76 | binders: ty.goal.binders.clone(), |
74 | value: InEnvironment { | 77 | value: InEnvironment { |
75 | value: Obligation::Trait(trait_ref), | 78 | goal: trait_ref.cast(&Interner), |
76 | environment: ty.environment.clone(), | 79 | environment: ty.environment.clone(), |
77 | }, | 80 | }, |
78 | }; | 81 | }; |
@@ -81,23 +84,32 @@ fn deref_by_trait( | |||
81 | } | 84 | } |
82 | 85 | ||
83 | // Now do the assoc type projection | 86 | // Now do the assoc type projection |
84 | let projection = super::traits::ProjectionPredicate { | 87 | let projection = AliasEq { |
85 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, ty.value.kinds.len())) | 88 | alias: AliasTy::Projection(ProjectionTy { |
86 | .intern(&Interner), | ||
87 | projection_ty: super::ProjectionTy { | ||
88 | associated_ty_id: to_assoc_type_id(target), | 89 | associated_ty_id: to_assoc_type_id(target), |
89 | substitution: parameters, | 90 | substitution: parameters, |
90 | }, | 91 | }), |
92 | ty: TyKind::BoundVar(BoundVar::new( | ||
93 | DebruijnIndex::INNERMOST, | ||
94 | ty.goal.binders.len(&Interner), | ||
95 | )) | ||
96 | .intern(&Interner), | ||
91 | }; | 97 | }; |
92 | 98 | ||
93 | let obligation = super::Obligation::Projection(projection); | 99 | let obligation = projection.cast(&Interner); |
94 | 100 | ||
95 | let in_env = InEnvironment { value: obligation, environment: ty.environment }; | 101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; |
96 | 102 | ||
97 | let canonical = Canonical::new( | 103 | let canonical = Canonical { |
98 | in_env, | 104 | value: in_env, |
99 | ty.value.kinds.iter().copied().chain(Some(chalk_ir::TyVariableKind::General)), | 105 | binders: CanonicalVarKinds::from_iter( |
100 | ); | 106 | &Interner, |
107 | ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( | ||
108 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
109 | chalk_ir::UniverseIndex::ROOT, | ||
110 | ))), | ||
111 | ), | ||
112 | }; | ||
101 | 113 | ||
102 | let solution = db.trait_solve(krate, canonical)?; | 114 | let solution = db.trait_solve(krate, canonical)?; |
103 | 115 | ||
@@ -118,21 +130,21 @@ fn deref_by_trait( | |||
118 | // assumptions will be broken. We would need to properly introduce | 130 | // assumptions will be broken. We would need to properly introduce |
119 | // new variables in that case | 131 | // new variables in that case |
120 | 132 | ||
121 | for i in 1..vars.0.kinds.len() { | 133 | for i in 1..vars.0.binders.len(&Interner) { |
122 | if vars.0.value[i - 1].interned(&Interner) | 134 | if vars.0.value[i - 1].interned(&Interner) |
123 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 135 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
124 | { | 136 | { |
125 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.value, solution); | 137 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
126 | return None; | 138 | return None; |
127 | } | 139 | } |
128 | } | 140 | } |
129 | Some(Canonical { | 141 | Some(Canonical { |
130 | value: vars.0.value[vars.0.value.len() - 1].clone(), | 142 | value: vars.0.value[vars.0.value.len() - 1].clone(), |
131 | kinds: vars.0.kinds.clone(), | 143 | binders: vars.0.binders.clone(), |
132 | }) | 144 | }) |
133 | } | 145 | } |
134 | Solution::Ambig(_) => { | 146 | Solution::Ambig(_) => { |
135 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.value, solution); | 147 | info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); |
136 | None | 148 | None |
137 | } | 149 | } |
138 | } | 150 | } |
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs new file mode 100644 index 000000000..bf884ae15 --- /dev/null +++ b/crates/hir_ty/src/chalk_cast.rs | |||
@@ -0,0 +1,53 @@ | |||
1 | //! Implementations of the Chalk `Cast` trait for our types. | ||
2 | |||
3 | use chalk_ir::{ | ||
4 | cast::{Cast, CastTo}, | ||
5 | interner::HasInterner, | ||
6 | }; | ||
7 | |||
8 | use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; | ||
9 | |||
10 | macro_rules! has_interner { | ||
11 | ($t:ty) => { | ||
12 | impl HasInterner for $t { | ||
13 | type Interner = crate::Interner; | ||
14 | } | ||
15 | }; | ||
16 | } | ||
17 | |||
18 | has_interner!(WhereClause); | ||
19 | has_interner!(DomainGoal); | ||
20 | |||
21 | impl CastTo<WhereClause> for TraitRef { | ||
22 | fn cast_to(self, _interner: &Interner) -> WhereClause { | ||
23 | WhereClause::Implemented(self) | ||
24 | } | ||
25 | } | ||
26 | |||
27 | impl CastTo<WhereClause> for AliasEq { | ||
28 | fn cast_to(self, _interner: &Interner) -> WhereClause { | ||
29 | WhereClause::AliasEq(self) | ||
30 | } | ||
31 | } | ||
32 | |||
33 | impl CastTo<DomainGoal> for WhereClause { | ||
34 | fn cast_to(self, _interner: &Interner) -> DomainGoal { | ||
35 | DomainGoal::Holds(self) | ||
36 | } | ||
37 | } | ||
38 | |||
39 | macro_rules! transitive_impl { | ||
40 | ($a:ty, $b:ty, $c:ty) => { | ||
41 | impl CastTo<$c> for $a { | ||
42 | fn cast_to(self, interner: &Interner) -> $c { | ||
43 | self.cast::<$b>(interner).cast(interner) | ||
44 | } | ||
45 | } | ||
46 | }; | ||
47 | } | ||
48 | |||
49 | // In Chalk, these can be done as blanket impls, but that doesn't work here | ||
50 | // because of coherence | ||
51 | |||
52 | transitive_impl!(TraitRef, WhereClause, DomainGoal); | ||
53 | transitive_impl!(AliasEq, WhereClause, DomainGoal); | ||
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 74a048672..58e4247c6 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -12,8 +12,8 @@ use la_arena::ArenaMap; | |||
12 | use crate::{ | 12 | use crate::{ |
13 | method_resolution::{InherentImpls, TraitImpls}, | 13 | method_resolution::{InherentImpls, TraitImpls}, |
14 | traits::chalk, | 14 | traits::chalk, |
15 | Binders, CallableDefId, FnDefId, GenericPredicate, ImplTraitId, InferenceResult, PolyFnSig, | 15 | Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig, |
16 | ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, | 16 | QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, |
17 | }; | 17 | }; |
18 | use hir_expand::name::Name; | 18 | use hir_expand::name::Name; |
19 | 19 | ||
@@ -60,10 +60,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
60 | fn generic_predicates_for_param( | 60 | fn generic_predicates_for_param( |
61 | &self, | 61 | &self, |
62 | param_id: TypeParamId, | 62 | param_id: TypeParamId, |
63 | ) -> Arc<[Binders<GenericPredicate>]>; | 63 | ) -> Arc<[Binders<QuantifiedWhereClause>]>; |
64 | 64 | ||
65 | #[salsa::invoke(crate::lower::generic_predicates_query)] | 65 | #[salsa::invoke(crate::lower::generic_predicates_query)] |
66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<GenericPredicate>]>; | 66 | fn generic_predicates(&self, def: GenericDefId) -> Arc<[Binders<QuantifiedWhereClause>]>; |
67 | 67 | ||
68 | #[salsa::invoke(crate::lower::trait_environment_query)] | 68 | #[salsa::invoke(crate::lower::trait_environment_query)] |
69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; | 69 | fn trait_environment(&self, def: GenericDefId) -> Arc<crate::TraitEnvironment>; |
@@ -122,7 +122,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
122 | fn trait_solve( | 122 | fn trait_solve( |
123 | &self, | 123 | &self, |
124 | krate: CrateId, | 124 | krate: CrateId, |
125 | goal: crate::Canonical<crate::InEnvironment<crate::Obligation>>, | 125 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, |
126 | ) -> Option<crate::traits::Solution>; | 126 | ) -> Option<crate::traits::Solution>; |
127 | 127 | ||
128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] | 128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] |
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index bfe239793..33a0f4d7d 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -102,7 +102,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
102 | let db = self.db; | 102 | let db = self.db; |
103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { |
104 | for (_, module) in block_def_map.modules() { | 104 | for (_, module) in block_def_map.modules() { |
105 | for (def_id, _) in module.scope.values() { | 105 | for def_id in module.scope.declarations() { |
106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); |
107 | validator.validate_item(def_id); | 107 | validator.validate_item(def_id); |
108 | } | 108 | } |
@@ -902,4 +902,17 @@ extern { | |||
902 | "#, | 902 | "#, |
903 | ); | 903 | ); |
904 | } | 904 | } |
905 | |||
906 | #[test] | ||
907 | fn infinite_loop_inner_items() { | ||
908 | check_diagnostics( | ||
909 | r#" | ||
910 | fn qualify() { | ||
911 | mod foo { | ||
912 | use super::*; | ||
913 | } | ||
914 | } | ||
915 | "#, | ||
916 | ) | ||
917 | } | ||
905 | } | 918 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 7ce0f864c..6149067c7 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | use std::{borrow::Cow, fmt}; | 3 | use std::fmt; |
4 | 4 | ||
5 | use arrayvec::ArrayVec; | 5 | use arrayvec::ArrayVec; |
6 | use chalk_ir::Mutability; | 6 | use chalk_ir::Mutability; |
@@ -18,9 +18,9 @@ use hir_expand::name::Name; | |||
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 20 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasTy, CallableDefId, | 21 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
22 | CallableSig, GenericPredicate, ImplTraitId, Interner, Lifetime, Obligation, OpaqueTy, | 22 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, |
23 | ProjectionTy, Scalar, Substitution, TraitRef, Ty, TyKind, | 23 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, |
24 | }; | 24 | }; |
25 | 25 | ||
26 | pub struct HirFormatter<'a> { | 26 | pub struct HirFormatter<'a> { |
@@ -190,6 +190,7 @@ impl DisplayTarget { | |||
190 | pub enum DisplaySourceCodeError { | 190 | pub enum DisplaySourceCodeError { |
191 | PathNotFound, | 191 | PathNotFound, |
192 | UnknownType, | 192 | UnknownType, |
193 | Closure, | ||
193 | } | 194 | } |
194 | 195 | ||
195 | pub enum HirDisplayError { | 196 | pub enum HirDisplayError { |
@@ -268,6 +269,16 @@ impl HirDisplay for ProjectionTy { | |||
268 | } | 269 | } |
269 | } | 270 | } |
270 | 271 | ||
272 | impl HirDisplay for OpaqueTy { | ||
273 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
274 | if f.should_truncate() { | ||
275 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | ||
276 | } | ||
277 | |||
278 | self.substitution[0].hir_fmt(f) | ||
279 | } | ||
280 | } | ||
281 | |||
271 | impl HirDisplay for Ty { | 282 | impl HirDisplay for Ty { |
272 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 283 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
273 | if f.should_truncate() { | 284 | if f.should_truncate() { |
@@ -318,9 +329,9 @@ impl HirDisplay for Ty { | |||
318 | 329 | ||
319 | // FIXME: all this just to decide whether to use parentheses... | 330 | // FIXME: all this just to decide whether to use parentheses... |
320 | let datas; | 331 | let datas; |
321 | let predicates = match t.interned(&Interner) { | 332 | let predicates: Vec<_> = match t.interned(&Interner) { |
322 | TyKind::Dyn(predicates) if predicates.len() > 1 => { | 333 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
323 | Cow::Borrowed(predicates.as_ref()) | 334 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
324 | } | 335 | } |
325 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 336 | &TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
326 | opaque_ty_id, | 337 | opaque_ty_id, |
@@ -335,17 +346,21 @@ impl HirDisplay for Ty { | |||
335 | .as_ref() | 346 | .as_ref() |
336 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); | 347 | .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); |
337 | let bounds = data.subst(parameters); | 348 | let bounds = data.subst(parameters); |
338 | Cow::Owned(bounds.value) | 349 | bounds.value |
339 | } else { | 350 | } else { |
340 | Cow::Borrowed(&[][..]) | 351 | Vec::new() |
341 | } | 352 | } |
342 | } | 353 | } |
343 | _ => Cow::Borrowed(&[][..]), | 354 | _ => Vec::new(), |
344 | }; | 355 | }; |
345 | 356 | ||
346 | if let [GenericPredicate::Implemented(trait_ref), _] = predicates.as_ref() { | 357 | if let Some(WhereClause::Implemented(trait_ref)) = |
347 | let trait_ = trait_ref.trait_; | 358 | predicates.get(0).map(|b| b.skip_binders()) |
348 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) { | 359 | { |
360 | let trait_ = trait_ref.hir_trait_id(); | ||
361 | if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) | ||
362 | && predicates.len() <= 2 | ||
363 | { | ||
349 | return write!(f, "{}", ty_display); | 364 | return write!(f, "{}", ty_display); |
350 | } | 365 | } |
351 | } | 366 | } |
@@ -529,6 +544,11 @@ impl HirDisplay for Ty { | |||
529 | } | 544 | } |
530 | } | 545 | } |
531 | TyKind::Closure(.., substs) => { | 546 | TyKind::Closure(.., substs) => { |
547 | if f.display_target.is_source_code() { | ||
548 | return Err(HirDisplayError::DisplaySourceCodeError( | ||
549 | DisplaySourceCodeError::Closure, | ||
550 | )); | ||
551 | } | ||
532 | let sig = substs[0].callable_sig(f.db); | 552 | let sig = substs[0].callable_sig(f.db); |
533 | if let Some(sig) = sig { | 553 | if let Some(sig) = sig { |
534 | if sig.params().is_empty() { | 554 | if sig.params().is_empty() { |
@@ -561,19 +581,32 @@ impl HirDisplay for Ty { | |||
561 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 581 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
562 | } | 582 | } |
563 | TypeParamProvenance::ArgumentImplTrait => { | 583 | TypeParamProvenance::ArgumentImplTrait => { |
564 | let bounds = f.db.generic_predicates_for_param(id); | ||
565 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 584 | let substs = Substitution::type_params_for_generics(f.db, &generics); |
566 | write_bounds_like_dyn_trait_with_prefix( | 585 | let bounds = f |
567 | "impl", | 586 | .db |
568 | &bounds.iter().map(|b| b.clone().subst(&substs)).collect::<Vec<_>>(), | 587 | .generic_predicates(id.parent) |
569 | f, | 588 | .into_iter() |
570 | )?; | 589 | .map(|pred| pred.clone().subst(&substs)) |
590 | .filter(|wc| match &wc.skip_binders() { | ||
591 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
592 | WhereClause::AliasEq(AliasEq { | ||
593 | alias: AliasTy::Projection(proj), | ||
594 | ty: _, | ||
595 | }) => proj.self_type_parameter() == self, | ||
596 | _ => false, | ||
597 | }) | ||
598 | .collect::<Vec<_>>(); | ||
599 | write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; | ||
571 | } | 600 | } |
572 | } | 601 | } |
573 | } | 602 | } |
574 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, | 603 | TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, |
575 | TyKind::Dyn(predicates) => { | 604 | TyKind::Dyn(dyn_ty) => { |
576 | write_bounds_like_dyn_trait_with_prefix("dyn", predicates, f)?; | 605 | write_bounds_like_dyn_trait_with_prefix( |
606 | "dyn", | ||
607 | dyn_ty.bounds.skip_binders().interned(), | ||
608 | f, | ||
609 | )?; | ||
577 | } | 610 | } |
578 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, | 611 | TyKind::Alias(AliasTy::Projection(p_ty)) => p_ty.hir_fmt(f)?, |
579 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { | 612 | TyKind::Alias(AliasTy::Opaque(opaque_ty)) => { |
@@ -642,7 +675,7 @@ fn fn_traits(db: &dyn DefDatabase, trait_: TraitId) -> impl Iterator<Item = Trai | |||
642 | 675 | ||
643 | pub fn write_bounds_like_dyn_trait_with_prefix( | 676 | pub fn write_bounds_like_dyn_trait_with_prefix( |
644 | prefix: &str, | 677 | prefix: &str, |
645 | predicates: &[GenericPredicate], | 678 | predicates: &[QuantifiedWhereClause], |
646 | f: &mut HirFormatter, | 679 | f: &mut HirFormatter, |
647 | ) -> Result<(), HirDisplayError> { | 680 | ) -> Result<(), HirDisplayError> { |
648 | write!(f, "{}", prefix)?; | 681 | write!(f, "{}", prefix)?; |
@@ -655,7 +688,7 @@ pub fn write_bounds_like_dyn_trait_with_prefix( | |||
655 | } | 688 | } |
656 | 689 | ||
657 | fn write_bounds_like_dyn_trait( | 690 | fn write_bounds_like_dyn_trait( |
658 | predicates: &[GenericPredicate], | 691 | predicates: &[QuantifiedWhereClause], |
659 | f: &mut HirFormatter, | 692 | f: &mut HirFormatter, |
660 | ) -> Result<(), HirDisplayError> { | 693 | ) -> Result<(), HirDisplayError> { |
661 | // Note: This code is written to produce nice results (i.e. | 694 | // Note: This code is written to produce nice results (i.e. |
@@ -668,9 +701,9 @@ fn write_bounds_like_dyn_trait( | |||
668 | let mut angle_open = false; | 701 | let mut angle_open = false; |
669 | let mut is_fn_trait = false; | 702 | let mut is_fn_trait = false; |
670 | for p in predicates.iter() { | 703 | for p in predicates.iter() { |
671 | match p { | 704 | match p.skip_binders() { |
672 | GenericPredicate::Implemented(trait_ref) => { | 705 | WhereClause::Implemented(trait_ref) => { |
673 | let trait_ = trait_ref.trait_; | 706 | let trait_ = trait_ref.hir_trait_id(); |
674 | if !is_fn_trait { | 707 | if !is_fn_trait { |
675 | is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); | 708 | is_fn_trait = fn_traits(f.db.upcast(), trait_).any(|it| it == trait_); |
676 | } | 709 | } |
@@ -685,7 +718,7 @@ fn write_bounds_like_dyn_trait( | |||
685 | // existential) here, which is the only thing that's | 718 | // existential) here, which is the only thing that's |
686 | // possible in actual Rust, and hence don't print it | 719 | // possible in actual Rust, and hence don't print it |
687 | write!(f, "{}", f.db.trait_data(trait_).name)?; | 720 | write!(f, "{}", f.db.trait_data(trait_).name)?; |
688 | if let [_, params @ ..] = &*trait_ref.substs.0 { | 721 | if let [_, params @ ..] = &*trait_ref.substitution.0 { |
689 | if is_fn_trait { | 722 | if is_fn_trait { |
690 | if let Some(args) = params.first().and_then(|it| it.as_tuple()) { | 723 | if let Some(args) = params.first().and_then(|it| it.as_tuple()) { |
691 | write!(f, "(")?; | 724 | write!(f, "(")?; |
@@ -700,12 +733,12 @@ fn write_bounds_like_dyn_trait( | |||
700 | } | 733 | } |
701 | } | 734 | } |
702 | } | 735 | } |
703 | GenericPredicate::Projection(projection_pred) if is_fn_trait => { | 736 | WhereClause::AliasEq(alias_eq) if is_fn_trait => { |
704 | is_fn_trait = false; | 737 | is_fn_trait = false; |
705 | write!(f, " -> ")?; | 738 | write!(f, " -> ")?; |
706 | projection_pred.ty.hir_fmt(f)?; | 739 | alias_eq.ty.hir_fmt(f)?; |
707 | } | 740 | } |
708 | GenericPredicate::Projection(projection_pred) => { | 741 | WhereClause::AliasEq(AliasEq { ty, alias }) => { |
709 | // in types in actual Rust, these will always come | 742 | // in types in actual Rust, these will always come |
710 | // after the corresponding Implemented predicate | 743 | // after the corresponding Implemented predicate |
711 | if angle_open { | 744 | if angle_open { |
@@ -714,21 +747,12 @@ fn write_bounds_like_dyn_trait( | |||
714 | write!(f, "<")?; | 747 | write!(f, "<")?; |
715 | angle_open = true; | 748 | angle_open = true; |
716 | } | 749 | } |
717 | let type_alias = f.db.type_alias_data(from_assoc_type_id( | 750 | if let AliasTy::Projection(proj) = alias { |
718 | projection_pred.projection_ty.associated_ty_id, | 751 | let type_alias = |
719 | )); | 752 | f.db.type_alias_data(from_assoc_type_id(proj.associated_ty_id)); |
720 | write!(f, "{} = ", type_alias.name)?; | 753 | write!(f, "{} = ", type_alias.name)?; |
721 | projection_pred.ty.hir_fmt(f)?; | ||
722 | } | ||
723 | GenericPredicate::Error => { | ||
724 | if angle_open { | ||
725 | // impl Trait<X, {error}> | ||
726 | write!(f, ", ")?; | ||
727 | } else if !first { | ||
728 | // impl Trait + {error} | ||
729 | write!(f, " + ")?; | ||
730 | } | 754 | } |
731 | p.hir_fmt(f)?; | 755 | ty.hir_fmt(f)?; |
732 | } | 756 | } |
733 | } | 757 | } |
734 | first = false; | 758 | first = false; |
@@ -745,16 +769,16 @@ impl TraitRef { | |||
745 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 769 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
746 | } | 770 | } |
747 | 771 | ||
748 | self.substs[0].hir_fmt(f)?; | 772 | self.substitution[0].hir_fmt(f)?; |
749 | if use_as { | 773 | if use_as { |
750 | write!(f, " as ")?; | 774 | write!(f, " as ")?; |
751 | } else { | 775 | } else { |
752 | write!(f, ": ")?; | 776 | write!(f, ": ")?; |
753 | } | 777 | } |
754 | write!(f, "{}", f.db.trait_data(self.trait_).name)?; | 778 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; |
755 | if self.substs.len() > 1 { | 779 | if self.substitution.len() > 1 { |
756 | write!(f, "<")?; | 780 | write!(f, "<")?; |
757 | f.write_joined(&self.substs[1..], ", ")?; | 781 | f.write_joined(&self.substitution[1..], ", ")?; |
758 | write!(f, ">")?; | 782 | write!(f, ">")?; |
759 | } | 783 | } |
760 | Ok(()) | 784 | Ok(()) |
@@ -767,28 +791,25 @@ impl HirDisplay for TraitRef { | |||
767 | } | 791 | } |
768 | } | 792 | } |
769 | 793 | ||
770 | impl HirDisplay for GenericPredicate { | 794 | impl HirDisplay for WhereClause { |
771 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 795 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
772 | if f.should_truncate() { | 796 | if f.should_truncate() { |
773 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 797 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
774 | } | 798 | } |
775 | 799 | ||
776 | match self { | 800 | match self { |
777 | GenericPredicate::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, | 801 | WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, |
778 | GenericPredicate::Projection(projection_pred) => { | 802 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
779 | write!(f, "<")?; | 803 | write!(f, "<")?; |
780 | projection_pred.projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; | 804 | projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; |
781 | write!( | 805 | write!( |
782 | f, | 806 | f, |
783 | ">::{} = ", | 807 | ">::{} = ", |
784 | f.db.type_alias_data(from_assoc_type_id( | 808 | f.db.type_alias_data(from_assoc_type_id(projection_ty.associated_ty_id)).name, |
785 | projection_pred.projection_ty.associated_ty_id | ||
786 | )) | ||
787 | .name, | ||
788 | )?; | 809 | )?; |
789 | projection_pred.ty.hir_fmt(f)?; | 810 | ty.hir_fmt(f)?; |
790 | } | 811 | } |
791 | GenericPredicate::Error => write!(f, "{{error}}")?, | 812 | WhereClause::AliasEq(_) => write!(f, "{{error}}")?, |
792 | } | 813 | } |
793 | Ok(()) | 814 | Ok(()) |
794 | } | 815 | } |
@@ -807,19 +828,12 @@ impl HirDisplay for Lifetime { | |||
807 | } | 828 | } |
808 | } | 829 | } |
809 | 830 | ||
810 | impl HirDisplay for Obligation { | 831 | impl HirDisplay for DomainGoal { |
811 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 832 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
812 | match self { | 833 | match self { |
813 | Obligation::Trait(tr) => { | 834 | DomainGoal::Holds(wc) => { |
814 | write!(f, "Implements(")?; | 835 | write!(f, "Holds(")?; |
815 | tr.hir_fmt(f)?; | 836 | wc.hir_fmt(f)?; |
816 | write!(f, ")") | ||
817 | } | ||
818 | Obligation::Projection(proj) => { | ||
819 | write!(f, "Normalize(")?; | ||
820 | proj.projection_ty.hir_fmt(f)?; | ||
821 | write!(f, " => ")?; | ||
822 | proj.ty.hir_fmt(f)?; | ||
823 | write!(f, ")") | 837 | write!(f, ")") |
824 | } | 838 | } |
825 | } | 839 | } |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 2610c9279..8f9cf7480 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -18,7 +18,7 @@ use std::mem; | |||
18 | use std::ops::Index; | 18 | use std::ops::Index; |
19 | use std::sync::Arc; | 19 | use std::sync::Arc; |
20 | 20 | ||
21 | use chalk_ir::Mutability; | 21 | use chalk_ir::{cast::Cast, Mutability}; |
22 | use hir_def::{ | 22 | use hir_def::{ |
23 | body::Body, | 23 | body::Body, |
24 | data::{ConstData, FunctionData, StaticData}, | 24 | data::{ConstData, FunctionData, StaticData}, |
@@ -37,12 +37,12 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{Guidance, Obligation, ProjectionPredicate, Solution}, | 40 | traits::{DomainGoal, Guidance, Solution}, |
41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, | 41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, |
45 | to_assoc_type_id, AliasTy, Interner, TyKind, | 45 | to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | pub(crate) use unify::unify; | 48 | pub(crate) use unify::unify; |
@@ -204,7 +204,7 @@ struct InferenceContext<'a> { | |||
204 | resolver: Resolver, | 204 | resolver: Resolver, |
205 | table: unify::InferenceTable, | 205 | table: unify::InferenceTable, |
206 | trait_env: Arc<TraitEnvironment>, | 206 | trait_env: Arc<TraitEnvironment>, |
207 | obligations: Vec<Obligation>, | 207 | obligations: Vec<DomainGoal>, |
208 | result: InferenceResult, | 208 | result: InferenceResult, |
209 | /// The return type of the function being inferred, or the closure if we're | 209 | /// The return type of the function being inferred, or the closure if we're |
210 | /// currently within one. | 210 | /// currently within one. |
@@ -331,7 +331,7 @@ impl<'a> InferenceContext<'a> { | |||
331 | fn resolve_obligations_as_possible(&mut self) { | 331 | fn resolve_obligations_as_possible(&mut self) { |
332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 332 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
333 | for obligation in obligations { | 333 | for obligation in obligations { |
334 | let in_env = InEnvironment::new(self.trait_env.clone(), obligation.clone()); | 334 | let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); |
335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); | 335 | let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); |
336 | let solution = | 336 | let solution = |
337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); | 337 | self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); |
@@ -394,16 +394,17 @@ impl<'a> InferenceContext<'a> { | |||
394 | .push(inner_ty) | 394 | .push(inner_ty) |
395 | .fill(params.iter().cloned()) | 395 | .fill(params.iter().cloned()) |
396 | .build(); | 396 | .build(); |
397 | let trait_ref = TraitRef { trait_, substs: substs.clone() }; | 397 | let trait_ref = |
398 | let projection = ProjectionPredicate { | 398 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; |
399 | ty: ty.clone(), | 399 | let alias_eq = AliasEq { |
400 | projection_ty: ProjectionTy { | 400 | alias: AliasTy::Projection(ProjectionTy { |
401 | associated_ty_id: to_assoc_type_id(res_assoc_ty), | 401 | associated_ty_id: to_assoc_type_id(res_assoc_ty), |
402 | substitution: substs, | 402 | substitution: substs, |
403 | }, | 403 | }), |
404 | ty: ty.clone(), | ||
404 | }; | 405 | }; |
405 | self.obligations.push(Obligation::Trait(trait_ref)); | 406 | self.obligations.push(trait_ref.cast(&Interner)); |
406 | self.obligations.push(Obligation::Projection(projection)); | 407 | self.obligations.push(alias_eq.cast(&Interner)); |
407 | self.resolve_ty_as_possible(ty) | 408 | self.resolve_ty_as_possible(ty) |
408 | } | 409 | } |
409 | None => self.err_ty(), | 410 | None => self.err_ty(), |
@@ -428,8 +429,8 @@ impl<'a> InferenceContext<'a> { | |||
428 | 429 | ||
429 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { | 430 | fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { |
430 | let var = self.table.new_type_var(); | 431 | let var = self.table.new_type_var(); |
431 | let predicate = ProjectionPredicate { projection_ty: proj_ty, ty: var.clone() }; | 432 | let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; |
432 | let obligation = Obligation::Projection(predicate); | 433 | let obligation = alias_eq.cast(&Interner); |
433 | self.obligations.push(obligation); | 434 | self.obligations.push(obligation); |
434 | var | 435 | var |
435 | } | 436 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index b1f98c507..9c62932b1 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -4,11 +4,11 @@ | |||
4 | //! | 4 | //! |
5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html | 5 | //! See: https://doc.rust-lang.org/nomicon/coercions.html |
6 | 6 | ||
7 | use chalk_ir::{Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | autoderef, traits::Solution, Interner, Obligation, Substitution, TraitRef, Ty, TyKind, | 11 | autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | use super::{InEnvironment, InferenceContext}; | 14 | use super::{InEnvironment, InferenceContext}; |
@@ -140,8 +140,9 @@ impl<'a> InferenceContext<'a> { | |||
140 | .push(from_ty.clone()) | 140 | .push(from_ty.clone()) |
141 | .push(to_ty.clone()) | 141 | .push(to_ty.clone()) |
142 | .build(); | 142 | .build(); |
143 | let trait_ref = TraitRef { trait_: coerce_unsized_trait, substs }; | 143 | let trait_ref = |
144 | let goal = InEnvironment::new(self.trait_env.clone(), Obligation::Trait(trait_ref)); | 144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; |
145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); | ||
145 | 146 | ||
146 | let canonicalizer = self.canonicalizer(); | 147 | let canonicalizer = self.canonicalizer(); |
147 | let canonicalized = canonicalizer.canonicalize_obligation(goal); | 148 | let canonicalized = canonicalizer.canonicalize_obligation(goal); |
@@ -169,8 +170,8 @@ impl<'a> InferenceContext<'a> { | |||
169 | self.db, | 170 | self.db, |
170 | self.resolver.krate(), | 171 | self.resolver.krate(), |
171 | InEnvironment { | 172 | InEnvironment { |
172 | value: canonicalized.value.clone(), | 173 | goal: canonicalized.value.clone(), |
173 | environment: self.trait_env.clone(), | 174 | environment: self.trait_env.env.clone(), |
174 | }, | 175 | }, |
175 | ) { | 176 | ) { |
176 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); | 177 | let derefed_ty = canonicalized.decanonicalize_ty(derefed_ty.value); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index 0be8c5a90..19249973c 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -3,7 +3,7 @@ | |||
3 | use std::iter::{repeat, repeat_with}; | 3 | use std::iter::{repeat, repeat_with}; |
4 | use std::{mem, sync::Arc}; | 4 | use std::{mem, sync::Arc}; |
5 | 5 | ||
6 | use chalk_ir::{Mutability, TyVariableKind}; | 6 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
7 | use hir_def::{ | 7 | use hir_def::{ |
8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, | 8 | expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, |
9 | path::{GenericArg, GenericArgs}, | 9 | path::{GenericArg, GenericArgs}, |
@@ -11,6 +11,7 @@ use hir_def::{ | |||
11 | AssocContainerId, FieldId, Lookup, | 11 | AssocContainerId, FieldId, Lookup, |
12 | }; | 12 | }; |
13 | use hir_expand::name::{name, Name}; | 13 | use hir_expand::name::{name, Name}; |
14 | use stdx::always; | ||
14 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
15 | 16 | ||
16 | use crate::{ | 17 | use crate::{ |
@@ -18,10 +19,10 @@ use crate::{ | |||
18 | lower::lower_to_chalk_mutability, | 19 | lower::lower_to_chalk_mutability, |
19 | method_resolution, op, | 20 | method_resolution, op, |
20 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
21 | to_assoc_type_id, | 22 | to_assoc_type_id, to_chalk_trait_id, |
22 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, | 23 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, |
23 | utils::{generics, variant_data, Generics}, | 24 | utils::{generics, variant_data, Generics}, |
24 | AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Obligation, Rawness, Scalar, | 25 | AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, |
25 | Substitution, TraitRef, Ty, TyKind, | 26 | Substitution, TraitRef, Ty, TyKind, |
26 | }; | 27 | }; |
27 | 28 | ||
@@ -89,11 +90,12 @@ impl<'a> InferenceContext<'a> { | |||
89 | let substs = | 90 | let substs = |
90 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); |
91 | 92 | ||
92 | let trait_env = Arc::clone(&self.trait_env); | 93 | let trait_env = self.trait_env.env.clone(); |
93 | let implements_fn_trait = | 94 | let implements_fn_trait: DomainGoal = |
94 | Obligation::Trait(TraitRef { trait_: fn_once_trait, substs: substs.clone() }); | 95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } |
96 | .cast(&Interner); | ||
95 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | 97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { |
96 | value: implements_fn_trait.clone(), | 98 | goal: implements_fn_trait.clone(), |
97 | environment: trait_env, | 99 | environment: trait_env, |
98 | }); | 100 | }); |
99 | if self.db.trait_solve(krate, goal.value).is_some() { | 101 | if self.db.trait_solve(krate, goal.value).is_some() { |
@@ -297,8 +299,8 @@ impl<'a> InferenceContext<'a> { | |||
297 | self.db, | 299 | self.db, |
298 | self.resolver.krate(), | 300 | self.resolver.krate(), |
299 | InEnvironment { | 301 | InEnvironment { |
300 | value: canonicalized.value.clone(), | 302 | goal: canonicalized.value.clone(), |
301 | environment: self.trait_env.clone(), | 303 | environment: self.trait_env.env.clone(), |
302 | }, | 304 | }, |
303 | ); | 305 | ); |
304 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs | 306 | let (param_tys, ret_ty): (Vec<Ty>, Ty) = derefs |
@@ -436,8 +438,8 @@ impl<'a> InferenceContext<'a> { | |||
436 | self.db, | 438 | self.db, |
437 | self.resolver.krate(), | 439 | self.resolver.krate(), |
438 | InEnvironment { | 440 | InEnvironment { |
439 | value: canonicalized.value.clone(), | 441 | goal: canonicalized.value.clone(), |
440 | environment: self.trait_env.clone(), | 442 | environment: self.trait_env.env.clone(), |
441 | }, | 443 | }, |
442 | ) | 444 | ) |
443 | .find_map(|derefed_ty| { | 445 | .find_map(|derefed_ty| { |
@@ -512,10 +514,10 @@ impl<'a> InferenceContext<'a> { | |||
512 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 514 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
513 | if let Some(box_) = self.resolve_boxed_box() { | 515 | if let Some(box_) = self.resolve_boxed_box() { |
514 | let mut sb = | 516 | let mut sb = |
515 | Substitution::builder(generics(self.db.upcast(), box_.into()).len()); | 517 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); |
516 | sb = sb.push(inner_ty); | 518 | sb = sb.push(inner_ty); |
517 | match self.db.generic_defaults(box_.into()).as_ref() { | 519 | match self.db.generic_defaults(box_.into()).get(1) { |
518 | [_, alloc_ty, ..] if !alloc_ty.value.is_unknown() => { | 520 | Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { |
519 | sb = sb.push(alloc_ty.value.clone()); | 521 | sb = sb.push(alloc_ty.value.clone()); |
520 | } | 522 | } |
521 | _ => (), | 523 | _ => (), |
@@ -536,8 +538,8 @@ impl<'a> InferenceContext<'a> { | |||
536 | self.db, | 538 | self.db, |
537 | krate, | 539 | krate, |
538 | InEnvironment { | 540 | InEnvironment { |
539 | value: &canonicalized.value, | 541 | goal: &canonicalized.value, |
540 | environment: self.trait_env.clone(), | 542 | environment: self.trait_env.env.clone(), |
541 | }, | 543 | }, |
542 | ) { | 544 | ) { |
543 | Some(derefed_ty) => { | 545 | Some(derefed_ty) => { |
@@ -935,20 +937,23 @@ impl<'a> InferenceContext<'a> { | |||
935 | let def: CallableDefId = from_chalk(self.db, *fn_def); | 937 | let def: CallableDefId = from_chalk(self.db, *fn_def); |
936 | let generic_predicates = self.db.generic_predicates(def.into()); | 938 | let generic_predicates = self.db.generic_predicates(def.into()); |
937 | for predicate in generic_predicates.iter() { | 939 | for predicate in generic_predicates.iter() { |
938 | let predicate = predicate.clone().subst(parameters); | 940 | let (predicate, binders) = |
939 | if let Some(obligation) = Obligation::from_predicate(predicate) { | 941 | predicate.clone().subst(parameters).into_value_and_skipped_binders(); |
940 | self.obligations.push(obligation); | 942 | always!(binders == 0); // quantified where clauses not yet handled |
941 | } | 943 | self.obligations.push(predicate.cast(&Interner)); |
942 | } | 944 | } |
943 | // add obligation for trait implementation, if this is a trait method | 945 | // add obligation for trait implementation, if this is a trait method |
944 | match def { | 946 | match def { |
945 | CallableDefId::FunctionId(f) => { | 947 | CallableDefId::FunctionId(f) => { |
946 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container | 948 | if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container |
947 | { | 949 | { |
948 | // construct a TraitDef | 950 | // construct a TraitRef |
949 | let substs = | 951 | let substs = |
950 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); | 952 | parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); |
951 | self.obligations.push(Obligation::Trait(TraitRef { trait_, substs })); | 953 | self.obligations.push( |
954 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } | ||
955 | .cast(&Interner), | ||
956 | ); | ||
952 | } | 957 | } |
953 | } | 958 | } |
954 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} | 959 | CallableDefId::StructId(_) | CallableDefId::EnumVariantId(_) => {} |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index befa0d69b..474363709 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,7 +13,9 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyKind, | 16 | lower::lower_to_chalk_mutability, |
17 | utils::{generics, variant_data}, | ||
18 | Interner, Substitution, Ty, TyKind, | ||
17 | }; | 19 | }; |
18 | 20 | ||
19 | impl<'a> InferenceContext<'a> { | 21 | impl<'a> InferenceContext<'a> { |
@@ -38,7 +40,7 @@ impl<'a> InferenceContext<'a> { | |||
38 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); | 40 | let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); |
39 | let (pre, post) = match ellipsis { | 41 | let (pre, post) = match ellipsis { |
40 | Some(idx) => subpats.split_at(idx), | 42 | Some(idx) => subpats.split_at(idx), |
41 | None => (&subpats[..], &[][..]), | 43 | None => (subpats, &[][..]), |
42 | }; | 44 | }; |
43 | let post_idx_offset = field_tys.iter().count() - post.len(); | 45 | let post_idx_offset = field_tys.iter().count() - post.len(); |
44 | 46 | ||
@@ -233,13 +235,31 @@ impl<'a> InferenceContext<'a> { | |||
233 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), | 235 | Pat::Lit(expr) => self.infer_expr(*expr, &Expectation::has_type(expected.clone())), |
234 | Pat::Box { inner } => match self.resolve_boxed_box() { | 236 | Pat::Box { inner } => match self.resolve_boxed_box() { |
235 | Some(box_adt) => { | 237 | Some(box_adt) => { |
236 | let inner_expected = match expected.as_adt() { | 238 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
237 | Some((adt, substs)) if adt == box_adt => substs.as_single().clone(), | 239 | Some((adt, subst)) if adt == box_adt => { |
238 | _ => self.result.standard_types.unknown.clone(), | 240 | (subst[0].clone(), subst.get(1).cloned()) |
241 | } | ||
242 | _ => (self.result.standard_types.unknown.clone(), None), | ||
239 | }; | 243 | }; |
240 | 244 | ||
241 | let inner_ty = self.infer_pat(*inner, &inner_expected, default_bm); | 245 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
242 | Ty::adt_ty(box_adt, Substitution::single(inner_ty)) | 246 | let mut sb = Substitution::build_for_generics(&generics( |
247 | self.db.upcast(), | ||
248 | box_adt.into(), | ||
249 | )); | ||
250 | sb = sb.push(inner_ty); | ||
251 | if sb.remaining() == 1 { | ||
252 | sb = sb.push(match alloc_ty { | ||
253 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
254 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
255 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
256 | alloc_ty.value.clone() | ||
257 | } | ||
258 | _ => self.table.new_type_var(), | ||
259 | }, | ||
260 | }); | ||
261 | } | ||
262 | Ty::adt_ty(box_adt, sb.build()) | ||
243 | } | 263 | } |
244 | None => self.err_ty(), | 264 | None => self.err_ty(), |
245 | }, | 265 | }, |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index ea01d6238..58cce56ab 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | use std::iter; | 3 | use std::iter; |
4 | 4 | ||
5 | use chalk_ir::cast::Cast; | ||
5 | use hir_def::{ | 6 | use hir_def::{ |
6 | path::{Path, PathSegment}, | 7 | path::{Path, PathSegment}, |
7 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, | 8 | resolver::{ResolveValueResult, Resolver, TypeNs, ValueNs}, |
@@ -9,7 +10,9 @@ use hir_def::{ | |||
9 | }; | 10 | }; |
10 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
11 | 12 | ||
12 | use crate::{method_resolution, Interner, Substitution, Ty, TyKind, ValueTyDefId}; | 13 | use crate::{ |
14 | method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId, | ||
15 | }; | ||
13 | 16 | ||
14 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 17 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
15 | 18 | ||
@@ -165,7 +168,7 @@ impl<'a> InferenceContext<'a> { | |||
165 | segment: PathSegment<'_>, | 168 | segment: PathSegment<'_>, |
166 | id: ExprOrPatId, | 169 | id: ExprOrPatId, |
167 | ) -> Option<(ValueNs, Option<Substitution>)> { | 170 | ) -> Option<(ValueNs, Option<Substitution>)> { |
168 | let trait_ = trait_ref.trait_; | 171 | let trait_ = trait_ref.hir_trait_id(); |
169 | let item = | 172 | let item = |
170 | self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id)).find_map(|item| { | 173 | self.db.trait_data(trait_).items.iter().map(|(_name, id)| (*id)).find_map(|item| { |
171 | match item { | 174 | match item { |
@@ -200,7 +203,7 @@ impl<'a> InferenceContext<'a> { | |||
200 | }; | 203 | }; |
201 | 204 | ||
202 | self.write_assoc_resolution(id, item); | 205 | self.write_assoc_resolution(id, item); |
203 | Some((def, Some(trait_ref.substs))) | 206 | Some((def, Some(trait_ref.substitution))) |
204 | } | 207 | } |
205 | 208 | ||
206 | fn resolve_ty_assoc_item( | 209 | fn resolve_ty_assoc_item( |
@@ -254,10 +257,13 @@ impl<'a> InferenceContext<'a> { | |||
254 | .push(ty.clone()) | 257 | .push(ty.clone()) |
255 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 258 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
256 | .build(); | 259 | .build(); |
257 | self.obligations.push(super::Obligation::Trait(TraitRef { | 260 | self.obligations.push( |
258 | trait_, | 261 | TraitRef { |
259 | substs: trait_substs.clone(), | 262 | trait_id: to_chalk_trait_id(trait_), |
260 | })); | 263 | substitution: trait_substs.clone(), |
264 | } | ||
265 | .cast(&Interner), | ||
266 | ); | ||
261 | Some(trait_substs) | 267 | Some(trait_substs) |
262 | } | 268 | } |
263 | AssocContainerId::ModuleId(_) => None, | 269 | AssocContainerId::ModuleId(_) => None, |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index b2d4f67b3..75250a369 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -2,13 +2,13 @@ | |||
2 | 2 | ||
3 | use std::borrow::Cow; | 3 | use std::borrow::Cow; |
4 | 4 | ||
5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind}; | 5 | use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; |
6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; | 6 | use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; |
7 | 7 | ||
8 | use super::{InferenceContext, Obligation}; | 8 | use super::{DomainGoal, InferenceContext}; |
9 | use crate::{ | 9 | use crate::{ |
10 | BoundVar, Canonical, DebruijnIndex, FnPointer, GenericPredicate, InEnvironment, InferenceVar, | 10 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, |
11 | Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, | 11 | InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, |
12 | }; | 12 | }; |
13 | 13 | ||
14 | impl<'a> InferenceContext<'a> { | 14 | impl<'a> InferenceContext<'a> { |
@@ -76,8 +76,17 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
76 | } | 76 | } |
77 | 77 | ||
78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { | 78 | fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { |
79 | let kinds = self.free_vars.iter().map(|&(_, k)| k).collect(); | 79 | let kinds = self |
80 | Canonicalized { value: Canonical { value: result, kinds }, free_vars: self.free_vars } | 80 | .free_vars |
81 | .iter() | ||
82 | .map(|&(_, k)| chalk_ir::WithKind::new(VariableKind::Ty(k), UniverseIndex::ROOT)); | ||
83 | Canonicalized { | ||
84 | value: Canonical { | ||
85 | value: result, | ||
86 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
87 | }, | ||
88 | free_vars: self.free_vars, | ||
89 | } | ||
81 | } | 90 | } |
82 | 91 | ||
83 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { | 92 | pub(crate) fn canonicalize_ty(mut self, ty: Ty) -> Canonicalized<Ty> { |
@@ -87,20 +96,14 @@ impl<'a, 'b> Canonicalizer<'a, 'b> { | |||
87 | 96 | ||
88 | pub(crate) fn canonicalize_obligation( | 97 | pub(crate) fn canonicalize_obligation( |
89 | mut self, | 98 | mut self, |
90 | obligation: InEnvironment<Obligation>, | 99 | obligation: InEnvironment<DomainGoal>, |
91 | ) -> Canonicalized<InEnvironment<Obligation>> { | 100 | ) -> Canonicalized<InEnvironment<DomainGoal>> { |
92 | let result = match obligation.value { | 101 | let result = match obligation.goal { |
93 | Obligation::Trait(tr) => { | 102 | DomainGoal::Holds(wc) => { |
94 | Obligation::Trait(self.do_canonicalize(tr, DebruijnIndex::INNERMOST)) | 103 | DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) |
95 | } | ||
96 | Obligation::Projection(pr) => { | ||
97 | Obligation::Projection(self.do_canonicalize(pr, DebruijnIndex::INNERMOST)) | ||
98 | } | 104 | } |
99 | }; | 105 | }; |
100 | self.into_canonicalized(InEnvironment { | 106 | self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) |
101 | value: result, | ||
102 | environment: obligation.environment, | ||
103 | }) | ||
104 | } | 107 | } |
105 | } | 108 | } |
106 | 109 | ||
@@ -128,12 +131,19 @@ impl<T> Canonicalized<T> { | |||
128 | // the solution may contain new variables, which we need to convert to new inference vars | 131 | // the solution may contain new variables, which we need to convert to new inference vars |
129 | let new_vars = Substitution( | 132 | let new_vars = Substitution( |
130 | solution | 133 | solution |
131 | .kinds | 134 | .binders |
132 | .iter() | 135 | .iter(&Interner) |
133 | .map(|k| match k { | 136 | .map(|k| match k.kind { |
134 | TyVariableKind::General => ctx.table.new_type_var(), | 137 | VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), |
135 | TyVariableKind::Integer => ctx.table.new_integer_var(), | 138 | VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), |
136 | TyVariableKind::Float => ctx.table.new_float_var(), | 139 | VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), |
140 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
141 | // want to just skip them, but to not mess up the indices of | ||
142 | // other variables, we'll just create a new type variable in | ||
143 | // their place instead. This should not matter (we never see the | ||
144 | // actual *uses* of the lifetime variable). | ||
145 | VariableKind::Lifetime => ctx.table.new_type_var(), | ||
146 | _ => panic!("const variable in solution"), | ||
137 | }) | 147 | }) |
138 | .collect(), | 148 | .collect(), |
139 | ); | 149 | ); |
@@ -150,8 +160,8 @@ impl<T> Canonicalized<T> { | |||
150 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | 160 | pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { |
151 | let mut table = InferenceTable::new(); | 161 | let mut table = InferenceTable::new(); |
152 | let vars = Substitution( | 162 | let vars = Substitution( |
153 | tys.kinds | 163 | tys.binders |
154 | .iter() | 164 | .iter(&Interner) |
155 | // we always use type vars here because we want everything to | 165 | // we always use type vars here because we want everything to |
156 | // fallback to Unknown in the end (kind of hacky, as below) | 166 | // fallback to Unknown in the end (kind of hacky, as below) |
157 | .map(|_| table.new_type_var()) | 167 | .map(|_| table.new_type_var()) |
@@ -173,7 +183,7 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
173 | } | 183 | } |
174 | } | 184 | } |
175 | Some( | 185 | Some( |
176 | Substitution::builder(tys.kinds.len()) | 186 | Substitution::builder(tys.binders.len(&Interner)) |
177 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) | 187 | .fill(vars.iter().map(|v| table.resolve_ty_completely(v.clone()))) |
178 | .build(), | 188 | .build(), |
179 | ) | 189 | ) |
@@ -313,9 +323,18 @@ impl InferenceTable { | |||
313 | 323 | ||
314 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, | 324 | (TyKind::Placeholder(p1), TyKind::Placeholder(p2)) if *p1 == *p2 => true, |
315 | 325 | ||
316 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) if dyn1.len() == dyn2.len() => { | 326 | (TyKind::Dyn(dyn1), TyKind::Dyn(dyn2)) |
317 | for (pred1, pred2) in dyn1.iter().zip(dyn2.iter()) { | 327 | if dyn1.bounds.skip_binders().interned().len() |
318 | if !self.unify_preds(pred1, pred2, depth + 1) { | 328 | == dyn2.bounds.skip_binders().interned().len() => |
329 | { | ||
330 | for (pred1, pred2) in dyn1 | ||
331 | .bounds | ||
332 | .skip_binders() | ||
333 | .interned() | ||
334 | .iter() | ||
335 | .zip(dyn2.bounds.skip_binders().interned().iter()) | ||
336 | { | ||
337 | if !self.unify_preds(pred1.skip_binders(), pred2.skip_binders(), depth + 1) { | ||
319 | return false; | 338 | return false; |
320 | } | 339 | } |
321 | } | 340 | } |
@@ -382,26 +401,32 @@ impl InferenceTable { | |||
382 | } | 401 | } |
383 | } | 402 | } |
384 | 403 | ||
385 | fn unify_preds( | 404 | fn unify_preds(&mut self, pred1: &WhereClause, pred2: &WhereClause, depth: usize) -> bool { |
386 | &mut self, | ||
387 | pred1: &GenericPredicate, | ||
388 | pred2: &GenericPredicate, | ||
389 | depth: usize, | ||
390 | ) -> bool { | ||
391 | match (pred1, pred2) { | 405 | match (pred1, pred2) { |
392 | (GenericPredicate::Implemented(tr1), GenericPredicate::Implemented(tr2)) | 406 | (WhereClause::Implemented(tr1), WhereClause::Implemented(tr2)) |
393 | if tr1.trait_ == tr2.trait_ => | 407 | if tr1.trait_id == tr2.trait_id => |
394 | { | 408 | { |
395 | self.unify_substs(&tr1.substs, &tr2.substs, depth + 1) | 409 | self.unify_substs(&tr1.substitution, &tr2.substitution, depth + 1) |
396 | } | 410 | } |
397 | (GenericPredicate::Projection(proj1), GenericPredicate::Projection(proj2)) | 411 | ( |
398 | if proj1.projection_ty.associated_ty_id == proj2.projection_ty.associated_ty_id => | 412 | WhereClause::AliasEq(AliasEq { alias: alias1, ty: ty1 }), |
399 | { | 413 | WhereClause::AliasEq(AliasEq { alias: alias2, ty: ty2 }), |
400 | self.unify_substs( | 414 | ) => { |
401 | &proj1.projection_ty.substitution, | 415 | let (substitution1, substitution2) = match (alias1, alias2) { |
402 | &proj2.projection_ty.substitution, | 416 | (AliasTy::Projection(projection_ty1), AliasTy::Projection(projection_ty2)) |
403 | depth + 1, | 417 | if projection_ty1.associated_ty_id == projection_ty2.associated_ty_id => |
404 | ) && self.unify_inner(&proj1.ty, &proj2.ty, depth + 1) | 418 | { |
419 | (&projection_ty1.substitution, &projection_ty2.substitution) | ||
420 | } | ||
421 | (AliasTy::Opaque(opaque1), AliasTy::Opaque(opaque2)) | ||
422 | if opaque1.opaque_ty_id == opaque2.opaque_ty_id => | ||
423 | { | ||
424 | (&opaque1.substitution, &opaque2.substitution) | ||
425 | } | ||
426 | _ => return false, | ||
427 | }; | ||
428 | self.unify_substs(&substitution1, &substitution2, depth + 1) | ||
429 | && self.unify_inner(&ty1, &ty2, depth + 1) | ||
405 | } | 430 | } |
406 | _ => false, | 431 | _ => false, |
407 | } | 432 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 52b498ff7..0f49dd39b 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -13,6 +13,7 @@ mod op; | |||
13 | mod lower; | 13 | mod lower; |
14 | pub(crate) mod infer; | 14 | pub(crate) mod infer; |
15 | pub(crate) mod utils; | 15 | pub(crate) mod utils; |
16 | mod chalk_cast; | ||
16 | 17 | ||
17 | pub mod display; | 18 | pub mod display; |
18 | pub mod db; | 19 | pub mod db; |
@@ -45,9 +46,11 @@ pub use lower::{ | |||
45 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 46 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
46 | TyDefId, TyLoweringContext, ValueTyDefId, | 47 | TyDefId, TyLoweringContext, ValueTyDefId, |
47 | }; | 48 | }; |
48 | pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; | 49 | pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; |
49 | 50 | ||
50 | pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; | 51 | pub use chalk_ir::{ |
52 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | ||
53 | }; | ||
51 | 54 | ||
52 | pub use crate::traits::chalk::Interner; | 55 | pub use crate::traits::chalk::Interner; |
53 | 56 | ||
@@ -58,6 +61,10 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>; | |||
58 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; | 61 | pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; |
59 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; | 62 | pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; |
60 | 63 | ||
64 | pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | ||
65 | |||
66 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | ||
67 | |||
61 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 68 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
62 | pub enum Lifetime { | 69 | pub enum Lifetime { |
63 | Parameter(LifetimeParamId), | 70 | Parameter(LifetimeParamId), |
@@ -70,6 +77,20 @@ pub struct OpaqueTy { | |||
70 | pub substitution: Substitution, | 77 | pub substitution: Substitution, |
71 | } | 78 | } |
72 | 79 | ||
80 | impl TypeWalk for OpaqueTy { | ||
81 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
82 | self.substitution.walk(f); | ||
83 | } | ||
84 | |||
85 | fn walk_mut_binders( | ||
86 | &mut self, | ||
87 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
88 | binders: DebruijnIndex, | ||
89 | ) { | ||
90 | self.substitution.walk_mut_binders(f, binders); | ||
91 | } | ||
92 | } | ||
93 | |||
73 | /// A "projection" type corresponds to an (unnormalized) | 94 | /// A "projection" type corresponds to an (unnormalized) |
74 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | 95 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the |
75 | /// trait and all its parameters are fully known. | 96 | /// trait and all its parameters are fully known. |
@@ -81,7 +102,14 @@ pub struct ProjectionTy { | |||
81 | 102 | ||
82 | impl ProjectionTy { | 103 | impl ProjectionTy { |
83 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { | 104 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { |
84 | TraitRef { trait_: self.trait_(db), substs: self.substitution.clone() } | 105 | TraitRef { |
106 | trait_id: to_chalk_trait_id(self.trait_(db)), | ||
107 | substitution: self.substitution.clone(), | ||
108 | } | ||
109 | } | ||
110 | |||
111 | pub fn self_type_parameter(&self) -> &Ty { | ||
112 | &self.substitution[0] | ||
85 | } | 113 | } |
86 | 114 | ||
87 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 115 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
@@ -106,6 +134,12 @@ impl TypeWalk for ProjectionTy { | |||
106 | } | 134 | } |
107 | } | 135 | } |
108 | 136 | ||
137 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
138 | pub struct DynTy { | ||
139 | /// The unknown self type. | ||
140 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
141 | } | ||
142 | |||
109 | pub type FnSig = chalk_ir::FnSig<Interner>; | 143 | pub type FnSig = chalk_ir::FnSig<Interner>; |
110 | 144 | ||
111 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 145 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
@@ -128,6 +162,25 @@ pub enum AliasTy { | |||
128 | Opaque(OpaqueTy), | 162 | Opaque(OpaqueTy), |
129 | } | 163 | } |
130 | 164 | ||
165 | impl TypeWalk for AliasTy { | ||
166 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
167 | match self { | ||
168 | AliasTy::Projection(it) => it.walk(f), | ||
169 | AliasTy::Opaque(it) => it.walk(f), | ||
170 | } | ||
171 | } | ||
172 | |||
173 | fn walk_mut_binders( | ||
174 | &mut self, | ||
175 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
176 | binders: DebruijnIndex, | ||
177 | ) { | ||
178 | match self { | ||
179 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
180 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
181 | } | ||
182 | } | ||
183 | } | ||
131 | /// A type. | 184 | /// A type. |
132 | /// | 185 | /// |
133 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | 186 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents |
@@ -238,7 +291,7 @@ pub enum TyKind { | |||
238 | /// represents the `Self` type inside the bounds. This is currently | 291 | /// represents the `Self` type inside the bounds. This is currently |
239 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | 292 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it |
240 | /// didn't seem worth the overhead yet. | 293 | /// didn't seem worth the overhead yet. |
241 | Dyn(Arc<[GenericPredicate]>), | 294 | Dyn(DynTy), |
242 | 295 | ||
243 | /// A placeholder for a type which could not be computed; this is propagated | 296 | /// A placeholder for a type which could not be computed; this is propagated |
244 | /// to avoid useless error messages. Doubles as a placeholder where type | 297 | /// to avoid useless error messages. Doubles as a placeholder where type |
@@ -445,6 +498,13 @@ impl<T> Binders<T> { | |||
445 | Self { num_binders, value } | 498 | Self { num_binders, value } |
446 | } | 499 | } |
447 | 500 | ||
501 | pub fn wrap_empty(value: T) -> Self | ||
502 | where | ||
503 | T: TypeWalk, | ||
504 | { | ||
505 | Self { num_binders: 0, value: value.shift_bound_vars(DebruijnIndex::ONE) } | ||
506 | } | ||
507 | |||
448 | pub fn as_ref(&self) -> Binders<&T> { | 508 | pub fn as_ref(&self) -> Binders<&T> { |
449 | Binders { num_binders: self.num_binders, value: &self.value } | 509 | Binders { num_binders: self.num_binders, value: &self.value } |
450 | } | 510 | } |
@@ -456,6 +516,14 @@ impl<T> Binders<T> { | |||
456 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { | 516 | pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> { |
457 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) | 517 | Some(Binders { num_binders: self.num_binders, value: f(self.value)? }) |
458 | } | 518 | } |
519 | |||
520 | pub fn skip_binders(&self) -> &T { | ||
521 | &self.value | ||
522 | } | ||
523 | |||
524 | pub fn into_value_and_skipped_binders(self) -> (T, usize) { | ||
525 | (self.value, self.num_binders) | ||
526 | } | ||
459 | } | 527 | } |
460 | 528 | ||
461 | impl<T: Clone> Binders<&T> { | 529 | impl<T: Clone> Binders<&T> { |
@@ -493,23 +561,25 @@ impl<T: TypeWalk> TypeWalk for Binders<T> { | |||
493 | } | 561 | } |
494 | 562 | ||
495 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | 563 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. |
496 | /// Name to be bikeshedded: TraitBound? TraitImplements? | ||
497 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 564 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
498 | pub struct TraitRef { | 565 | pub struct TraitRef { |
499 | /// FIXME name? | 566 | pub trait_id: ChalkTraitId, |
500 | pub trait_: TraitId, | 567 | pub substitution: Substitution, |
501 | pub substs: Substitution, | ||
502 | } | 568 | } |
503 | 569 | ||
504 | impl TraitRef { | 570 | impl TraitRef { |
505 | pub fn self_ty(&self) -> &Ty { | 571 | pub fn self_type_parameter(&self) -> &Ty { |
506 | &self.substs[0] | 572 | &self.substitution[0] |
573 | } | ||
574 | |||
575 | pub fn hir_trait_id(&self) -> TraitId { | ||
576 | from_chalk_trait_id(self.trait_id) | ||
507 | } | 577 | } |
508 | } | 578 | } |
509 | 579 | ||
510 | impl TypeWalk for TraitRef { | 580 | impl TypeWalk for TraitRef { |
511 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 581 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
512 | self.substs.walk(f); | 582 | self.substitution.walk(f); |
513 | } | 583 | } |
514 | 584 | ||
515 | fn walk_mut_binders( | 585 | fn walk_mut_binders( |
@@ -517,47 +587,41 @@ impl TypeWalk for TraitRef { | |||
517 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | 587 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), |
518 | binders: DebruijnIndex, | 588 | binders: DebruijnIndex, |
519 | ) { | 589 | ) { |
520 | self.substs.walk_mut_binders(f, binders); | 590 | self.substitution.walk_mut_binders(f, binders); |
521 | } | 591 | } |
522 | } | 592 | } |
523 | 593 | ||
524 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | 594 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the |
525 | /// parameters of a generic item. | 595 | /// parameters of a generic item. |
526 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 596 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
527 | pub enum GenericPredicate { | 597 | pub enum WhereClause { |
528 | /// The given trait needs to be implemented for its type parameters. | 598 | /// The given trait needs to be implemented for its type parameters. |
529 | Implemented(TraitRef), | 599 | Implemented(TraitRef), |
530 | /// An associated type bindings like in `Iterator<Item = T>`. | 600 | /// An associated type bindings like in `Iterator<Item = T>`. |
531 | Projection(ProjectionPredicate), | 601 | AliasEq(AliasEq), |
532 | /// We couldn't resolve the trait reference. (If some type parameters can't | ||
533 | /// be resolved, they will just be Unknown). | ||
534 | Error, | ||
535 | } | 602 | } |
536 | 603 | ||
537 | impl GenericPredicate { | 604 | impl WhereClause { |
538 | pub fn is_error(&self) -> bool { | ||
539 | matches!(self, GenericPredicate::Error) | ||
540 | } | ||
541 | |||
542 | pub fn is_implemented(&self) -> bool { | 605 | pub fn is_implemented(&self) -> bool { |
543 | matches!(self, GenericPredicate::Implemented(_)) | 606 | matches!(self, WhereClause::Implemented(_)) |
544 | } | 607 | } |
545 | 608 | ||
546 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { | 609 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> { |
547 | match self { | 610 | match self { |
548 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 611 | WhereClause::Implemented(tr) => Some(tr.clone()), |
549 | GenericPredicate::Projection(proj) => Some(proj.projection_ty.trait_ref(db)), | 612 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => { |
550 | GenericPredicate::Error => None, | 613 | Some(proj.trait_ref(db)) |
614 | } | ||
615 | WhereClause::AliasEq(_) => None, | ||
551 | } | 616 | } |
552 | } | 617 | } |
553 | } | 618 | } |
554 | 619 | ||
555 | impl TypeWalk for GenericPredicate { | 620 | impl TypeWalk for WhereClause { |
556 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 621 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
557 | match self { | 622 | match self { |
558 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk(f), | 623 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), |
559 | GenericPredicate::Projection(projection_pred) => projection_pred.walk(f), | 624 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), |
560 | GenericPredicate::Error => {} | ||
561 | } | 625 | } |
562 | } | 626 | } |
563 | 627 | ||
@@ -567,15 +631,30 @@ impl TypeWalk for GenericPredicate { | |||
567 | binders: DebruijnIndex, | 631 | binders: DebruijnIndex, |
568 | ) { | 632 | ) { |
569 | match self { | 633 | match self { |
570 | GenericPredicate::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | 634 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), |
571 | GenericPredicate::Projection(projection_pred) => { | 635 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), |
572 | projection_pred.walk_mut_binders(f, binders) | ||
573 | } | ||
574 | GenericPredicate::Error => {} | ||
575 | } | 636 | } |
576 | } | 637 | } |
577 | } | 638 | } |
578 | 639 | ||
640 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
641 | |||
642 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
643 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
644 | |||
645 | impl QuantifiedWhereClauses { | ||
646 | pub fn from_iter( | ||
647 | _interner: &Interner, | ||
648 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
649 | ) -> Self { | ||
650 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
651 | } | ||
652 | |||
653 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
654 | &self.0 | ||
655 | } | ||
656 | } | ||
657 | |||
579 | /// Basically a claim (currently not validated / checked) that the contained | 658 | /// Basically a claim (currently not validated / checked) that the contained |
580 | /// type / trait ref contains no inference variables; any inference variables it | 659 | /// type / trait ref contains no inference variables; any inference variables it |
581 | /// contained have been replaced by bound variables, and `kinds` tells us how | 660 | /// contained have been replaced by bound variables, and `kinds` tells us how |
@@ -585,12 +664,18 @@ impl TypeWalk for GenericPredicate { | |||
585 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 664 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
586 | pub struct Canonical<T> { | 665 | pub struct Canonical<T> { |
587 | pub value: T, | 666 | pub value: T, |
588 | pub kinds: Arc<[TyVariableKind]>, | 667 | pub binders: CanonicalVarKinds, |
589 | } | 668 | } |
590 | 669 | ||
591 | impl<T> Canonical<T> { | 670 | impl<T> Canonical<T> { |
592 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | 671 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
593 | Self { value, kinds: kinds.into_iter().collect() } | 672 | let kinds = kinds.into_iter().map(|tk| { |
673 | chalk_ir::CanonicalVarKind::new( | ||
674 | chalk_ir::VariableKind::Ty(tk), | ||
675 | chalk_ir::UniverseIndex::ROOT, | ||
676 | ) | ||
677 | }); | ||
678 | Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) } | ||
594 | } | 679 | } |
595 | } | 680 | } |
596 | 681 | ||
@@ -772,19 +857,21 @@ impl Ty { | |||
772 | } | 857 | } |
773 | 858 | ||
774 | /// If this is a `dyn Trait` type, this returns the `Trait` part. | 859 | /// If this is a `dyn Trait` type, this returns the `Trait` part. |
775 | pub fn dyn_trait_ref(&self) -> Option<&TraitRef> { | 860 | fn dyn_trait_ref(&self) -> Option<&TraitRef> { |
776 | match self.interned(&Interner) { | 861 | match self.interned(&Interner) { |
777 | TyKind::Dyn(bounds) => bounds.get(0).and_then(|b| match b { | 862 | TyKind::Dyn(dyn_ty) => { |
778 | GenericPredicate::Implemented(trait_ref) => Some(trait_ref), | 863 | dyn_ty.bounds.value.interned().get(0).and_then(|b| match b.skip_binders() { |
779 | _ => None, | 864 | WhereClause::Implemented(trait_ref) => Some(trait_ref), |
780 | }), | 865 | _ => None, |
866 | }) | ||
867 | } | ||
781 | _ => None, | 868 | _ => None, |
782 | } | 869 | } |
783 | } | 870 | } |
784 | 871 | ||
785 | /// If this is a `dyn Trait`, returns that trait. | 872 | /// If this is a `dyn Trait`, returns that trait. |
786 | pub fn dyn_trait(&self) -> Option<TraitId> { | 873 | pub fn dyn_trait(&self) -> Option<TraitId> { |
787 | self.dyn_trait_ref().map(|it| it.trait_) | 874 | self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id) |
788 | } | 875 | } |
789 | 876 | ||
790 | fn builtin_deref(&self) -> Option<Ty> { | 877 | fn builtin_deref(&self) -> Option<Ty> { |
@@ -854,7 +941,7 @@ impl Ty { | |||
854 | } | 941 | } |
855 | } | 942 | } |
856 | 943 | ||
857 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<GenericPredicate>> { | 944 | pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> { |
858 | match self.interned(&Interner) { | 945 | match self.interned(&Interner) { |
859 | TyKind::OpaqueType(opaque_ty_id, ..) => { | 946 | TyKind::OpaqueType(opaque_ty_id, ..) => { |
860 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { | 947 | match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) { |
@@ -867,10 +954,13 @@ impl Ty { | |||
867 | // This is only used by type walking. | 954 | // This is only used by type walking. |
868 | // Parameters will be walked outside, and projection predicate is not used. | 955 | // Parameters will be walked outside, and projection predicate is not used. |
869 | // So just provide the Future trait. | 956 | // So just provide the Future trait. |
870 | let impl_bound = GenericPredicate::Implemented(TraitRef { | 957 | let impl_bound = Binders::new( |
871 | trait_: future_trait, | 958 | 0, |
872 | substs: Substitution::empty(), | 959 | WhereClause::Implemented(TraitRef { |
873 | }); | 960 | trait_id: to_chalk_trait_id(future_trait), |
961 | substitution: Substitution::empty(), | ||
962 | }), | ||
963 | ); | ||
874 | Some(vec![impl_bound]) | 964 | Some(vec![impl_bound]) |
875 | } else { | 965 | } else { |
876 | None | 966 | None |
@@ -902,10 +992,19 @@ impl Ty { | |||
902 | let param_data = &generic_params.types[id.local_id]; | 992 | let param_data = &generic_params.types[id.local_id]; |
903 | match param_data.provenance { | 993 | match param_data.provenance { |
904 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 994 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
995 | let substs = Substitution::type_params(db, id.parent); | ||
905 | let predicates = db | 996 | let predicates = db |
906 | .generic_predicates_for_param(id) | 997 | .generic_predicates(id.parent) |
907 | .into_iter() | 998 | .into_iter() |
908 | .map(|pred| pred.value.clone()) | 999 | .map(|pred| pred.clone().subst(&substs)) |
1000 | .filter(|wc| match &wc.skip_binders() { | ||
1001 | WhereClause::Implemented(tr) => tr.self_type_parameter() == self, | ||
1002 | WhereClause::AliasEq(AliasEq { | ||
1003 | alias: AliasTy::Projection(proj), | ||
1004 | ty: _, | ||
1005 | }) => proj.self_type_parameter() == self, | ||
1006 | _ => false, | ||
1007 | }) | ||
909 | .collect_vec(); | 1008 | .collect_vec(); |
910 | 1009 | ||
911 | Some(predicates) | 1010 | Some(predicates) |
@@ -1047,8 +1146,8 @@ impl TypeWalk for Ty { | |||
1047 | t.walk(f); | 1146 | t.walk(f); |
1048 | } | 1147 | } |
1049 | } | 1148 | } |
1050 | TyKind::Dyn(predicates) => { | 1149 | TyKind::Dyn(dyn_ty) => { |
1051 | for p in predicates.iter() { | 1150 | for p in dyn_ty.bounds.value.interned().iter() { |
1052 | p.walk(f); | 1151 | p.walk(f); |
1053 | } | 1152 | } |
1054 | } | 1153 | } |
@@ -1075,8 +1174,8 @@ impl TypeWalk for Ty { | |||
1075 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | 1174 | TyKind::Alias(AliasTy::Projection(p_ty)) => { |
1076 | p_ty.substitution.walk_mut_binders(f, binders); | 1175 | p_ty.substitution.walk_mut_binders(f, binders); |
1077 | } | 1176 | } |
1078 | TyKind::Dyn(predicates) => { | 1177 | TyKind::Dyn(dyn_ty) => { |
1079 | for p in make_mut_slice(predicates) { | 1178 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { |
1080 | p.walk_mut_binders(f, binders.shifted_in()); | 1179 | p.walk_mut_binders(f, binders.shifted_in()); |
1081 | } | 1180 | } |
1082 | } | 1181 | } |
@@ -1126,7 +1225,7 @@ pub struct ReturnTypeImplTraits { | |||
1126 | 1225 | ||
1127 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | 1226 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
1128 | pub(crate) struct ReturnTypeImplTrait { | 1227 | pub(crate) struct ReturnTypeImplTrait { |
1129 | pub(crate) bounds: Binders<Vec<GenericPredicate>>, | 1228 | pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, |
1130 | } | 1229 | } |
1131 | 1230 | ||
1132 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { | 1231 | pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { |
@@ -1158,3 +1257,11 @@ pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderI | |||
1158 | idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), | 1257 | idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), |
1159 | } | 1258 | } |
1160 | } | 1259 | } |
1260 | |||
1261 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | ||
1262 | chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) | ||
1263 | } | ||
1264 | |||
1265 | pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { | ||
1266 | salsa::InternKey::from_intern_id(id.0) | ||
1267 | } | ||
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index 462882b2b..f60cec649 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -27,15 +27,16 @@ use stdx::impl_from; | |||
27 | 27 | ||
28 | use crate::{ | 28 | use crate::{ |
29 | db::HirDatabase, | 29 | db::HirDatabase, |
30 | to_assoc_type_id, to_placeholder_idx, | 30 | to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, |
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, |
35 | }, | 35 | }, |
36 | AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, FnPointer, FnSig, GenericPredicate, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionPredicate, ProjectionTy, ReturnTypeImplTrait, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -188,10 +189,14 @@ impl<'a> TyLoweringContext<'a> { | |||
188 | TypeRef::DynTrait(bounds) => { | 189 | TypeRef::DynTrait(bounds) => { |
189 | let self_ty = | 190 | let self_ty = |
190 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 191 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
191 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 192 | let bounds = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
192 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 193 | QuantifiedWhereClauses::from_iter( |
194 | &Interner, | ||
195 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)), | ||
196 | ) | ||
193 | }); | 197 | }); |
194 | TyKind::Dyn(predicates).intern(&Interner) | 198 | let bounds = Binders::new(1, bounds); |
199 | TyKind::Dyn(DynTy { bounds }).intern(&Interner) | ||
195 | } | 200 | } |
196 | TypeRef::ImplTrait(bounds) => { | 201 | TypeRef::ImplTrait(bounds) => { |
197 | match self.impl_trait_mode { | 202 | match self.impl_trait_mode { |
@@ -360,7 +365,7 @@ impl<'a> TyLoweringContext<'a> { | |||
360 | // FIXME handle type parameters on the segment | 365 | // FIXME handle type parameters on the segment |
361 | TyKind::Alias(AliasTy::Projection(ProjectionTy { | 366 | TyKind::Alias(AliasTy::Projection(ProjectionTy { |
362 | associated_ty_id: to_assoc_type_id(associated_ty), | 367 | associated_ty_id: to_assoc_type_id(associated_ty), |
363 | substitution: super_trait_ref.substs, | 368 | substitution: super_trait_ref.substitution, |
364 | })) | 369 | })) |
365 | .intern(&Interner) | 370 | .intern(&Interner) |
366 | } | 371 | } |
@@ -373,8 +378,16 @@ impl<'a> TyLoweringContext<'a> { | |||
373 | // FIXME report error (ambiguous associated type) | 378 | // FIXME report error (ambiguous associated type) |
374 | TyKind::Unknown.intern(&Interner) | 379 | TyKind::Unknown.intern(&Interner) |
375 | } else { | 380 | } else { |
376 | TyKind::Dyn(Arc::new([GenericPredicate::Implemented(trait_ref)])) | 381 | let dyn_ty = DynTy { |
377 | .intern(&Interner) | 382 | bounds: Binders::new( |
383 | 1, | ||
384 | QuantifiedWhereClauses::from_iter( | ||
385 | &Interner, | ||
386 | Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), | ||
387 | ), | ||
388 | ), | ||
389 | }; | ||
390 | TyKind::Dyn(dyn_ty).intern(&Interner) | ||
378 | }; | 391 | }; |
379 | return (ty, None); | 392 | return (ty, None); |
380 | } | 393 | } |
@@ -470,9 +483,9 @@ impl<'a> TyLoweringContext<'a> { | |||
470 | "there should be generics if there's a generic param", | 483 | "there should be generics if there's a generic param", |
471 | ), | 484 | ), |
472 | ); | 485 | ); |
473 | t.substs.clone().subst_bound_vars(&s) | 486 | t.substitution.clone().subst_bound_vars(&s) |
474 | } | 487 | } |
475 | TypeParamLoweringMode::Variable => t.substs.clone(), | 488 | TypeParamLoweringMode::Variable => t.substitution.clone(), |
476 | }; | 489 | }; |
477 | // We need to shift in the bound vars, since | 490 | // We need to shift in the bound vars, since |
478 | // associated_type_shorthand_candidates does not do that | 491 | // associated_type_shorthand_candidates does not do that |
@@ -641,7 +654,7 @@ impl<'a> TyLoweringContext<'a> { | |||
641 | if let Some(self_ty) = explicit_self_ty { | 654 | if let Some(self_ty) = explicit_self_ty { |
642 | substs.0[0] = self_ty; | 655 | substs.0[0] = self_ty; |
643 | } | 656 | } |
644 | TraitRef { trait_: resolved, substs } | 657 | TraitRef { trait_id: to_chalk_trait_id(resolved), substitution: substs } |
645 | } | 658 | } |
646 | 659 | ||
647 | fn lower_trait_ref( | 660 | fn lower_trait_ref( |
@@ -667,7 +680,8 @@ impl<'a> TyLoweringContext<'a> { | |||
667 | pub(crate) fn lower_where_predicate( | 680 | pub(crate) fn lower_where_predicate( |
668 | &'a self, | 681 | &'a self, |
669 | where_predicate: &'a WherePredicate, | 682 | where_predicate: &'a WherePredicate, |
670 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 683 | ignore_bindings: bool, |
684 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { | ||
671 | match where_predicate { | 685 | match where_predicate { |
672 | WherePredicate::ForLifetime { target, bound, .. } | 686 | WherePredicate::ForLifetime { target, bound, .. } |
673 | | WherePredicate::TypeBound { target, bound } => { | 687 | | WherePredicate::TypeBound { target, bound } => { |
@@ -689,7 +703,9 @@ impl<'a> TyLoweringContext<'a> { | |||
689 | .intern(&Interner) | 703 | .intern(&Interner) |
690 | } | 704 | } |
691 | }; | 705 | }; |
692 | self.lower_type_bound(bound, self_ty).collect::<Vec<_>>().into_iter() | 706 | self.lower_type_bound(bound, self_ty, ignore_bindings) |
707 | .collect::<Vec<_>>() | ||
708 | .into_iter() | ||
693 | } | 709 | } |
694 | WherePredicate::Lifetime { .. } => vec![].into_iter(), | 710 | WherePredicate::Lifetime { .. } => vec![].into_iter(), |
695 | } | 711 | } |
@@ -699,21 +715,21 @@ impl<'a> TyLoweringContext<'a> { | |||
699 | &'a self, | 715 | &'a self, |
700 | bound: &'a TypeBound, | 716 | bound: &'a TypeBound, |
701 | self_ty: Ty, | 717 | self_ty: Ty, |
702 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 718 | ignore_bindings: bool, |
719 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { | ||
703 | let mut bindings = None; | 720 | let mut bindings = None; |
704 | let trait_ref = match bound { | 721 | let trait_ref = match bound { |
705 | TypeBound::Path(path) => { | 722 | TypeBound::Path(path) => { |
706 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); | 723 | bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); |
707 | Some( | 724 | bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) |
708 | bindings.clone().map_or(GenericPredicate::Error, GenericPredicate::Implemented), | ||
709 | ) | ||
710 | } | 725 | } |
711 | TypeBound::Lifetime(_) => None, | 726 | TypeBound::Lifetime(_) => None, |
712 | TypeBound::Error => Some(GenericPredicate::Error), | 727 | TypeBound::Error => None, |
713 | }; | 728 | }; |
714 | trait_ref.into_iter().chain( | 729 | trait_ref.into_iter().chain( |
715 | bindings | 730 | bindings |
716 | .into_iter() | 731 | .into_iter() |
732 | .filter(move |_| !ignore_bindings) | ||
717 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), | 733 | .flat_map(move |tr| self.assoc_type_bindings_from_type_bound(bound, tr)), |
718 | ) | 734 | ) |
719 | } | 735 | } |
@@ -722,7 +738,7 @@ impl<'a> TyLoweringContext<'a> { | |||
722 | &'a self, | 738 | &'a self, |
723 | bound: &'a TypeBound, | 739 | bound: &'a TypeBound, |
724 | trait_ref: TraitRef, | 740 | trait_ref: TraitRef, |
725 | ) -> impl Iterator<Item = GenericPredicate> + 'a { | 741 | ) -> impl Iterator<Item = QuantifiedWhereClause> + 'a { |
726 | let last_segment = match bound { | 742 | let last_segment = match bound { |
727 | TypeBound::Path(path) => path.segments().last(), | 743 | TypeBound::Path(path) => path.segments().last(), |
728 | TypeBound::Error | TypeBound::Lifetime(_) => None, | 744 | TypeBound::Error | TypeBound::Lifetime(_) => None, |
@@ -738,26 +754,27 @@ impl<'a> TyLoweringContext<'a> { | |||
738 | &binding.name, | 754 | &binding.name, |
739 | ); | 755 | ); |
740 | let (super_trait_ref, associated_ty) = match found { | 756 | let (super_trait_ref, associated_ty) = match found { |
741 | None => return SmallVec::<[GenericPredicate; 1]>::new(), | 757 | None => return SmallVec::<[QuantifiedWhereClause; 1]>::new(), |
742 | Some(t) => t, | 758 | Some(t) => t, |
743 | }; | 759 | }; |
744 | let projection_ty = ProjectionTy { | 760 | let projection_ty = ProjectionTy { |
745 | associated_ty_id: to_assoc_type_id(associated_ty), | 761 | associated_ty_id: to_assoc_type_id(associated_ty), |
746 | substitution: super_trait_ref.substs, | 762 | substitution: super_trait_ref.substitution, |
747 | }; | 763 | }; |
748 | let mut preds = SmallVec::with_capacity( | 764 | let mut preds = SmallVec::with_capacity( |
749 | binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), | 765 | binding.type_ref.as_ref().map_or(0, |_| 1) + binding.bounds.len(), |
750 | ); | 766 | ); |
751 | if let Some(type_ref) = &binding.type_ref { | 767 | if let Some(type_ref) = &binding.type_ref { |
752 | let ty = self.lower_ty(type_ref); | 768 | let ty = self.lower_ty(type_ref); |
753 | let projection_predicate = | 769 | let alias_eq = |
754 | ProjectionPredicate { projection_ty: projection_ty.clone(), ty }; | 770 | AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; |
755 | preds.push(GenericPredicate::Projection(projection_predicate)); | 771 | preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); |
756 | } | 772 | } |
757 | for bound in &binding.bounds { | 773 | for bound in &binding.bounds { |
758 | preds.extend(self.lower_type_bound( | 774 | preds.extend(self.lower_type_bound( |
759 | bound, | 775 | bound, |
760 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), | 776 | TyKind::Alias(AliasTy::Projection(projection_ty.clone())).intern(&Interner), |
777 | false, | ||
761 | )); | 778 | )); |
762 | } | 779 | } |
763 | preds | 780 | preds |
@@ -769,7 +786,7 @@ impl<'a> TyLoweringContext<'a> { | |||
769 | let self_ty = | 786 | let self_ty = |
770 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); | 787 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)).intern(&Interner); |
771 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { | 788 | let predicates = self.with_shifted_in(DebruijnIndex::ONE, |ctx| { |
772 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone())).collect() | 789 | bounds.iter().flat_map(|b| ctx.lower_type_bound(b, self_ty.clone(), false)).collect() |
773 | }); | 790 | }); |
774 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } | 791 | ReturnTypeImplTrait { bounds: Binders::new(1, predicates) } |
775 | } | 792 | } |
@@ -808,8 +825,8 @@ pub fn associated_type_shorthand_candidates<R>( | |||
808 | let predicates = db.generic_predicates_for_param(param_id); | 825 | let predicates = db.generic_predicates_for_param(param_id); |
809 | let mut traits_: Vec<_> = predicates | 826 | let mut traits_: Vec<_> = predicates |
810 | .iter() | 827 | .iter() |
811 | .filter_map(|pred| match &pred.value { | 828 | .filter_map(|pred| match &pred.value.value { |
812 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 829 | WhereClause::Implemented(tr) => Some(tr.clone()), |
813 | _ => None, | 830 | _ => None, |
814 | }) | 831 | }) |
815 | .collect(); | 832 | .collect(); |
@@ -820,8 +837,8 @@ pub fn associated_type_shorthand_candidates<R>( | |||
820 | == TypeParamProvenance::TraitSelf | 837 | == TypeParamProvenance::TraitSelf |
821 | { | 838 | { |
822 | let trait_ref = TraitRef { | 839 | let trait_ref = TraitRef { |
823 | trait_: trait_id, | 840 | trait_id: to_chalk_trait_id(trait_id), |
824 | substs: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), | 841 | substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), |
825 | }; | 842 | }; |
826 | traits_.push(trait_ref); | 843 | traits_.push(trait_ref); |
827 | } | 844 | } |
@@ -832,7 +849,7 @@ pub fn associated_type_shorthand_candidates<R>( | |||
832 | }; | 849 | }; |
833 | 850 | ||
834 | for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) { | 851 | for t in traits_from_env.into_iter().flat_map(move |t| all_super_trait_refs(db, t)) { |
835 | let data = db.trait_data(t.trait_); | 852 | let data = db.trait_data(t.hir_trait_id()); |
836 | 853 | ||
837 | for (name, assoc_id) in &data.items { | 854 | for (name, assoc_id) in &data.items { |
838 | match assoc_id { | 855 | match assoc_id { |
@@ -881,7 +898,7 @@ pub(crate) fn field_types_query( | |||
881 | pub(crate) fn generic_predicates_for_param_query( | 898 | pub(crate) fn generic_predicates_for_param_query( |
882 | db: &dyn HirDatabase, | 899 | db: &dyn HirDatabase, |
883 | param_id: TypeParamId, | 900 | param_id: TypeParamId, |
884 | ) -> Arc<[Binders<GenericPredicate>]> { | 901 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
885 | let resolver = param_id.parent.resolver(db.upcast()); | 902 | let resolver = param_id.parent.resolver(db.upcast()); |
886 | let ctx = | 903 | let ctx = |
887 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 904 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
@@ -899,7 +916,9 @@ pub(crate) fn generic_predicates_for_param_query( | |||
899 | }, | 916 | }, |
900 | WherePredicate::Lifetime { .. } => false, | 917 | WherePredicate::Lifetime { .. } => false, |
901 | }) | 918 | }) |
902 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 919 | .flat_map(|pred| { |
920 | ctx.lower_where_predicate(pred, true).map(|p| Binders::new(generics.len(), p)) | ||
921 | }) | ||
903 | .collect() | 922 | .collect() |
904 | } | 923 | } |
905 | 924 | ||
@@ -907,7 +926,7 @@ pub(crate) fn generic_predicates_for_param_recover( | |||
907 | _db: &dyn HirDatabase, | 926 | _db: &dyn HirDatabase, |
908 | _cycle: &[String], | 927 | _cycle: &[String], |
909 | _param_id: &TypeParamId, | 928 | _param_id: &TypeParamId, |
910 | ) -> Arc<[Binders<GenericPredicate>]> { | 929 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
911 | Arc::new([]) | 930 | Arc::new([]) |
912 | } | 931 | } |
913 | 932 | ||
@@ -921,12 +940,9 @@ pub(crate) fn trait_environment_query( | |||
921 | let mut traits_in_scope = Vec::new(); | 940 | let mut traits_in_scope = Vec::new(); |
922 | let mut clauses = Vec::new(); | 941 | let mut clauses = Vec::new(); |
923 | for pred in resolver.where_predicates_in_scope() { | 942 | for pred in resolver.where_predicates_in_scope() { |
924 | for pred in ctx.lower_where_predicate(pred) { | 943 | for pred in ctx.lower_where_predicate(pred, false) { |
925 | if pred.is_error() { | 944 | if let WhereClause::Implemented(tr) = &pred.skip_binders() { |
926 | continue; | 945 | traits_in_scope.push((tr.self_type_parameter().clone(), tr.hir_trait_id())); |
927 | } | ||
928 | if let GenericPredicate::Implemented(tr) = &pred { | ||
929 | traits_in_scope.push((tr.self_ty().clone(), tr.trait_)); | ||
930 | } | 946 | } |
931 | let program_clause: chalk_ir::ProgramClause<Interner> = | 947 | let program_clause: chalk_ir::ProgramClause<Interner> = |
932 | pred.clone().to_chalk(db).cast(&Interner); | 948 | pred.clone().to_chalk(db).cast(&Interner); |
@@ -950,10 +966,9 @@ pub(crate) fn trait_environment_query( | |||
950 | // inside consts or type aliases) | 966 | // inside consts or type aliases) |
951 | cov_mark::hit!(trait_self_implements_self); | 967 | cov_mark::hit!(trait_self_implements_self); |
952 | let substs = Substitution::type_params(db, trait_id); | 968 | let substs = Substitution::type_params(db, trait_id); |
953 | let trait_ref = TraitRef { trait_: trait_id, substs }; | 969 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; |
954 | let pred = GenericPredicate::Implemented(trait_ref); | 970 | let pred = WhereClause::Implemented(trait_ref); |
955 | let program_clause: chalk_ir::ProgramClause<Interner> = | 971 | let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); |
956 | pred.clone().to_chalk(db).cast(&Interner); | ||
957 | clauses.push(program_clause.into_from_env_clause(&Interner)); | 972 | clauses.push(program_clause.into_from_env_clause(&Interner)); |
958 | } | 973 | } |
959 | 974 | ||
@@ -966,14 +981,16 @@ pub(crate) fn trait_environment_query( | |||
966 | pub(crate) fn generic_predicates_query( | 981 | pub(crate) fn generic_predicates_query( |
967 | db: &dyn HirDatabase, | 982 | db: &dyn HirDatabase, |
968 | def: GenericDefId, | 983 | def: GenericDefId, |
969 | ) -> Arc<[Binders<GenericPredicate>]> { | 984 | ) -> Arc<[Binders<QuantifiedWhereClause>]> { |
970 | let resolver = def.resolver(db.upcast()); | 985 | let resolver = def.resolver(db.upcast()); |
971 | let ctx = | 986 | let ctx = |
972 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 987 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
973 | let generics = generics(db.upcast(), def); | 988 | let generics = generics(db.upcast(), def); |
974 | resolver | 989 | resolver |
975 | .where_predicates_in_scope() | 990 | .where_predicates_in_scope() |
976 | .flat_map(|pred| ctx.lower_where_predicate(pred).map(|p| Binders::new(generics.len(), p))) | 991 | .flat_map(|pred| { |
992 | ctx.lower_where_predicate(pred, false).map(|p| Binders::new(generics.len(), p)) | ||
993 | }) | ||
977 | .collect() | 994 | .collect() |
978 | } | 995 | } |
979 | 996 | ||
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 943d3339b..8e986ddde 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -6,7 +6,7 @@ use std::{iter, sync::Arc}; | |||
6 | 6 | ||
7 | use arrayvec::ArrayVec; | 7 | use arrayvec::ArrayVec; |
8 | use base_db::CrateId; | 8 | use base_db::CrateId; |
9 | use chalk_ir::Mutability; | 9 | use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; |
10 | use hir_def::{ | 10 | use hir_def::{ |
11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, | 11 | lang_item::LangItemTarget, AssocContainerId, AssocItemId, FunctionId, GenericDefId, HasModule, |
12 | ImplId, Lookup, ModuleId, TraitId, | 12 | ImplId, Lookup, ModuleId, TraitId, |
@@ -19,9 +19,11 @@ use crate::{ | |||
19 | db::HirDatabase, | 19 | db::HirDatabase, |
20 | from_foreign_def_id, | 20 | from_foreign_def_id, |
21 | primitive::{self, FloatTy, IntTy, UintTy}, | 21 | primitive::{self, FloatTy, IntTy, UintTy}, |
22 | to_chalk_trait_id, | ||
22 | utils::all_super_traits, | 23 | utils::all_super_traits, |
23 | AdtId, Canonical, DebruijnIndex, FnPointer, FnSig, ForeignDefId, InEnvironment, Interner, | 24 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, |
24 | Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, TypeWalk, | 25 | InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, |
26 | TypeWalk, | ||
25 | }; | 27 | }; |
26 | 28 | ||
27 | /// This is used as a key for indexing impls. | 29 | /// This is used as a key for indexing impls. |
@@ -101,7 +103,7 @@ impl TraitImpls { | |||
101 | for (_module_id, module_data) in crate_def_map.modules() { | 103 | for (_module_id, module_data) in crate_def_map.modules() { |
102 | for impl_id in module_data.scope.impls() { | 104 | for impl_id in module_data.scope.impls() { |
103 | let target_trait = match db.impl_trait(impl_id) { | 105 | let target_trait = match db.impl_trait(impl_id) { |
104 | Some(tr) => tr.value.trait_, | 106 | Some(tr) => tr.value.hir_trait_id(), |
105 | None => continue, | 107 | None => continue, |
106 | }; | 108 | }; |
107 | let self_ty = db.impl_self_ty(impl_id); | 109 | let self_ty = db.impl_self_ty(impl_id); |
@@ -374,7 +376,7 @@ fn iterate_method_candidates_impl( | |||
374 | // Also note that when we've got a receiver like &S, even if the method we | 376 | // Also note that when we've got a receiver like &S, even if the method we |
375 | // find in the end takes &self, we still do the autoderef step (just as | 377 | // find in the end takes &self, we still do the autoderef step (just as |
376 | // rustc does an autoderef and then autoref again). | 378 | // rustc does an autoderef and then autoref again). |
377 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 379 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
378 | 380 | ||
379 | // We have to be careful about the order we're looking at candidates | 381 | // We have to be careful about the order we're looking at candidates |
380 | // in here. Consider the case where we're resolving `x.clone()` | 382 | // in here. Consider the case where we're resolving `x.clone()` |
@@ -442,7 +444,7 @@ fn iterate_method_candidates_with_autoref( | |||
442 | return true; | 444 | return true; |
443 | } | 445 | } |
444 | let refed = Canonical { | 446 | let refed = Canonical { |
445 | kinds: deref_chain[0].kinds.clone(), | 447 | binders: deref_chain[0].binders.clone(), |
446 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), | 448 | value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), |
447 | }; | 449 | }; |
448 | if iterate_method_candidates_by_receiver( | 450 | if iterate_method_candidates_by_receiver( |
@@ -458,7 +460,7 @@ fn iterate_method_candidates_with_autoref( | |||
458 | return true; | 460 | return true; |
459 | } | 461 | } |
460 | let ref_muted = Canonical { | 462 | let ref_muted = Canonical { |
461 | kinds: deref_chain[0].kinds.clone(), | 463 | binders: deref_chain[0].binders.clone(), |
462 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), | 464 | value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), |
463 | }; | 465 | }; |
464 | if iterate_method_candidates_by_receiver( | 466 | if iterate_method_candidates_by_receiver( |
@@ -620,7 +622,7 @@ pub fn resolve_indexing_op( | |||
620 | krate: CrateId, | 622 | krate: CrateId, |
621 | index_trait: TraitId, | 623 | index_trait: TraitId, |
622 | ) -> Option<Canonical<Ty>> { | 624 | ) -> Option<Canonical<Ty>> { |
623 | let ty = InEnvironment { value: ty.clone(), environment: env.clone() }; | 625 | let ty = InEnvironment { goal: ty.clone(), environment: env.env.clone() }; |
624 | let deref_chain = autoderef_method_receiver(db, krate, ty); | 626 | let deref_chain = autoderef_method_receiver(db, krate, ty); |
625 | for ty in deref_chain { | 627 | for ty in deref_chain { |
626 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); | 628 | let goal = generic_implements_goal(db, env.clone(), index_trait, ty.clone()); |
@@ -676,19 +678,28 @@ pub(crate) fn inherent_impl_substs( | |||
676 | // we create a var for each type parameter of the impl; we need to keep in | 678 | // we create a var for each type parameter of the impl; we need to keep in |
677 | // mind here that `self_ty` might have vars of its own | 679 | // mind here that `self_ty` might have vars of its own |
678 | let vars = Substitution::build_for_def(db, impl_id) | 680 | let vars = Substitution::build_for_def(db, impl_id) |
679 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.kinds.len()) | 681 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) |
680 | .build(); | 682 | .build(); |
681 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | 683 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); |
682 | let mut kinds = self_ty.kinds.to_vec(); | 684 | let mut kinds = self_ty.binders.interned().to_vec(); |
683 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(vars.len())); | 685 | kinds.extend( |
684 | let tys = Canonical { kinds: kinds.into(), value: (self_ty_with_vars, self_ty.value.clone()) }; | 686 | iter::repeat(chalk_ir::WithKind::new( |
687 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | ||
688 | UniverseIndex::ROOT, | ||
689 | )) | ||
690 | .take(vars.len()), | ||
691 | ); | ||
692 | let tys = Canonical { | ||
693 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
694 | value: (self_ty_with_vars, self_ty.value.clone()), | ||
695 | }; | ||
685 | let substs = super::infer::unify(&tys); | 696 | let substs = super::infer::unify(&tys); |
686 | // We only want the substs for the vars we added, not the ones from self_ty. | 697 | // We only want the substs for the vars we added, not the ones from self_ty. |
687 | // Also, if any of the vars we added are still in there, we replace them by | 698 | // Also, if any of the vars we added are still in there, we replace them by |
688 | // Unknown. I think this can only really happen if self_ty contained | 699 | // Unknown. I think this can only really happen if self_ty contained |
689 | // Unknown, and in that case we want the result to contain Unknown in those | 700 | // Unknown, and in that case we want the result to contain Unknown in those |
690 | // places again. | 701 | // places again. |
691 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.kinds.len())) | 702 | substs.map(|s| fallback_bound_vars(s.suffix(vars.len()), self_ty.binders.len(&Interner))) |
692 | } | 703 | } |
693 | 704 | ||
694 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past | 705 | /// This replaces any 'free' Bound vars in `s` (i.e. those with indices past |
@@ -766,16 +777,25 @@ fn generic_implements_goal( | |||
766 | env: Arc<TraitEnvironment>, | 777 | env: Arc<TraitEnvironment>, |
767 | trait_: TraitId, | 778 | trait_: TraitId, |
768 | self_ty: Canonical<Ty>, | 779 | self_ty: Canonical<Ty>, |
769 | ) -> Canonical<InEnvironment<super::Obligation>> { | 780 | ) -> Canonical<InEnvironment<super::DomainGoal>> { |
770 | let mut kinds = self_ty.kinds.to_vec(); | 781 | let mut kinds = self_ty.binders.interned().to_vec(); |
771 | let substs = super::Substitution::build_for_def(db, trait_) | 782 | let substs = super::Substitution::build_for_def(db, trait_) |
772 | .push(self_ty.value) | 783 | .push(self_ty.value) |
773 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) | 784 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) |
774 | .build(); | 785 | .build(); |
775 | kinds.extend(iter::repeat(chalk_ir::TyVariableKind::General).take(substs.len() - 1)); | 786 | kinds.extend( |
776 | let trait_ref = TraitRef { trait_, substs }; | 787 | iter::repeat(chalk_ir::WithKind::new( |
777 | let obligation = super::Obligation::Trait(trait_ref); | 788 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), |
778 | Canonical { kinds: kinds.into(), value: InEnvironment::new(env, obligation) } | 789 | UniverseIndex::ROOT, |
790 | )) | ||
791 | .take(substs.len() - 1), | ||
792 | ); | ||
793 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; | ||
794 | let obligation = trait_ref.cast(&Interner); | ||
795 | Canonical { | ||
796 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | ||
797 | value: InEnvironment::new(env.env.clone(), obligation), | ||
798 | } | ||
779 | } | 799 | } |
780 | 800 | ||
781 | fn autoderef_method_receiver( | 801 | fn autoderef_method_receiver( |
@@ -788,9 +808,9 @@ fn autoderef_method_receiver( | |||
788 | if let Some(TyKind::Array(parameters)) = | 808 | if let Some(TyKind::Array(parameters)) = |
789 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) | 809 | deref_chain.last().map(|ty| ty.value.interned(&Interner)) |
790 | { | 810 | { |
791 | let kinds = deref_chain.last().unwrap().kinds.clone(); | 811 | let kinds = deref_chain.last().unwrap().binders.clone(); |
792 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); | 812 | let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); |
793 | deref_chain.push(Canonical { value: unsized_ty, kinds }) | 813 | deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) |
794 | } | 814 | } |
795 | deref_chain | 815 | deref_chain |
796 | } | 816 | } |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index 0a4141e69..ad283c1e0 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -369,3 +369,72 @@ fn check_infer_with_mismatches(ra_fixture: &str, expect: Expect) { | |||
369 | actual.push('\n'); | 369 | actual.push('\n'); |
370 | expect.assert_eq(&actual); | 370 | expect.assert_eq(&actual); |
371 | } | 371 | } |
372 | |||
373 | #[test] | ||
374 | fn salsa_bug() { | ||
375 | let (mut db, pos) = TestDB::with_position( | ||
376 | " | ||
377 | //- /lib.rs | ||
378 | trait Index { | ||
379 | type Output; | ||
380 | } | ||
381 | |||
382 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
383 | |||
384 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
385 | type Key; | ||
386 | |||
387 | fn len(&self) -> usize; | ||
388 | } | ||
389 | |||
390 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
391 | fn push(&mut self, value: Self::Key); | ||
392 | } | ||
393 | |||
394 | fn main() { | ||
395 | let x = 1; | ||
396 | x.push(1);$0 | ||
397 | } | ||
398 | ", | ||
399 | ); | ||
400 | |||
401 | let module = db.module_for_file(pos.file_id); | ||
402 | let crate_def_map = module.def_map(&db); | ||
403 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
404 | db.infer(def); | ||
405 | }); | ||
406 | |||
407 | let new_text = " | ||
408 | //- /lib.rs | ||
409 | trait Index { | ||
410 | type Output; | ||
411 | } | ||
412 | |||
413 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
414 | |||
415 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
416 | type Key; | ||
417 | |||
418 | fn len(&self) -> usize; | ||
419 | } | ||
420 | |||
421 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
422 | fn push(&mut self, value: Self::Key); | ||
423 | } | ||
424 | |||
425 | fn main() { | ||
426 | |||
427 | let x = 1; | ||
428 | x.push(1); | ||
429 | } | ||
430 | " | ||
431 | .to_string(); | ||
432 | |||
433 | db.set_file_text(pos.file_id, Arc::new(new_text)); | ||
434 | |||
435 | let module = db.module_for_file(pos.file_id); | ||
436 | let crate_def_map = module.def_map(&db); | ||
437 | visit_module(&db, &crate_def_map, module.local_id, &mut |def| { | ||
438 | db.infer(def); | ||
439 | }); | ||
440 | } | ||
diff --git a/crates/hir_ty/src/tests/macros.rs b/crates/hir_ty/src/tests/macros.rs index af4f8bb11..12951fb16 100644 --- a/crates/hir_ty/src/tests/macros.rs +++ b/crates/hir_ty/src/tests/macros.rs | |||
@@ -232,6 +232,28 @@ fn expr_macro_expanded_in_stmts() { | |||
232 | } | 232 | } |
233 | 233 | ||
234 | #[test] | 234 | #[test] |
235 | fn recursive_inner_item_macro_rules() { | ||
236 | check_infer( | ||
237 | r#" | ||
238 | macro_rules! mac { | ||
239 | () => { mac!($)}; | ||
240 | ($x:tt) => { macro_rules! blub { () => { 1 }; } }; | ||
241 | } | ||
242 | fn foo() { | ||
243 | mac!(); | ||
244 | let a = blub!(); | ||
245 | } | ||
246 | "#, | ||
247 | expect![[r#" | ||
248 | !0..1 '1': i32 | ||
249 | !0..7 'mac!($)': {unknown} | ||
250 | 107..143 '{ ...!(); }': () | ||
251 | 129..130 'a': i32 | ||
252 | "#]], | ||
253 | ); | ||
254 | } | ||
255 | |||
256 | #[test] | ||
235 | fn infer_type_value_macro_having_same_name() { | 257 | fn infer_type_value_macro_having_same_name() { |
236 | check_infer( | 258 | check_infer( |
237 | r#" | 259 | r#" |
@@ -585,6 +607,29 @@ fn bar() -> u32 {0} | |||
585 | } | 607 | } |
586 | 608 | ||
587 | #[test] | 609 | #[test] |
610 | fn infer_builtin_macros_include_child_mod() { | ||
611 | check_types( | ||
612 | r#" | ||
613 | //- /main.rs | ||
614 | #[rustc_builtin_macro] | ||
615 | macro_rules! include {() => {}} | ||
616 | |||
617 | include!("f/foo.rs"); | ||
618 | |||
619 | fn main() { | ||
620 | bar::bar(); | ||
621 | } //^ u32 | ||
622 | |||
623 | //- /f/foo.rs | ||
624 | pub mod bar; | ||
625 | |||
626 | //- /f/bar.rs | ||
627 | pub fn bar() -> u32 {0} | ||
628 | "#, | ||
629 | ); | ||
630 | } | ||
631 | |||
632 | #[test] | ||
588 | fn infer_builtin_macros_include_str() { | 633 | fn infer_builtin_macros_include_str() { |
589 | check_types( | 634 | check_types( |
590 | r#" | 635 | r#" |
diff --git a/crates/hir_ty/src/tests/patterns.rs b/crates/hir_ty/src/tests/patterns.rs index 5da19ba5f..85a28e76b 100644 --- a/crates/hir_ty/src/tests/patterns.rs +++ b/crates/hir_ty/src/tests/patterns.rs | |||
@@ -658,6 +658,28 @@ fn slice_tail_pattern() { | |||
658 | fn box_pattern() { | 658 | fn box_pattern() { |
659 | check_infer( | 659 | check_infer( |
660 | r#" | 660 | r#" |
661 | pub struct Global; | ||
662 | #[lang = "owned_box"] | ||
663 | pub struct Box<T, A = Global>(T); | ||
664 | |||
665 | fn foo(params: Box<i32>) { | ||
666 | match params { | ||
667 | box integer => {} | ||
668 | } | ||
669 | } | ||
670 | "#, | ||
671 | expect![[r#" | ||
672 | 83..89 'params': Box<i32, Global> | ||
673 | 101..155 '{ ... } }': () | ||
674 | 107..153 'match ... }': () | ||
675 | 113..119 'params': Box<i32, Global> | ||
676 | 130..141 'box integer': Box<i32, Global> | ||
677 | 134..141 'integer': i32 | ||
678 | 145..147 '{}': () | ||
679 | "#]], | ||
680 | ); | ||
681 | check_infer( | ||
682 | r#" | ||
661 | #[lang = "owned_box"] | 683 | #[lang = "owned_box"] |
662 | pub struct Box<T>(T); | 684 | pub struct Box<T>(T); |
663 | 685 | ||
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs index 8270fa219..37cd04c6f 100644 --- a/crates/hir_ty/src/tests/traits.rs +++ b/crates/hir_ty/src/tests/traits.rs | |||
@@ -1412,8 +1412,8 @@ fn weird_bounds() { | |||
1412 | 50..51 'b': impl | 1412 | 50..51 'b': impl |
1413 | 69..70 'c': impl Trait | 1413 | 69..70 'c': impl Trait |
1414 | 86..87 'd': impl | 1414 | 86..87 'd': impl |
1415 | 107..108 'e': impl {error} | 1415 | 107..108 'e': impl |
1416 | 123..124 'f': impl Trait + {error} | 1416 | 123..124 'f': impl Trait |
1417 | 147..149 '{}': () | 1417 | 147..149 '{}': () |
1418 | "#]], | 1418 | "#]], |
1419 | ); | 1419 | ); |
@@ -2272,6 +2272,56 @@ fn test<T, U>() where T: Trait<U::Item>, U: Trait<T::Item> { | |||
2272 | } | 2272 | } |
2273 | 2273 | ||
2274 | #[test] | 2274 | #[test] |
2275 | fn unselected_projection_in_trait_env_cycle_3() { | ||
2276 | // this is a cycle for rustc; we currently accept it | ||
2277 | check_types( | ||
2278 | r#" | ||
2279 | //- /main.rs | ||
2280 | trait Trait { | ||
2281 | type Item; | ||
2282 | type OtherItem; | ||
2283 | } | ||
2284 | |||
2285 | fn test<T>() where T: Trait<OtherItem = T::Item> { | ||
2286 | let x: T::Item = no_matter; | ||
2287 | } //^ Trait::Item<T> | ||
2288 | "#, | ||
2289 | ); | ||
2290 | } | ||
2291 | |||
2292 | #[test] | ||
2293 | fn unselected_projection_in_trait_env_no_cycle() { | ||
2294 | // this is not a cycle | ||
2295 | check_types( | ||
2296 | r#" | ||
2297 | //- /main.rs | ||
2298 | trait Index { | ||
2299 | type Output; | ||
2300 | } | ||
2301 | |||
2302 | type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key; | ||
2303 | |||
2304 | pub trait UnificationStoreBase: Index<Output = Key<Self>> { | ||
2305 | type Key; | ||
2306 | |||
2307 | fn len(&self) -> usize; | ||
2308 | } | ||
2309 | |||
2310 | pub trait UnificationStoreMut: UnificationStoreBase { | ||
2311 | fn push(&mut self, value: Self::Key); | ||
2312 | } | ||
2313 | |||
2314 | fn test<T>(t: T) where T: UnificationStoreMut { | ||
2315 | let x; | ||
2316 | t.push(x); | ||
2317 | let y: Key<T>; | ||
2318 | (x, y); | ||
2319 | } //^ (UnificationStoreBase::Key<T>, UnificationStoreBase::Key<T>) | ||
2320 | "#, | ||
2321 | ); | ||
2322 | } | ||
2323 | |||
2324 | #[test] | ||
2275 | fn inline_assoc_type_bounds_1() { | 2325 | fn inline_assoc_type_bounds_1() { |
2276 | check_types( | 2326 | check_types( |
2277 | r#" | 2327 | r#" |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index 40eb1034e..ccee0e5ad 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -1,6 +1,5 @@ | |||
1 | //! Trait solving using Chalk. | 1 | //! Trait solving using Chalk. |
2 | use std::env::var; | 2 | use std::env::var; |
3 | use std::sync::Arc; | ||
4 | 3 | ||
5 | use base_db::CrateId; | 4 | use base_db::CrateId; |
6 | use chalk_ir::cast::Cast; | 5 | use chalk_ir::cast::Cast; |
@@ -8,10 +7,9 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; | |||
8 | use hir_def::{lang_item::LangItemTarget, TraitId}; | 7 | use hir_def::{lang_item::LangItemTarget, TraitId}; |
9 | use stdx::panic_context; | 8 | use stdx::panic_context; |
10 | 9 | ||
11 | use crate::{db::HirDatabase, DebruijnIndex, Substitution}; | 10 | use crate::{ |
12 | 11 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, | |
13 | use super::{ | 12 | TypeWalk, WhereClause, |
14 | Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk, | ||
15 | }; | 13 | }; |
16 | 14 | ||
17 | use self::chalk::{from_chalk, Interner, ToChalk}; | 15 | use self::chalk::{from_chalk, Interner, ToChalk}; |
@@ -45,7 +43,7 @@ pub struct TraitEnvironment { | |||
45 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, | 43 | // When we're using Chalk's Ty we can make this a BTreeMap since it's Ord, |
46 | // but for now it's too annoying... | 44 | // but for now it's too annoying... |
47 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, | 45 | pub(crate) traits_from_clauses: Vec<(Ty, TraitId)>, |
48 | pub(crate) env: chalk_ir::Environment<Interner>, | 46 | pub env: chalk_ir::Environment<Interner>, |
49 | } | 47 | } |
50 | 48 | ||
51 | impl TraitEnvironment { | 49 | impl TraitEnvironment { |
@@ -75,13 +73,13 @@ impl Default for TraitEnvironment { | |||
75 | /// Something (usually a goal), along with an environment. | 73 | /// Something (usually a goal), along with an environment. |
76 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 74 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
77 | pub struct InEnvironment<T> { | 75 | pub struct InEnvironment<T> { |
78 | pub environment: Arc<TraitEnvironment>, | 76 | pub environment: chalk_ir::Environment<Interner>, |
79 | pub value: T, | 77 | pub goal: T, |
80 | } | 78 | } |
81 | 79 | ||
82 | impl<T> InEnvironment<T> { | 80 | impl<T> InEnvironment<T> { |
83 | pub fn new(environment: Arc<TraitEnvironment>, value: T) -> InEnvironment<T> { | 81 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { |
84 | InEnvironment { environment, value } | 82 | InEnvironment { environment, goal: value } |
85 | } | 83 | } |
86 | } | 84 | } |
87 | 85 | ||
@@ -89,35 +87,23 @@ impl<T> InEnvironment<T> { | |||
89 | /// a certain type implements a certain trait. Proving the Obligation might | 87 | /// a certain type implements a certain trait. Proving the Obligation might |
90 | /// result in additional information about inference variables. | 88 | /// result in additional information about inference variables. |
91 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 89 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
92 | pub enum Obligation { | 90 | pub enum DomainGoal { |
93 | /// Prove that a certain type implements a trait (the type is the `Self` type | 91 | Holds(WhereClause), |
94 | /// parameter to the `TraitRef`). | ||
95 | Trait(TraitRef), | ||
96 | Projection(ProjectionPredicate), | ||
97 | } | ||
98 | |||
99 | impl Obligation { | ||
100 | pub fn from_predicate(predicate: GenericPredicate) -> Option<Obligation> { | ||
101 | match predicate { | ||
102 | GenericPredicate::Implemented(trait_ref) => Some(Obligation::Trait(trait_ref)), | ||
103 | GenericPredicate::Projection(projection_pred) => { | ||
104 | Some(Obligation::Projection(projection_pred)) | ||
105 | } | ||
106 | GenericPredicate::Error => None, | ||
107 | } | ||
108 | } | ||
109 | } | 92 | } |
110 | 93 | ||
111 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | 94 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] |
112 | pub struct ProjectionPredicate { | 95 | pub struct AliasEq { |
113 | pub projection_ty: ProjectionTy, | 96 | pub alias: AliasTy, |
114 | pub ty: Ty, | 97 | pub ty: Ty, |
115 | } | 98 | } |
116 | 99 | ||
117 | impl TypeWalk for ProjectionPredicate { | 100 | impl TypeWalk for AliasEq { |
118 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | 101 | fn walk(&self, f: &mut impl FnMut(&Ty)) { |
119 | self.projection_ty.walk(f); | ||
120 | self.ty.walk(f); | 102 | self.ty.walk(f); |
103 | match &self.alias { | ||
104 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
105 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
106 | } | ||
121 | } | 107 | } |
122 | 108 | ||
123 | fn walk_mut_binders( | 109 | fn walk_mut_binders( |
@@ -125,8 +111,11 @@ impl TypeWalk for ProjectionPredicate { | |||
125 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | 111 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), |
126 | binders: DebruijnIndex, | 112 | binders: DebruijnIndex, |
127 | ) { | 113 | ) { |
128 | self.projection_ty.walk_mut_binders(f, binders); | ||
129 | self.ty.walk_mut_binders(f, binders); | 114 | self.ty.walk_mut_binders(f, binders); |
115 | match &mut self.alias { | ||
116 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
117 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
118 | } | ||
130 | } | 119 | } |
131 | } | 120 | } |
132 | 121 | ||
@@ -134,16 +123,22 @@ impl TypeWalk for ProjectionPredicate { | |||
134 | pub(crate) fn trait_solve_query( | 123 | pub(crate) fn trait_solve_query( |
135 | db: &dyn HirDatabase, | 124 | db: &dyn HirDatabase, |
136 | krate: CrateId, | 125 | krate: CrateId, |
137 | goal: Canonical<InEnvironment<Obligation>>, | 126 | goal: Canonical<InEnvironment<DomainGoal>>, |
138 | ) -> Option<Solution> { | 127 | ) -> Option<Solution> { |
139 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.value { | 128 | let _p = profile::span("trait_solve_query").detail(|| match &goal.value.goal { |
140 | Obligation::Trait(it) => db.trait_data(it.trait_).name.to_string(), | 129 | DomainGoal::Holds(WhereClause::Implemented(it)) => { |
141 | Obligation::Projection(_) => "projection".to_string(), | 130 | db.trait_data(it.hir_trait_id()).name.to_string() |
131 | } | ||
132 | DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), | ||
142 | }); | 133 | }); |
143 | log::info!("trait_solve_query({})", goal.value.value.display(db)); | 134 | log::info!("trait_solve_query({})", goal.value.goal.display(db)); |
144 | 135 | ||
145 | if let Obligation::Projection(pred) = &goal.value.value { | 136 | if let DomainGoal::Holds(WhereClause::AliasEq(AliasEq { |
146 | if let TyKind::BoundVar(_) = &pred.projection_ty.substitution[0].interned(&Interner) { | 137 | alias: AliasTy::Projection(projection_ty), |
138 | .. | ||
139 | })) = &goal.value.goal | ||
140 | { | ||
141 | if let TyKind::BoundVar(_) = &projection_ty.substitution[0].interned(&Interner) { | ||
147 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible | 142 | // Hack: don't ask Chalk to normalize with an unknown self type, it'll say that's impossible |
148 | return Some(Solution::Ambig(Guidance::Unknown)); | 143 | return Some(Solution::Ambig(Guidance::Unknown)); |
149 | } | 144 | } |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index bef6e7e9c..4019fdf17 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -19,10 +19,10 @@ use crate::{ | |||
19 | display::HirDisplay, | 19 | display::HirDisplay, |
20 | from_assoc_type_id, | 20 | from_assoc_type_id, |
21 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, | 21 | method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, |
22 | to_assoc_type_id, | 22 | to_assoc_type_id, to_chalk_trait_id, |
23 | utils::generics, | 23 | utils::generics, |
24 | BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, GenericPredicate, | 24 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, DebruijnIndex, FnDefId, ProjectionTy, |
25 | ProjectionPredicate, ProjectionTy, Substitution, TraitRef, Ty, TyKind, | 25 | Substitution, TraitRef, Ty, TyKind, WhereClause, |
26 | }; | 26 | }; |
27 | use mapping::{ | 27 | use mapping::{ |
28 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, | 28 | convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, |
@@ -187,13 +187,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
187 | let data = &datas.value.impl_traits[idx as usize]; | 187 | let data = &datas.value.impl_traits[idx as usize]; |
188 | let bound = OpaqueTyDatumBound { | 188 | let bound = OpaqueTyDatumBound { |
189 | bounds: make_binders( | 189 | bounds: make_binders( |
190 | data.bounds | 190 | data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(), |
191 | .value | ||
192 | .iter() | ||
193 | .cloned() | ||
194 | .filter(|b| !b.is_error()) | ||
195 | .map(|b| b.to_chalk(self.db)) | ||
196 | .collect(), | ||
197 | 1, | 191 | 1, |
198 | ), | 192 | ), |
199 | where_clauses: make_binders(vec![], 0), | 193 | where_clauses: make_binders(vec![], 0), |
@@ -218,10 +212,10 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
218 | // |-------------OpaqueTyDatumBound--------------| | 212 | // |-------------OpaqueTyDatumBound--------------| |
219 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] | 213 | // for<T> <Self> [Future<Self>, Future::Output<Self> = T] |
220 | // ^1 ^0 ^0 ^0 ^1 | 214 | // ^1 ^0 ^0 ^0 ^1 |
221 | let impl_bound = GenericPredicate::Implemented(TraitRef { | 215 | let impl_bound = WhereClause::Implemented(TraitRef { |
222 | trait_: future_trait, | 216 | trait_id: to_chalk_trait_id(future_trait), |
223 | // Self type as the first parameter. | 217 | // Self type as the first parameter. |
224 | substs: Substitution::single( | 218 | substitution: Substitution::single( |
225 | TyKind::BoundVar(BoundVar { | 219 | TyKind::BoundVar(BoundVar { |
226 | debruijn: DebruijnIndex::INNERMOST, | 220 | debruijn: DebruijnIndex::INNERMOST, |
227 | index: 0, | 221 | index: 0, |
@@ -229,22 +223,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
229 | .intern(&Interner), | 223 | .intern(&Interner), |
230 | ), | 224 | ), |
231 | }); | 225 | }); |
232 | let proj_bound = GenericPredicate::Projection(ProjectionPredicate { | 226 | let proj_bound = WhereClause::AliasEq(AliasEq { |
233 | // The parameter of the opaque type. | 227 | alias: AliasTy::Projection(ProjectionTy { |
234 | ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) | ||
235 | .intern(&Interner), | ||
236 | projection_ty: ProjectionTy { | ||
237 | associated_ty_id: to_assoc_type_id(future_output), | 228 | associated_ty_id: to_assoc_type_id(future_output), |
238 | // Self type as the first parameter. | 229 | // Self type as the first parameter. |
239 | substitution: Substitution::single( | 230 | substitution: Substitution::single( |
240 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) | 231 | TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) |
241 | .intern(&Interner), | 232 | .intern(&Interner), |
242 | ), | 233 | ), |
243 | }, | 234 | }), |
235 | // The parameter of the opaque type. | ||
236 | ty: TyKind::BoundVar(BoundVar { debruijn: DebruijnIndex::ONE, index: 0 }) | ||
237 | .intern(&Interner), | ||
244 | }); | 238 | }); |
245 | let bound = OpaqueTyDatumBound { | 239 | let bound = OpaqueTyDatumBound { |
246 | bounds: make_binders( | 240 | bounds: make_binders( |
247 | vec![impl_bound.to_chalk(self.db), proj_bound.to_chalk(self.db)], | 241 | vec![ |
242 | wrap_in_empty_binders(impl_bound).to_chalk(self.db), | ||
243 | wrap_in_empty_binders(proj_bound).to_chalk(self.db), | ||
244 | ], | ||
248 | 1, | 245 | 1, |
249 | ), | 246 | ), |
250 | where_clauses: make_binders(vec![], 0), | 247 | where_clauses: make_binders(vec![], 0), |
@@ -401,9 +398,8 @@ pub(crate) fn associated_ty_data_query( | |||
401 | let bounds = type_alias_data | 398 | let bounds = type_alias_data |
402 | .bounds | 399 | .bounds |
403 | .iter() | 400 | .iter() |
404 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone())) | 401 | .flat_map(|bound| ctx.lower_type_bound(bound, self_ty.clone(), false)) |
405 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) | 402 | .filter_map(|pred| generic_predicate_to_inline_bound(db, &pred, &self_ty)) |
406 | .map(|bound| make_binders(bound.shifted_in(&Interner), 0)) | ||
407 | .collect(); | 403 | .collect(); |
408 | 404 | ||
409 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); | 405 | let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); |
@@ -546,7 +542,7 @@ fn impl_def_datum( | |||
546 | 542 | ||
547 | let generic_params = generics(db.upcast(), impl_id.into()); | 543 | let generic_params = generics(db.upcast(), impl_id.into()); |
548 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 544 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); |
549 | let trait_ = trait_ref.trait_; | 545 | let trait_ = trait_ref.hir_trait_id(); |
550 | let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { | 546 | let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { |
551 | rust_ir::ImplType::Local | 547 | rust_ir::ImplType::Local |
552 | } else { | 548 | } else { |
@@ -614,7 +610,7 @@ fn type_alias_associated_ty_value( | |||
614 | 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 | 610 | 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 |
615 | 611 | ||
616 | let assoc_ty = db | 612 | let assoc_ty = db |
617 | .trait_data(trait_ref.trait_) | 613 | .trait_data(trait_ref.hir_trait_id()) |
618 | .associated_type_by_name(&type_alias_data.name) | 614 | .associated_type_by_name(&type_alias_data.name) |
619 | .expect("assoc ty value should not exist"); // validated when building the impl data as well | 615 | .expect("assoc ty value should not exist"); // validated when building the impl data as well |
620 | let ty = db.ty(type_alias.into()); | 616 | let ty = db.ty(type_alias.into()); |
@@ -726,3 +722,7 @@ impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { | |||
726 | chalk_ir::ClosureId(id.as_intern_id()) | 722 | chalk_ir::ClosureId(id.as_intern_id()) |
727 | } | 723 | } |
728 | } | 724 | } |
725 | |||
726 | fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> { | ||
727 | crate::Binders::wrap_empty(value) | ||
728 | } | ||
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index d969527dc..aef6b8a15 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -7,15 +7,14 @@ use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeDa | |||
7 | use chalk_solve::rust_ir; | 7 | use chalk_solve::rust_ir; |
8 | 8 | ||
9 | use base_db::salsa::InternKey; | 9 | use base_db::salsa::InternKey; |
10 | use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, |
14 | from_assoc_type_id, | ||
15 | primitive::UintTy, | 14 | primitive::UintTy, |
16 | traits::{Canonical, Obligation}, | 15 | traits::{Canonical, DomainGoal}, |
17 | AliasTy, CallableDefId, FnPointer, GenericPredicate, InEnvironment, OpaqueTy, | 16 | AliasTy, CallableDefId, FnPointer, InEnvironment, OpaqueTy, ProjectionTy, |
18 | ProjectionPredicate, ProjectionTy, Scalar, Substitution, TraitRef, Ty, | 17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, |
19 | }; | 18 | }; |
20 | 19 | ||
21 | use super::interner::*; | 20 | use super::interner::*; |
@@ -95,10 +94,10 @@ impl ToChalk for Ty { | |||
95 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), | 94 | TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner), |
96 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), | 95 | TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner), |
97 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), | 96 | TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"), |
98 | TyKind::Dyn(predicates) => { | 97 | TyKind::Dyn(dyn_ty) => { |
99 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( | 98 | let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter( |
100 | &Interner, | 99 | &Interner, |
101 | predicates.iter().filter(|p| !p.is_error()).cloned().map(|p| p.to_chalk(db)), | 100 | dyn_ty.bounds.value.interned().iter().cloned().map(|p| p.to_chalk(db)), |
102 | ); | 101 | ); |
103 | let bounded_ty = chalk_ir::DynTy { | 102 | let bounded_ty = chalk_ir::DynTy { |
104 | bounds: make_binders(where_clauses, 1), | 103 | bounds: make_binders(where_clauses, 1), |
@@ -144,13 +143,17 @@ impl ToChalk for Ty { | |||
144 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, | 143 | chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Unknown, |
145 | chalk_ir::TyKind::Dyn(where_clauses) => { | 144 | chalk_ir::TyKind::Dyn(where_clauses) => { |
146 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); | 145 | assert_eq!(where_clauses.bounds.binders.len(&Interner), 1); |
147 | let predicates = where_clauses | 146 | let bounds = where_clauses |
148 | .bounds | 147 | .bounds |
149 | .skip_binders() | 148 | .skip_binders() |
150 | .iter(&Interner) | 149 | .iter(&Interner) |
151 | .map(|c| from_chalk(db, c.clone())) | 150 | .map(|c| from_chalk(db, c.clone())); |
152 | .collect(); | 151 | TyKind::Dyn(crate::DynTy { |
153 | TyKind::Dyn(predicates) | 152 | bounds: crate::Binders::new( |
153 | 1, | ||
154 | crate::QuantifiedWhereClauses::from_iter(&Interner, bounds), | ||
155 | ), | ||
156 | }) | ||
154 | } | 157 | } |
155 | 158 | ||
156 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), | 159 | chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)), |
@@ -239,15 +242,15 @@ impl ToChalk for TraitRef { | |||
239 | type Chalk = chalk_ir::TraitRef<Interner>; | 242 | type Chalk = chalk_ir::TraitRef<Interner>; |
240 | 243 | ||
241 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { | 244 | fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> { |
242 | let trait_id = self.trait_.to_chalk(db); | 245 | let trait_id = self.trait_id; |
243 | let substitution = self.substs.to_chalk(db); | 246 | let substitution = self.substitution.to_chalk(db); |
244 | chalk_ir::TraitRef { trait_id, substitution } | 247 | chalk_ir::TraitRef { trait_id, substitution } |
245 | } | 248 | } |
246 | 249 | ||
247 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { | 250 | fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self { |
248 | let trait_ = from_chalk(db, trait_ref.trait_id); | 251 | let trait_id = trait_ref.trait_id; |
249 | let substs = from_chalk(db, trait_ref.substitution); | 252 | let substs = from_chalk(db, trait_ref.substitution); |
250 | TraitRef { trait_, substs } | 253 | TraitRef { trait_id, substitution: substs } |
251 | } | 254 | } |
252 | } | 255 | } |
253 | 256 | ||
@@ -304,50 +307,26 @@ impl ToChalk for TypeAliasAsValue { | |||
304 | } | 307 | } |
305 | } | 308 | } |
306 | 309 | ||
307 | impl ToChalk for GenericPredicate { | 310 | impl ToChalk for WhereClause { |
308 | type Chalk = chalk_ir::QuantifiedWhereClause<Interner>; | 311 | type Chalk = chalk_ir::WhereClause<Interner>; |
309 | 312 | ||
310 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::QuantifiedWhereClause<Interner> { | 313 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> { |
311 | match self { | 314 | match self { |
312 | GenericPredicate::Implemented(trait_ref) => { | 315 | WhereClause::Implemented(trait_ref) => { |
313 | let chalk_trait_ref = trait_ref.to_chalk(db); | 316 | chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db)) |
314 | let chalk_trait_ref = chalk_trait_ref.shifted_in(&Interner); | ||
315 | make_binders(chalk_ir::WhereClause::Implemented(chalk_trait_ref), 0) | ||
316 | } | ||
317 | GenericPredicate::Projection(projection_pred) => { | ||
318 | let ty = projection_pred.ty.to_chalk(db).shifted_in(&Interner); | ||
319 | let projection = projection_pred.projection_ty.to_chalk(db).shifted_in(&Interner); | ||
320 | let alias = chalk_ir::AliasTy::Projection(projection); | ||
321 | make_binders(chalk_ir::WhereClause::AliasEq(chalk_ir::AliasEq { alias, ty }), 0) | ||
322 | } | 317 | } |
323 | GenericPredicate::Error => panic!("tried passing GenericPredicate::Error to Chalk"), | 318 | WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)), |
324 | } | 319 | } |
325 | } | 320 | } |
326 | 321 | ||
327 | fn from_chalk( | 322 | fn from_chalk( |
328 | db: &dyn HirDatabase, | 323 | db: &dyn HirDatabase, |
329 | where_clause: chalk_ir::QuantifiedWhereClause<Interner>, | 324 | where_clause: chalk_ir::WhereClause<Interner>, |
330 | ) -> GenericPredicate { | 325 | ) -> WhereClause { |
331 | // we don't produce any where clauses with binders and can't currently deal with them | 326 | match where_clause { |
332 | match where_clause | 327 | chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)), |
333 | .skip_binders() | 328 | chalk_ir::WhereClause::AliasEq(alias_eq) => { |
334 | .clone() | 329 | WhereClause::AliasEq(from_chalk(db, alias_eq)) |
335 | .shifted_out(&Interner) | ||
336 | .expect("unexpected bound vars in where clause") | ||
337 | { | ||
338 | chalk_ir::WhereClause::Implemented(tr) => { | ||
339 | GenericPredicate::Implemented(from_chalk(db, tr)) | ||
340 | } | ||
341 | chalk_ir::WhereClause::AliasEq(projection_eq) => { | ||
342 | let projection_ty = from_chalk( | ||
343 | db, | ||
344 | match projection_eq.alias { | ||
345 | chalk_ir::AliasTy::Projection(p) => p, | ||
346 | _ => unimplemented!(), | ||
347 | }, | ||
348 | ); | ||
349 | let ty = from_chalk(db, projection_eq.ty); | ||
350 | GenericPredicate::Projection(ProjectionPredicate { projection_ty, ty }) | ||
351 | } | 330 | } |
352 | 331 | ||
353 | chalk_ir::WhereClause::LifetimeOutlives(_) => { | 332 | chalk_ir::WhereClause::LifetimeOutlives(_) => { |
@@ -383,29 +362,67 @@ impl ToChalk for ProjectionTy { | |||
383 | } | 362 | } |
384 | } | 363 | } |
385 | } | 364 | } |
365 | impl ToChalk for OpaqueTy { | ||
366 | type Chalk = chalk_ir::OpaqueTy<Interner>; | ||
367 | |||
368 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { | ||
369 | chalk_ir::OpaqueTy { | ||
370 | opaque_ty_id: self.opaque_ty_id, | ||
371 | substitution: self.substitution.to_chalk(db), | ||
372 | } | ||
373 | } | ||
374 | |||
375 | fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
376 | OpaqueTy { | ||
377 | opaque_ty_id: chalk.opaque_ty_id, | ||
378 | substitution: from_chalk(db, chalk.substitution), | ||
379 | } | ||
380 | } | ||
381 | } | ||
382 | |||
383 | impl ToChalk for AliasTy { | ||
384 | type Chalk = chalk_ir::AliasTy<Interner>; | ||
385 | |||
386 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { | ||
387 | match self { | ||
388 | AliasTy::Projection(projection_ty) => { | ||
389 | chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db)) | ||
390 | } | ||
391 | AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)), | ||
392 | } | ||
393 | } | ||
394 | |||
395 | fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self { | ||
396 | match chalk { | ||
397 | chalk_ir::AliasTy::Projection(projection_ty) => { | ||
398 | AliasTy::Projection(from_chalk(db, projection_ty)) | ||
399 | } | ||
400 | chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)), | ||
401 | } | ||
402 | } | ||
403 | } | ||
386 | 404 | ||
387 | impl ToChalk for ProjectionPredicate { | 405 | impl ToChalk for AliasEq { |
388 | type Chalk = chalk_ir::AliasEq<Interner>; | 406 | type Chalk = chalk_ir::AliasEq<Interner>; |
389 | 407 | ||
390 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { | 408 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> { |
391 | chalk_ir::AliasEq { | 409 | chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) } |
392 | alias: chalk_ir::AliasTy::Projection(self.projection_ty.to_chalk(db)), | ||
393 | ty: self.ty.to_chalk(db), | ||
394 | } | ||
395 | } | 410 | } |
396 | 411 | ||
397 | fn from_chalk(_db: &dyn HirDatabase, _normalize: chalk_ir::AliasEq<Interner>) -> Self { | 412 | fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self { |
398 | unimplemented!() | 413 | AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) } |
399 | } | 414 | } |
400 | } | 415 | } |
401 | 416 | ||
402 | impl ToChalk for Obligation { | 417 | impl ToChalk for DomainGoal { |
403 | type Chalk = chalk_ir::DomainGoal<Interner>; | 418 | type Chalk = chalk_ir::DomainGoal<Interner>; |
404 | 419 | ||
405 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { | 420 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> { |
406 | match self { | 421 | match self { |
407 | Obligation::Trait(tr) => tr.to_chalk(db).cast(&Interner), | 422 | DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner), |
408 | Obligation::Projection(pr) => pr.to_chalk(db).cast(&Interner), | 423 | DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => { |
424 | alias_eq.to_chalk(db).cast(&Interner) | ||
425 | } | ||
409 | } | 426 | } |
410 | } | 427 | } |
411 | 428 | ||
@@ -422,35 +439,12 @@ where | |||
422 | type Chalk = chalk_ir::Canonical<T::Chalk>; | 439 | type Chalk = chalk_ir::Canonical<T::Chalk>; |
423 | 440 | ||
424 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { | 441 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> { |
425 | let kinds = self.kinds.iter().map(|&tk| { | ||
426 | chalk_ir::CanonicalVarKind::new( | ||
427 | chalk_ir::VariableKind::Ty(tk), | ||
428 | chalk_ir::UniverseIndex::ROOT, | ||
429 | ) | ||
430 | }); | ||
431 | let value = self.value.to_chalk(db); | 442 | let value = self.value.to_chalk(db); |
432 | chalk_ir::Canonical { | 443 | chalk_ir::Canonical { value, binders: self.binders } |
433 | value, | ||
434 | binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds), | ||
435 | } | ||
436 | } | 444 | } |
437 | 445 | ||
438 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { | 446 | fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> { |
439 | let kinds = canonical | 447 | Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) } |
440 | .binders | ||
441 | .iter(&Interner) | ||
442 | .map(|k| match k.kind { | ||
443 | chalk_ir::VariableKind::Ty(tk) => tk, | ||
444 | // HACK: Chalk can sometimes return new lifetime variables. We | ||
445 | // want to just skip them, but to not mess up the indices of | ||
446 | // other variables, we'll just create a new type variable in | ||
447 | // their place instead. This should not matter (we never see the | ||
448 | // actual *uses* of the lifetime variable). | ||
449 | chalk_ir::VariableKind::Lifetime => chalk_ir::TyVariableKind::General, | ||
450 | chalk_ir::VariableKind::Const(_) => panic!("unexpected const from Chalk"), | ||
451 | }) | ||
452 | .collect(); | ||
453 | Canonical { kinds, value: from_chalk(db, canonical.value) } | ||
454 | } | 448 | } |
455 | } | 449 | } |
456 | 450 | ||
@@ -461,10 +455,7 @@ where | |||
461 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; | 455 | type Chalk = chalk_ir::InEnvironment<T::Chalk>; |
462 | 456 | ||
463 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { | 457 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> { |
464 | chalk_ir::InEnvironment { | 458 | chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) } |
465 | environment: self.environment.env.clone(), | ||
466 | goal: self.value.to_chalk(db), | ||
467 | } | ||
468 | } | 459 | } |
469 | 460 | ||
470 | fn from_chalk( | 461 | fn from_chalk( |
@@ -475,6 +466,29 @@ where | |||
475 | } | 466 | } |
476 | } | 467 | } |
477 | 468 | ||
469 | impl<T: ToChalk> ToChalk for crate::Binders<T> | ||
470 | where | ||
471 | T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>, | ||
472 | { | ||
473 | type Chalk = chalk_ir::Binders<T::Chalk>; | ||
474 | |||
475 | fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> { | ||
476 | chalk_ir::Binders::new( | ||
477 | chalk_ir::VariableKinds::from_iter( | ||
478 | &Interner, | ||
479 | std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General)) | ||
480 | .take(self.num_binders), | ||
481 | ), | ||
482 | self.value.to_chalk(db), | ||
483 | ) | ||
484 | } | ||
485 | |||
486 | fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> { | ||
487 | let (v, b) = binders.into_value_and_skipped_binders(); | ||
488 | crate::Binders::new(b.len(&Interner), from_chalk(db, v)) | ||
489 | } | ||
490 | } | ||
491 | |||
478 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> | 492 | pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> |
479 | where | 493 | where |
480 | T: HasInterner<Interner = Interner>, | 494 | T: HasInterner<Interner = Interner>, |
@@ -497,10 +511,6 @@ pub(super) fn convert_where_clauses( | |||
497 | let generic_predicates = db.generic_predicates(def); | 511 | let generic_predicates = db.generic_predicates(def); |
498 | let mut result = Vec::with_capacity(generic_predicates.len()); | 512 | let mut result = Vec::with_capacity(generic_predicates.len()); |
499 | for pred in generic_predicates.iter() { | 513 | for pred in generic_predicates.iter() { |
500 | if pred.value.is_error() { | ||
501 | // skip errored predicates completely | ||
502 | continue; | ||
503 | } | ||
504 | result.push(pred.clone().subst(substs).to_chalk(db)); | 514 | result.push(pred.clone().subst(substs).to_chalk(db)); |
505 | } | 515 | } |
506 | result | 516 | result |
@@ -508,49 +518,43 @@ pub(super) fn convert_where_clauses( | |||
508 | 518 | ||
509 | pub(super) fn generic_predicate_to_inline_bound( | 519 | pub(super) fn generic_predicate_to_inline_bound( |
510 | db: &dyn HirDatabase, | 520 | db: &dyn HirDatabase, |
511 | pred: &GenericPredicate, | 521 | pred: &QuantifiedWhereClause, |
512 | self_ty: &Ty, | 522 | self_ty: &Ty, |
513 | ) -> Option<rust_ir::InlineBound<Interner>> { | 523 | ) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> { |
514 | // An InlineBound is like a GenericPredicate, except the self type is left out. | 524 | // An InlineBound is like a GenericPredicate, except the self type is left out. |
515 | // We don't have a special type for this, but Chalk does. | 525 | // We don't have a special type for this, but Chalk does. |
516 | match pred { | 526 | let self_ty_shifted_in = self_ty.clone().shift_bound_vars(DebruijnIndex::ONE); |
517 | GenericPredicate::Implemented(trait_ref) => { | 527 | match &pred.value { |
518 | if &trait_ref.substs[0] != self_ty { | 528 | WhereClause::Implemented(trait_ref) => { |
529 | if trait_ref.self_type_parameter() != &self_ty_shifted_in { | ||
519 | // we can only convert predicates back to type bounds if they | 530 | // we can only convert predicates back to type bounds if they |
520 | // have the expected self type | 531 | // have the expected self type |
521 | return None; | 532 | return None; |
522 | } | 533 | } |
523 | let args_no_self = trait_ref.substs[1..] | 534 | let args_no_self = trait_ref.substitution[1..] |
524 | .iter() | 535 | .iter() |
525 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 536 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
526 | .collect(); | 537 | .collect(); |
527 | let trait_bound = | 538 | let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self }; |
528 | rust_ir::TraitBound { trait_id: trait_ref.trait_.to_chalk(db), args_no_self }; | 539 | Some(make_binders(rust_ir::InlineBound::TraitBound(trait_bound), pred.num_binders)) |
529 | Some(rust_ir::InlineBound::TraitBound(trait_bound)) | ||
530 | } | 540 | } |
531 | GenericPredicate::Projection(proj) => { | 541 | WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { |
532 | if &proj.projection_ty.substitution[0] != self_ty { | 542 | if projection_ty.self_type_parameter() != &self_ty_shifted_in { |
533 | return None; | 543 | return None; |
534 | } | 544 | } |
535 | let trait_ = match from_assoc_type_id(proj.projection_ty.associated_ty_id) | 545 | let trait_ = projection_ty.trait_(db); |
536 | .lookup(db.upcast()) | 546 | let args_no_self = projection_ty.substitution[1..] |
537 | .container | ||
538 | { | ||
539 | AssocContainerId::TraitId(t) => t, | ||
540 | _ => panic!("associated type not in trait"), | ||
541 | }; | ||
542 | let args_no_self = proj.projection_ty.substitution[1..] | ||
543 | .iter() | 547 | .iter() |
544 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 548 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
545 | .collect(); | 549 | .collect(); |
546 | let alias_eq_bound = rust_ir::AliasEqBound { | 550 | let alias_eq_bound = rust_ir::AliasEqBound { |
547 | value: proj.ty.clone().to_chalk(db), | 551 | value: ty.clone().to_chalk(db), |
548 | trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, | 552 | trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self }, |
549 | associated_ty_id: proj.projection_ty.associated_ty_id, | 553 | associated_ty_id: projection_ty.associated_ty_id, |
550 | parameters: Vec::new(), // FIXME we don't support generic associated types yet | 554 | parameters: Vec::new(), // FIXME we don't support generic associated types yet |
551 | }; | 555 | }; |
552 | Some(rust_ir::InlineBound::AliasEqBound(alias_eq_bound)) | 556 | Some(make_binders(rust_ir::InlineBound::AliasEqBound(alias_eq_bound), pred.num_binders)) |
553 | } | 557 | } |
554 | GenericPredicate::Error => None, | 558 | _ => None, |
555 | } | 559 | } |
556 | } | 560 | } |
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 7351e4e54..19874e42b 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -15,7 +15,7 @@ use hir_def::{ | |||
15 | }; | 15 | }; |
16 | use hir_expand::name::{name, Name}; | 16 | use hir_expand::name::{name, Name}; |
17 | 17 | ||
18 | use crate::{db::HirDatabase, GenericPredicate, TraitRef}; | 18 | use crate::{db::HirDatabase, TraitRef, WhereClause}; |
19 | 19 | ||
20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 20 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
21 | let resolver = trait_.resolver(db); | 21 | let resolver = trait_.resolver(db); |
@@ -55,20 +55,20 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr | |||
55 | // lifetime problems, but since there usually shouldn't be more than a | 55 | // lifetime problems, but since there usually shouldn't be more than a |
56 | // few direct traits this should be fine (we could even use some kind of | 56 | // few direct traits this should be fine (we could even use some kind of |
57 | // SmallVec if performance is a concern) | 57 | // SmallVec if performance is a concern) |
58 | let generic_params = db.generic_params(trait_ref.trait_.into()); | 58 | let generic_params = db.generic_params(trait_ref.hir_trait_id().into()); |
59 | let trait_self = match generic_params.find_trait_self_param() { | 59 | let trait_self = match generic_params.find_trait_self_param() { |
60 | Some(p) => TypeParamId { parent: trait_ref.trait_.into(), local_id: p }, | 60 | Some(p) => TypeParamId { parent: trait_ref.hir_trait_id().into(), local_id: p }, |
61 | None => return Vec::new(), | 61 | None => return Vec::new(), |
62 | }; | 62 | }; |
63 | db.generic_predicates_for_param(trait_self) | 63 | db.generic_predicates_for_param(trait_self) |
64 | .iter() | 64 | .iter() |
65 | .filter_map(|pred| { | 65 | .filter_map(|pred| { |
66 | pred.as_ref().filter_map(|pred| match pred { | 66 | pred.as_ref().filter_map(|pred| match pred.skip_binders() { |
67 | GenericPredicate::Implemented(tr) => Some(tr.clone()), | 67 | WhereClause::Implemented(tr) => Some(tr.clone()), |
68 | _ => None, | 68 | _ => None, |
69 | }) | 69 | }) |
70 | }) | 70 | }) |
71 | .map(|pred| pred.subst(&trait_ref.substs)) | 71 | .map(|pred| pred.subst(&trait_ref.substitution)) |
72 | .collect() | 72 | .collect() |
73 | } | 73 | } |
74 | 74 | ||
@@ -108,7 +108,7 @@ pub(super) fn all_super_trait_refs(db: &dyn HirDatabase, trait_ref: TraitRef) -> | |||
108 | // yeah this is quadratic, but trait hierarchies should be flat | 108 | // yeah this is quadratic, but trait hierarchies should be flat |
109 | // enough that this doesn't matter | 109 | // enough that this doesn't matter |
110 | for tt in direct_super_trait_refs(db, t) { | 110 | for tt in direct_super_trait_refs(db, t) { |
111 | if !result.iter().any(|tr| tr.trait_ == tt.trait_) { | 111 | if !result.iter().any(|tr| tr.trait_id == tt.trait_id) { |
112 | result.push(tt); | 112 | result.push(tt); |
113 | } | 113 | } |
114 | } | 114 | } |
@@ -123,7 +123,7 @@ pub(super) fn associated_type_by_name_including_super_traits( | |||
123 | name: &Name, | 123 | name: &Name, |
124 | ) -> Option<(TraitRef, TypeAliasId)> { | 124 | ) -> Option<(TraitRef, TypeAliasId)> { |
125 | all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| { | 125 | all_super_trait_refs(db, trait_ref).into_iter().find_map(|t| { |
126 | let assoc_type = db.trait_data(t.trait_).associated_type_by_name(name)?; | 126 | let assoc_type = db.trait_data(t.hir_trait_id()).associated_type_by_name(name)?; |
127 | Some((t, assoc_type)) | 127 | Some((t, assoc_type)) |
128 | }) | 128 | }) |
129 | } | 129 | } |