aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/autoderef.rs62
-rw-r--r--crates/hir_ty/src/chalk_cast.rs53
-rw-r--r--crates/hir_ty/src/db.rs10
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs15
-rw-r--r--crates/hir_ty/src/display.rs152
-rw-r--r--crates/hir_ty/src/infer.rs29
-rw-r--r--crates/hir_ty/src/infer/coerce.rs13
-rw-r--r--crates/hir_ty/src/infer/expr.rs49
-rw-r--r--crates/hir_ty/src/infer/pat.rs34
-rw-r--r--crates/hir_ty/src/infer/path.rs20
-rw-r--r--crates/hir_ty/src/infer/unify.rs119
-rw-r--r--crates/hir_ty/src/lib.rs217
-rw-r--r--crates/hir_ty/src/lower.rs111
-rw-r--r--crates/hir_ty/src/method_resolution.rs62
-rw-r--r--crates/hir_ty/src/tests.rs69
-rw-r--r--crates/hir_ty/src/tests/macros.rs45
-rw-r--r--crates/hir_ty/src/tests/patterns.rs22
-rw-r--r--crates/hir_ty/src/tests/traits.rs54
-rw-r--r--crates/hir_ty/src/traits.rs75
-rw-r--r--crates/hir_ty/src/traits/chalk.rs48
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs238
-rw-r--r--crates/hir_ty/src/utils.rs16
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 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast;
9use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
10use hir_expand::name::name; 11use hir_expand::name::name;
11use log::{info, warn}; 12use log::{info, warn};
12 13
13use crate::{ 14use 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
21const AUTODEREF_RECURSION_LIMIT: usize = 10; 23const 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
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20
21impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause {
23 WhereClause::Implemented(self)
24 }
25}
26
27impl CastTo<WhereClause> for AliasEq {
28 fn cast_to(self, _interner: &Interner) -> WhereClause {
29 WhereClause::AliasEq(self)
30 }
31}
32
33impl CastTo<DomainGoal> for WhereClause {
34 fn cast_to(self, _interner: &Interner) -> DomainGoal {
35 DomainGoal::Holds(self)
36 }
37}
38
39macro_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
52transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_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;
12use crate::{ 12use 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};
18use hir_expand::name::Name; 18use 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#"
910fn 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
3use std::{borrow::Cow, fmt}; 3use std::fmt;
4 4
5use arrayvec::ArrayVec; 5use arrayvec::ArrayVec;
6use chalk_ir::Mutability; 6use chalk_ir::Mutability;
@@ -18,9 +18,9 @@ use hir_expand::name::Name;
18 18
19use crate::{ 19use 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
26pub struct HirFormatter<'a> { 26pub struct HirFormatter<'a> {
@@ -190,6 +190,7 @@ impl DisplayTarget {
190pub enum DisplaySourceCodeError { 190pub enum DisplaySourceCodeError {
191 PathNotFound, 191 PathNotFound,
192 UnknownType, 192 UnknownType,
193 Closure,
193} 194}
194 195
195pub enum HirDisplayError { 196pub enum HirDisplayError {
@@ -268,6 +269,16 @@ impl HirDisplay for ProjectionTy {
268 } 269 }
269} 270}
270 271
272impl 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
271impl HirDisplay for Ty { 282impl 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
643pub fn write_bounds_like_dyn_trait_with_prefix( 676pub 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
657fn write_bounds_like_dyn_trait( 690fn 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
770impl HirDisplay for GenericPredicate { 794impl 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
810impl HirDisplay for Obligation { 831impl 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;
18use std::ops::Index; 18use std::ops::Index;
19use std::sync::Arc; 19use std::sync::Arc;
20 20
21use chalk_ir::Mutability; 21use chalk_ir::{cast::Cast, Mutability};
22use hir_def::{ 22use 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;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use 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};
43use crate::{ 43use 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
48pub(crate) use unify::unify; 48pub(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
7use chalk_ir::{Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{ 10use 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
14use super::{InEnvironment, InferenceContext}; 14use 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 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
7use hir_def::{ 7use 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};
13use hir_expand::name::{name, Name}; 13use hir_expand::name::{name, Name};
14use stdx::always;
14use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
15 16
16use crate::{ 17use 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
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 15use 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
19impl<'a> InferenceContext<'a> { 21impl<'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
3use std::iter; 3use std::iter;
4 4
5use chalk_ir::cast::Cast;
5use hir_def::{ 6use 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};
10use hir_expand::name::Name; 11use hir_expand::name::Name;
11 12
12use crate::{method_resolution, Interner, Substitution, Ty, TyKind, ValueTyDefId}; 13use crate::{
14 method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId,
15};
13 16
14use super::{ExprOrPatId, InferenceContext, TraitRef}; 17use 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
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind}; 5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 7
8use super::{InferenceContext, Obligation}; 8use super::{DomainGoal, InferenceContext};
9use crate::{ 9use 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
14impl<'a> InferenceContext<'a> { 14impl<'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> {
150pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { 160pub(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;
13mod lower; 13mod lower;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast;
16 17
17pub mod display; 18pub mod display;
18pub mod db; 19pub 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};
48pub use traits::{InEnvironment, Obligation, ProjectionPredicate, TraitEnvironment}; 49pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment};
49 50
50pub use chalk_ir::{AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind}; 51pub use chalk_ir::{
52 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
53};
51 54
52pub use crate::traits::chalk::Interner; 55pub use crate::traits::chalk::Interner;
53 56
@@ -58,6 +61,10 @@ pub type ClosureId = chalk_ir::ClosureId<Interner>;
58pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 61pub type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>;
59pub type PlaceholderIndex = chalk_ir::PlaceholderIndex; 62pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
60 63
64pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
65
66pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
67
61#[derive(Clone, PartialEq, Eq, Debug, Hash)] 68#[derive(Clone, PartialEq, Eq, Debug, Hash)]
62pub enum Lifetime { 69pub 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
80impl 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
82impl ProjectionTy { 103impl 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)]
138pub struct DynTy {
139 /// The unknown self type.
140 pub bounds: Binders<QuantifiedWhereClauses>,
141}
142
109pub type FnSig = chalk_ir::FnSig<Interner>; 143pub 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
165impl 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
461impl<T: Clone> Binders<&T> { 529impl<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)]
498pub struct TraitRef { 565pub 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
504impl TraitRef { 570impl 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
510impl TypeWalk for TraitRef { 580impl 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)]
527pub enum GenericPredicate { 597pub 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
537impl GenericPredicate { 604impl 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
555impl TypeWalk for GenericPredicate { 620impl 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
640pub type QuantifiedWhereClause = Binders<WhereClause>;
641
642#[derive(Debug, Clone, PartialEq, Eq, Hash)]
643pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
644
645impl 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)]
586pub struct Canonical<T> { 665pub struct Canonical<T> {
587 pub value: T, 666 pub value: T,
588 pub kinds: Arc<[TyVariableKind]>, 667 pub binders: CanonicalVarKinds,
589} 668}
590 669
591impl<T> Canonical<T> { 670impl<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)]
1128pub(crate) struct ReturnTypeImplTrait { 1227pub(crate) struct ReturnTypeImplTrait {
1129 pub(crate) bounds: Binders<Vec<GenericPredicate>>, 1228 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
1130} 1229}
1131 1230
1132pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 1231pub 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
1261pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
1262 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
1263}
1264
1265pub 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
28use crate::{ 28use 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(
881pub(crate) fn generic_predicates_for_param_query( 898pub(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(
966pub(crate) fn generic_predicates_query( 981pub(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
7use arrayvec::ArrayVec; 7use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::Mutability; 9use chalk_ir::{cast::Cast, Mutability, UniverseIndex};
10use hir_def::{ 10use 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
781fn autoderef_method_receiver( 801fn 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]
374fn 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]
235fn 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]
235fn infer_type_value_macro_having_same_name() { 257fn 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]
610fn infer_builtin_macros_include_child_mod() {
611 check_types(
612 r#"
613//- /main.rs
614#[rustc_builtin_macro]
615macro_rules! include {() => {}}
616
617include!("f/foo.rs");
618
619fn main() {
620 bar::bar();
621} //^ u32
622
623//- /f/foo.rs
624pub mod bar;
625
626//- /f/bar.rs
627pub fn bar() -> u32 {0}
628"#,
629 );
630}
631
632#[test]
588fn infer_builtin_macros_include_str() { 633fn 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() {
658fn box_pattern() { 658fn 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]
2275fn 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
2280trait Trait {
2281 type Item;
2282 type OtherItem;
2283}
2284
2285fn 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]
2293fn unselected_projection_in_trait_env_no_cycle() {
2294 // this is not a cycle
2295 check_types(
2296 r#"
2297//- /main.rs
2298trait Index {
2299 type Output;
2300}
2301
2302type Key<S: UnificationStoreBase> = <S as UnificationStoreBase>::Key;
2303
2304pub trait UnificationStoreBase: Index<Output = Key<Self>> {
2305 type Key;
2306
2307 fn len(&self) -> usize;
2308}
2309
2310pub trait UnificationStoreMut: UnificationStoreBase {
2311 fn push(&mut self, value: Self::Key);
2312}
2313
2314fn 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]
2275fn inline_assoc_type_bounds_1() { 2325fn 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.
2use std::env::var; 2use std::env::var;
3use std::sync::Arc;
4 3
5use base_db::CrateId; 4use base_db::CrateId;
6use chalk_ir::cast::Cast; 5use chalk_ir::cast::Cast;
@@ -8,10 +7,9 @@ use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
8use hir_def::{lang_item::LangItemTarget, TraitId}; 7use hir_def::{lang_item::LangItemTarget, TraitId};
9use stdx::panic_context; 8use stdx::panic_context;
10 9
11use crate::{db::HirDatabase, DebruijnIndex, Substitution}; 10use crate::{
12 11 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind,
13use super::{ 12 TypeWalk, WhereClause,
14 Canonical, GenericPredicate, HirDisplay, ProjectionTy, TraitRef, Ty, TyKind, TypeWalk,
15}; 13};
16 14
17use self::chalk::{from_chalk, Interner, ToChalk}; 15use 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
51impl TraitEnvironment { 49impl 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)]
77pub struct InEnvironment<T> { 75pub 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
82impl<T> InEnvironment<T> { 80impl<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)]
92pub enum Obligation { 90pub 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
99impl 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)]
112pub struct ProjectionPredicate { 95pub struct AliasEq {
113 pub projection_ty: ProjectionTy, 96 pub alias: AliasTy,
114 pub ty: Ty, 97 pub ty: Ty,
115} 98}
116 99
117impl TypeWalk for ProjectionPredicate { 100impl 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 {
134pub(crate) fn trait_solve_query( 123pub(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};
27use mapping::{ 27use 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
726fn 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
7use chalk_solve::rust_ir; 7use chalk_solve::rust_ir;
8 8
9use base_db::salsa::InternKey; 9use base_db::salsa::InternKey;
10use hir_def::{AssocContainerId, GenericDefId, Lookup, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use 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
21use super::interner::*; 20use 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
307impl ToChalk for GenericPredicate { 310impl 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}
365impl 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
383impl 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
387impl ToChalk for ProjectionPredicate { 405impl 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
402impl ToChalk for Obligation { 417impl 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
469impl<T: ToChalk> ToChalk for crate::Binders<T>
470where
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
478pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T> 492pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
479where 493where
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
509pub(super) fn generic_predicate_to_inline_bound( 519pub(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};
16use hir_expand::name::{name, Name}; 16use hir_expand::name::{name, Name};
17 17
18use crate::{db::HirDatabase, GenericPredicate, TraitRef}; 18use crate::{db::HirDatabase, TraitRef, WhereClause};
19 19
20fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 20fn 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}