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.rs64
-rw-r--r--crates/hir_ty/src/builder.rs21
-rw-r--r--crates/hir_ty/src/chalk_cast.rs73
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)233
-rw-r--r--crates/hir_ty/src/chalk_ext.rs294
-rw-r--r--crates/hir_ty/src/db.rs66
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs11
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--crates/hir_ty/src/display.rs215
-rw-r--r--crates/hir_ty/src/infer.rs141
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs77
-rw-r--r--crates/hir_ty/src/infer/pat.rs50
-rw-r--r--crates/hir_ty/src/infer/path.rs7
-rw-r--r--crates/hir_ty/src/infer/unify.rs207
-rw-r--r--crates/hir_ty/src/interner.rs (renamed from crates/hir_ty/src/traits/chalk/interner.rs)127
-rw-r--r--crates/hir_ty/src/lib.rs577
-rw-r--r--crates/hir_ty/src/lower.rs81
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs294
-rw-r--r--crates/hir_ty/src/op.rs58
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/tests/simple.rs33
-rw-r--r--crates/hir_ty/src/tests/traits.rs1467
-rw-r--r--crates/hir_ty/src/tls.rs (renamed from crates/hir_ty/src/traits/chalk/tls.rs)14
-rw-r--r--crates/hir_ty/src/traits.rs52
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs572
-rw-r--r--crates/hir_ty/src/types.rs475
-rw-r--r--crates/hir_ty/src/utils.rs29
-rw-r--r--crates/hir_ty/src/walk.rs283
34 files changed, 2513 insertions, 3264 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 7ca4af80e..71bc436e6 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,14 +6,15 @@
6use std::iter::successors; 6use std::iter::successors;
7 7
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::cast::Cast; 9use chalk_ir::{cast::Cast, fold::Fold, interner::HasInterner, VariableKind};
10use hir_def::lang_item::LangItemTarget; 10use hir_def::lang_item::LangItemTarget;
11use hir_expand::name::name; 11use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, 15 db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 TyKind,
17}; 18};
18 19
19const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -35,13 +36,21 @@ pub(crate) fn deref(
35 krate: CrateId, 36 krate: CrateId,
36 ty: InEnvironment<&Canonical<Ty>>, 37 ty: InEnvironment<&Canonical<Ty>>,
37) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
38 if let Some(derefed) = ty.goal.value.builtin_deref() { 39 if let Some(derefed) = builtin_deref(&ty.goal.value) {
39 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 40 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
40 } else { 41 } else {
41 deref_by_trait(db, krate, ty) 42 deref_by_trait(db, krate, ty)
42 } 43 }
43} 44}
44 45
46fn builtin_deref(ty: &Ty) -> Option<Ty> {
47 match ty.kind(&Interner) {
48 TyKind::Ref(.., ty) => Some(ty.clone()),
49 TyKind::Raw(.., ty) => Some(ty.clone()),
50 _ => None,
51 }
52}
53
45fn deref_by_trait( 54fn deref_by_trait(
46 db: &dyn HirDatabase, 55 db: &dyn HirDatabase,
47 krate: CrateId, 56 krate: CrateId,
@@ -95,7 +104,7 @@ fn deref_by_trait(
95 binders: CanonicalVarKinds::from_iter( 104 binders: CanonicalVarKinds::from_iter(
96 &Interner, 105 &Interner,
97 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( 106 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
98 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 107 VariableKind::Ty(chalk_ir::TyVariableKind::General),
99 chalk_ir::UniverseIndex::ROOT, 108 chalk_ir::UniverseIndex::ROOT,
100 ))), 109 ))),
101 ), 110 ),
@@ -120,23 +129,25 @@ fn deref_by_trait(
120 // assumptions will be broken. We would need to properly introduce 129 // assumptions will be broken. We would need to properly introduce
121 // new variables in that case 130 // new variables in that case
122 131
123 for i in 1..vars.0.binders.len(&Interner) { 132 for i in 1..vars.binders.len(&Interner) {
124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) 133 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 134 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
126 { 135 {
127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 136 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
128 return None; 137 return None;
129 } 138 }
130 } 139 }
131 Some(Canonical { 140 // FIXME: we remove lifetime variables here since they can confuse
141 // the method resolution code later
142 Some(fixup_lifetime_variables(Canonical {
132 value: vars 143 value: vars
133 .0
134 .value 144 .value
135 .at(&Interner, vars.0.value.len(&Interner) - 1) 145 .subst
146 .at(&Interner, vars.value.subst.len(&Interner) - 1)
136 .assert_ty_ref(&Interner) 147 .assert_ty_ref(&Interner)
137 .clone(), 148 .clone(),
138 binders: vars.0.binders.clone(), 149 binders: vars.binders.clone(),
139 }) 150 }))
140 } 151 }
141 Solution::Ambig(_) => { 152 Solution::Ambig(_) => {
142 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 153 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -144,3 +155,32 @@ fn deref_by_trait(
144 } 155 }
145 } 156 }
146} 157}
158
159fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
160 c: Canonical<T>,
161) -> Canonical<T> {
162 // Removes lifetime variables from the Canonical, replacing them by static lifetimes.
163 let mut i = 0;
164 let subst = Substitution::from_iter(
165 &Interner,
166 c.binders.iter(&Interner).map(|vk| match vk.kind {
167 VariableKind::Ty(_) => {
168 let index = i;
169 i += 1;
170 BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
171 }
172 VariableKind::Lifetime => static_lifetime().cast(&Interner),
173 VariableKind::Const(_) => unimplemented!(),
174 }),
175 );
176 let binders = CanonicalVarKinds::from_iter(
177 &Interner,
178 c.binders.iter(&Interner).filter(|vk| match vk.kind {
179 VariableKind::Ty(_) => true,
180 VariableKind::Lifetime => false,
181 VariableKind::Const(_) => true,
182 }),
183 );
184 let value = subst.apply(c.value, &Interner);
185 Canonical { binders, value }
186}
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index 9b2c6975a..e25ef866d 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -4,6 +4,7 @@ use std::iter;
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 cast::{Cast, CastTo, Caster}, 6 cast::{Cast, CastTo, Caster},
7 fold::Fold,
7 interner::HasInterner, 8 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar, 9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9}; 10};
@@ -12,8 +13,8 @@ use smallvec::SmallVec;
12 13
13use crate::{ 14use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, 15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, 16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId, 17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
17}; 18};
18 19
19/// This is a builder for `Ty` or anything that needs a `Substitution`. 20/// This is a builder for `Ty` or anything that needs a `Substitution`.
@@ -32,8 +33,7 @@ impl<D> TyBuilder<D> {
32 33
33 fn build_internal(self) -> (D, Substitution) { 34 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count); 35 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form 36 let subst = Substitution::from_iter(&Interner, self.vec);
36 let subst = Substitution::intern(self.vec);
37 (self.data, subst) 37 (self.data, subst)
38 } 38 }
39 39
@@ -78,9 +78,12 @@ impl TyBuilder<()> {
78 78
79 pub fn fn_ptr(sig: CallableSig) -> Ty { 79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer { 80 TyKind::Function(FnPointer {
81 num_args: sig.params().len(), 81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, 82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), 83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
84 }) 87 })
85 .intern(&Interner) 88 .intern(&Interner)
86 } 89 }
@@ -138,7 +141,7 @@ impl TyBuilder<hir_def::AdtId> {
138 self.vec.push(fallback().cast(&Interner)); 141 self.vec.push(fallback().cast(&Interner));
139 } else { 142 } else {
140 // each default can depend on the previous parameters 143 // each default can depend on the previous parameters
141 let subst_so_far = Substitution::intern(self.vec.clone()); 144 let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
142 self.vec 145 self.vec
143 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner)); 146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
144 } 147 }
@@ -193,13 +196,13 @@ impl TyBuilder<TypeAliasId> {
193 } 196 }
194} 197}
195 198
196impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { 199impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
197 fn subst_binders(b: Binders<T>) -> Self { 200 fn subst_binders(b: Binders<T>) -> Self {
198 let param_count = b.binders.len(&Interner); 201 let param_count = b.binders.len(&Interner);
199 TyBuilder::new(b, param_count) 202 TyBuilder::new(b, param_count)
200 } 203 }
201 204
202 pub fn build(self) -> T { 205 pub fn build(self) -> <T as Fold<Interner>>::Result {
203 let (b, subst) = self.build_internal(); 206 let (b, subst) = self.build_internal();
204 b.substitute(&Interner, &subst) 207 b.substitute(&Interner, &subst)
205 } 208 }
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index df6492113..000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,73 +0,0 @@
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, GenericArg, GenericArgData, Interner, TraitRef, Ty, 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);
20has_interner!(GenericArg);
21has_interner!(Ty);
22
23impl CastTo<WhereClause> for TraitRef {
24 fn cast_to(self, _interner: &Interner) -> WhereClause {
25 WhereClause::Implemented(self)
26 }
27}
28
29impl CastTo<WhereClause> for AliasEq {
30 fn cast_to(self, _interner: &Interner) -> WhereClause {
31 WhereClause::AliasEq(self)
32 }
33}
34
35impl CastTo<DomainGoal> for WhereClause {
36 fn cast_to(self, _interner: &Interner) -> DomainGoal {
37 DomainGoal::Holds(self)
38 }
39}
40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
47macro_rules! transitive_impl {
48 ($a:ty, $b:ty, $c:ty) => {
49 impl CastTo<$c> for $a {
50 fn cast_to(self, interner: &Interner) -> $c {
51 self.cast::<$b>(interner).cast(interner)
52 }
53 }
54 };
55}
56
57// In Chalk, these can be done as blanket impls, but that doesn't work here
58// because of coherence
59
60transitive_impl!(TraitRef, WhereClause, DomainGoal);
61transitive_impl!(AliasEq, WhereClause, DomainGoal);
62
63macro_rules! reflexive_impl {
64 ($a:ty) => {
65 impl CastTo<$a> for $a {
66 fn cast_to(self, _interner: &Interner) -> $a {
67 self
68 }
69 }
70 };
71}
72
73reflexive_impl!(GenericArg);
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/chalk_db.rs
index dff87ef70..8f054d06b 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -1,52 +1,47 @@
1//! Conversion code from/to Chalk. 1//! The implementation of `RustIrDatabase` for Chalk, which provides information
2//! about the code that Chalk needs.
2use std::sync::Arc; 3use std::sync::Arc;
3 4
4use log::debug; 5use log::debug;
5 6
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; 7use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 8use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 9
9use base_db::{salsa::InternKey, CrateId}; 10use base_db::CrateId;
10use hir_def::{ 11use hir_def::{
11 lang_item::{lang_attr, LangItemTarget}, 12 lang_item::{lang_attr, LangItemTarget},
12 AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, 13 AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId,
13}; 14};
14use hir_expand::name::name; 15use hir_expand::name::name;
15 16
16use super::ChalkContext;
17use crate::{ 17use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id, from_chalk_trait_id, make_only_type_binders,
21 mapping::{from_chalk, ToChalk, TypeAliasAsValue},
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 22 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, to_chalk_trait_id, 23 to_assoc_type_id, to_chalk_trait_id,
24 traits::ChalkContext,
23 utils::generics, 25 utils::generics,
24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, 26 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy,
25 TraitRef, Ty, TyBuilder, TyKind, WhereClause, 27 ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
28 TyExt, TyKind, WhereClause,
26}; 29};
27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
29};
30
31pub use self::interner::Interner;
32pub(crate) use self::interner::*;
33 30
34pub(super) mod tls; 31pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
35mod interner; 32pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
36mod mapping; 33pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
37 34pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
38pub(crate) trait ToChalk { 35pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
39 type Chalk; 36
40 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; 37pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
41 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; 38pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
42} 39pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
43 40pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
44pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 41pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
45where 42pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
46 T: ToChalk<Chalk = ChalkT>, 43pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
47{ 44pub(crate) type Variances = chalk_ir::Variances<Interner>;
48 T::from_chalk(db, chalk)
49}
50 45
51impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { 46impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
52 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { 47 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
@@ -84,9 +79,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
84 binders: &CanonicalVarKinds<Interner>, 79 binders: &CanonicalVarKinds<Interner>,
85 ) -> Vec<ImplId> { 80 ) -> Vec<ImplId> {
86 debug!("impls_for_trait {:?}", trait_id); 81 debug!("impls_for_trait {:?}", trait_id);
87 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 82 let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id);
88 83
89 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 84 let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
90 85
91 fn binder_kind( 86 fn binder_kind(
92 ty: &Ty, 87 ty: &Ty,
@@ -103,7 +98,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
103 None 98 None
104 } 99 }
105 100
106 let self_ty_fp = TyFingerprint::for_impl(&ty); 101 let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
107 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { 102 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
108 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, 103 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
109 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, 104 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
@@ -166,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
166 Some(LangItemTarget::TraitId(trait_)) => trait_, 161 Some(LangItemTarget::TraitId(trait_)) => trait_,
167 _ => return None, 162 _ => return None,
168 }; 163 };
169 Some(trait_.to_chalk(self.db)) 164 Some(to_chalk_trait_id(trait_))
170 } 165 }
171 166
172 fn program_clauses_for_env( 167 fn program_clauses_for_env(
@@ -187,16 +182,11 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
187 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders(); 182 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
188 let data = &datas.impl_traits[idx as usize]; 183 let data = &datas.impl_traits[idx as usize];
189 let bound = OpaqueTyDatumBound { 184 let bound = OpaqueTyDatumBound {
190 bounds: make_binders( 185 bounds: make_only_type_binders(
191 data.bounds
192 .skip_binders()
193 .iter()
194 .cloned()
195 .map(|b| b.to_chalk(self.db))
196 .collect(),
197 1, 186 1,
187 data.bounds.skip_binders().iter().cloned().collect(),
198 ), 188 ),
199 where_clauses: make_binders(vec![], 0), 189 where_clauses: make_only_type_binders(0, vec![]),
200 }; 190 };
201 chalk_ir::Binders::new(binders, bound) 191 chalk_ir::Binders::new(binders, bound)
202 } 192 }
@@ -220,7 +210,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
220 let impl_bound = WhereClause::Implemented(TraitRef { 210 let impl_bound = WhereClause::Implemented(TraitRef {
221 trait_id: to_chalk_trait_id(future_trait), 211 trait_id: to_chalk_trait_id(future_trait),
222 // Self type as the first parameter. 212 // Self type as the first parameter.
223 substitution: Substitution::single( 213 substitution: Substitution::from1(
214 &Interner,
224 TyKind::BoundVar(BoundVar { 215 TyKind::BoundVar(BoundVar {
225 debruijn: DebruijnIndex::INNERMOST, 216 debruijn: DebruijnIndex::INNERMOST,
226 index: 0, 217 index: 0,
@@ -232,7 +223,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
232 alias: AliasTy::Projection(ProjectionTy { 223 alias: AliasTy::Projection(ProjectionTy {
233 associated_ty_id: to_assoc_type_id(future_output), 224 associated_ty_id: to_assoc_type_id(future_output),
234 // Self type as the first parameter. 225 // Self type as the first parameter.
235 substitution: Substitution::single( 226 substitution: Substitution::from1(
227 &Interner,
236 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 228 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
237 .intern(&Interner), 229 .intern(&Interner),
238 ), 230 ),
@@ -242,25 +234,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
242 .intern(&Interner), 234 .intern(&Interner),
243 }); 235 });
244 let bound = OpaqueTyDatumBound { 236 let bound = OpaqueTyDatumBound {
245 bounds: make_binders( 237 bounds: make_only_type_binders(
238 1,
246 vec![ 239 vec![
247 wrap_in_empty_binders(impl_bound).to_chalk(self.db), 240 crate::wrap_empty_binders(impl_bound),
248 wrap_in_empty_binders(proj_bound).to_chalk(self.db), 241 crate::wrap_empty_binders(proj_bound),
249 ], 242 ],
250 1,
251 ), 243 ),
252 where_clauses: make_binders(vec![], 0), 244 where_clauses: make_only_type_binders(0, vec![]),
253 }; 245 };
254 // The opaque type has 1 parameter. 246 // The opaque type has 1 parameter.
255 make_binders(bound, 1) 247 make_only_type_binders(1, bound)
256 } else { 248 } else {
257 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback. 249 // If failed to find Symbol’s value as variable is void: Future::Output, return empty bounds as fallback.
258 let bound = OpaqueTyDatumBound { 250 let bound = OpaqueTyDatumBound {
259 bounds: make_binders(vec![], 0), 251 bounds: make_only_type_binders(0, vec![]),
260 where_clauses: make_binders(vec![], 0), 252 where_clauses: make_only_type_binders(0, vec![]),
261 }; 253 };
262 // The opaque type has 1 parameter. 254 // The opaque type has 1 parameter.
263 make_binders(bound, 1) 255 make_only_type_binders(1, bound)
264 } 256 }
265 } 257 }
266 }; 258 };
@@ -270,7 +262,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
270 262
271 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> { 263 fn hidden_opaque_type(&self, _id: chalk_ir::OpaqueTyId<Interner>) -> chalk_ir::Ty<Interner> {
272 // FIXME: actually provide the hidden type; it is relevant for auto traits 264 // FIXME: actually provide the hidden type; it is relevant for auto traits
273 TyKind::Error.intern(&Interner).to_chalk(self.db) 265 TyKind::Error.intern(&Interner)
274 } 266 }
275 267
276 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool { 268 fn is_object_safe(&self, _trait_id: chalk_ir::TraitId<Interner>) -> bool {
@@ -291,33 +283,32 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
291 _closure_id: chalk_ir::ClosureId<Interner>, 283 _closure_id: chalk_ir::ClosureId<Interner>,
292 substs: &chalk_ir::Substitution<Interner>, 284 substs: &chalk_ir::Substitution<Interner>,
293 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 285 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
294 let sig_ty: Ty = 286 let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
295 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
296 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr"); 287 let sig = &sig_ty.callable_sig(self.db).expect("first closure param should be fn ptr");
297 let io = rust_ir::FnDefInputsAndOutputDatum { 288 let io = rust_ir::FnDefInputsAndOutputDatum {
298 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), 289 argument_types: sig.params().iter().cloned().collect(),
299 return_type: sig.ret().clone().to_chalk(self.db), 290 return_type: sig.ret().clone(),
300 }; 291 };
301 make_binders(io.shifted_in(&Interner), 0) 292 make_only_type_binders(0, io.shifted_in(&Interner))
302 } 293 }
303 fn closure_upvars( 294 fn closure_upvars(
304 &self, 295 &self,
305 _closure_id: chalk_ir::ClosureId<Interner>, 296 _closure_id: chalk_ir::ClosureId<Interner>,
306 _substs: &chalk_ir::Substitution<Interner>, 297 _substs: &chalk_ir::Substitution<Interner>,
307 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 298 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
308 let ty = TyBuilder::unit().to_chalk(self.db); 299 let ty = TyBuilder::unit();
309 make_binders(ty, 0) 300 make_only_type_binders(0, ty)
310 } 301 }
311 fn closure_fn_substitution( 302 fn closure_fn_substitution(
312 &self, 303 &self,
313 _closure_id: chalk_ir::ClosureId<Interner>, 304 _closure_id: chalk_ir::ClosureId<Interner>,
314 _substs: &chalk_ir::Substitution<Interner>, 305 _substs: &chalk_ir::Substitution<Interner>,
315 ) -> chalk_ir::Substitution<Interner> { 306 ) -> chalk_ir::Substitution<Interner> {
316 Substitution::empty(&Interner).to_chalk(self.db) 307 Substitution::empty(&Interner)
317 } 308 }
318 309
319 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String { 310 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
320 let id = from_chalk(self.db, trait_id); 311 let id = from_chalk_trait_id(trait_id);
321 self.db.trait_data(id).name.to_string() 312 self.db.trait_data(id).name.to_string()
322 } 313 }
323 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { 314 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
@@ -408,10 +399,10 @@ pub(crate) fn associated_ty_data_query(
408 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars); 399 let where_clauses = convert_where_clauses(db, type_alias.into(), &bound_vars);
409 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; 400 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
410 let datum = AssociatedTyDatum { 401 let datum = AssociatedTyDatum {
411 trait_id: trait_.to_chalk(db), 402 trait_id: to_chalk_trait_id(trait_),
412 id, 403 id,
413 name: type_alias, 404 name: type_alias,
414 binders: make_binders(bound_data, generic_params.len()), 405 binders: make_only_type_binders(generic_params.len(), bound_data),
415 }; 406 };
416 Arc::new(datum) 407 Arc::new(datum)
417} 408}
@@ -422,7 +413,7 @@ pub(crate) fn trait_datum_query(
422 trait_id: TraitId, 413 trait_id: TraitId,
423) -> Arc<TraitDatum> { 414) -> Arc<TraitDatum> {
424 debug!("trait_datum {:?}", trait_id); 415 debug!("trait_datum {:?}", trait_id);
425 let trait_: hir_def::TraitId = from_chalk(db, trait_id); 416 let trait_ = from_chalk_trait_id(trait_id);
426 let trait_data = db.trait_data(trait_); 417 let trait_data = db.trait_data(trait_);
427 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 418 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
428 let generic_params = generics(db.upcast(), trait_.into()); 419 let generic_params = generics(db.upcast(), trait_.into());
@@ -444,7 +435,7 @@ pub(crate) fn trait_datum_query(
444 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name)); 435 lang_attr(db.upcast(), trait_).and_then(|name| well_known_trait_from_lang_attr(&name));
445 let trait_datum = TraitDatum { 436 let trait_datum = TraitDatum {
446 id: trait_id, 437 id: trait_id,
447 binders: make_binders(trait_datum_bound, bound_vars.len(&Interner)), 438 binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
448 flags, 439 flags,
449 associated_ty_ids, 440 associated_ty_ids,
450 well_known, 441 well_known,
@@ -513,7 +504,7 @@ pub(crate) fn struct_datum_query(
513 // FIXME set ADT kind 504 // FIXME set ADT kind
514 kind: rust_ir::AdtKind::Struct, 505 kind: rust_ir::AdtKind::Struct,
515 id: struct_id, 506 id: struct_id,
516 binders: make_binders(struct_datum_bound, num_params), 507 binders: make_only_type_binders(num_params, struct_datum_bound),
517 flags, 508 flags,
518 }; 509 };
519 Arc::new(struct_datum) 510 Arc::new(struct_datum)
@@ -561,7 +552,6 @@ fn impl_def_datum(
561 trait_ref.display(db), 552 trait_ref.display(db),
562 where_clauses 553 where_clauses
563 ); 554 );
564 let trait_ref = trait_ref.to_chalk(db);
565 555
566 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive }; 556 let polarity = if negative { rust_ir::Polarity::Negative } else { rust_ir::Polarity::Positive };
567 557
@@ -583,7 +573,7 @@ fn impl_def_datum(
583 .collect(); 573 .collect();
584 debug!("impl_datum: {:?}", impl_datum_bound); 574 debug!("impl_datum: {:?}", impl_datum_bound);
585 let impl_datum = ImplDatum { 575 let impl_datum = ImplDatum {
586 binders: make_binders(impl_datum_bound, bound_vars.len(&Interner)), 576 binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
587 impl_type, 577 impl_type,
588 polarity, 578 polarity,
589 associated_ty_value_ids, 579 associated_ty_value_ids,
@@ -622,7 +612,7 @@ fn type_alias_associated_ty_value(
622 .associated_type_by_name(&type_alias_data.name) 612 .associated_type_by_name(&type_alias_data.name)
623 .expect("assoc ty value should not exist"); // validated when building the impl data as well 613 .expect("assoc ty value should not exist"); // validated when building the impl data as well
624 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders(); 614 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
625 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.to_chalk(db) }; 615 let value_bound = rust_ir::AssociatedTyValueBound { ty };
626 let value = rust_ir::AssociatedTyValue { 616 let value = rust_ir::AssociatedTyValue {
627 impl_id: impl_id.to_chalk(db), 617 impl_id: impl_id.to_chalk(db),
628 associated_ty_id: to_assoc_type_id(assoc_ty), 618 associated_ty_id: to_assoc_type_id(assoc_ty),
@@ -643,13 +633,13 @@ pub(crate) fn fn_def_datum_query(
643 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
644 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
645 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
646 inputs_and_output: make_binders( 636 inputs_and_output: make_only_type_binders(
637 0,
647 rust_ir::FnDefInputsAndOutputDatum { 638 rust_ir::FnDefInputsAndOutputDatum {
648 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(db)).collect(), 639 argument_types: sig.params().iter().cloned().collect(),
649 return_type: sig.ret().clone().to_chalk(db), 640 return_type: sig.ret().clone(),
650 } 641 }
651 .shifted_in(&Interner), 642 .shifted_in(&Interner),
652 0,
653 ), 643 ),
654 where_clauses, 644 where_clauses,
655 }; 645 };
@@ -686,42 +676,65 @@ pub(crate) fn adt_variance_query(
686 ) 676 )
687} 677}
688 678
689impl From<FnDefId> for crate::db::InternedCallableDefId { 679pub(super) fn convert_where_clauses(
690 fn from(fn_def_id: FnDefId) -> Self { 680 db: &dyn HirDatabase,
691 InternKey::from_intern_id(fn_def_id.0) 681 def: GenericDefId,
692 } 682 substs: &Substitution,
693} 683) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
694 684 let generic_predicates = db.generic_predicates(def);
695impl From<crate::db::InternedCallableDefId> for FnDefId { 685 let mut result = Vec::with_capacity(generic_predicates.len());
696 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { 686 for pred in generic_predicates.iter() {
697 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 687 result.push(pred.clone().substitute(&Interner, substs));
698 } 688 }
699} 689 result
700
701impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
702 fn from(id: OpaqueTyId) -> Self {
703 InternKey::from_intern_id(id.0)
704 }
705}
706
707impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
708 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
709 chalk_ir::OpaqueTyId(id.as_intern_id())
710 }
711}
712
713impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
714 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
715 Self::from_intern_id(id.0)
716 }
717} 690}
718 691
719impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { 692pub(super) fn generic_predicate_to_inline_bound(
720 fn from(id: crate::db::InternedClosureId) -> Self { 693 db: &dyn HirDatabase,
721 chalk_ir::ClosureId(id.as_intern_id()) 694 pred: &QuantifiedWhereClause,
695 self_ty: &Ty,
696) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
697 // An InlineBound is like a GenericPredicate, except the self type is left out.
698 // We don't have a special type for this, but Chalk does.
699 let self_ty_shifted_in = self_ty.clone().shifted_in_from(&Interner, DebruijnIndex::ONE);
700 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
701 match pred {
702 WhereClause::Implemented(trait_ref) => {
703 if trait_ref.self_type_parameter(&Interner) != self_ty_shifted_in {
704 // we can only convert predicates back to type bounds if they
705 // have the expected self type
706 return None;
707 }
708 let args_no_self = trait_ref.substitution.as_slice(&Interner)[1..]
709 .iter()
710 .map(|ty| ty.clone().cast(&Interner))
711 .collect();
712 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
713 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
714 }
715 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
716 if projection_ty.self_type_parameter(&Interner) != self_ty_shifted_in {
717 return None;
718 }
719 let trait_ = projection_ty.trait_(db);
720 let args_no_self = projection_ty.substitution.as_slice(&Interner)[1..]
721 .iter()
722 .map(|ty| ty.clone().cast(&Interner))
723 .collect();
724 let alias_eq_bound = rust_ir::AliasEqBound {
725 value: ty.clone(),
726 trait_bound: rust_ir::TraitBound {
727 trait_id: to_chalk_trait_id(trait_),
728 args_no_self,
729 },
730 associated_ty_id: projection_ty.associated_ty_id,
731 parameters: Vec::new(), // FIXME we don't support generic associated types yet
732 };
733 Some(chalk_ir::Binders::new(
734 binders,
735 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
736 ))
737 }
738 _ => None,
722 } 739 }
723} 740}
724
725fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
726 crate::Binders::wrap_empty(value)
727}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index b7463366b..8c4542956 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,13 +1,305 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use crate::{Interner, Ty, TyKind}; 3use chalk_ir::Mutability;
4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6};
7
8use crate::{
9 db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
10 from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
11 CallableSig, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
12 Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
13};
4 14
5pub trait TyExt { 15pub trait TyExt {
6 fn is_unit(&self) -> bool; 16 fn is_unit(&self) -> bool;
17 fn is_never(&self) -> bool;
18 fn is_unknown(&self) -> bool;
19
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
21 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
24 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
25 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
26
27 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
28 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
29
30 fn strip_references(&self) -> &Ty;
31
32 /// If this is a `dyn Trait`, returns that trait.
33 fn dyn_trait(&self) -> Option<TraitId>;
34
35 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
36 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
37
38 /// FIXME: Get rid of this, it's not a good abstraction
39 fn equals_ctor(&self, other: &Ty) -> bool;
7} 40}
8 41
9impl TyExt for Ty { 42impl TyExt for Ty {
10 fn is_unit(&self) -> bool { 43 fn is_unit(&self) -> bool {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _)) 44 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 } 45 }
46
47 fn is_never(&self) -> bool {
48 matches!(self.kind(&Interner), TyKind::Never)
49 }
50
51 fn is_unknown(&self) -> bool {
52 matches!(self.kind(&Interner), TyKind::Error)
53 }
54
55 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
56 match self.kind(&Interner) {
57 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
58 _ => None,
59 }
60 }
61
62 fn as_tuple(&self) -> Option<&Substitution> {
63 match self.kind(&Interner) {
64 TyKind::Tuple(_, substs) => Some(substs),
65 _ => None,
66 }
67 }
68
69 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
70 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
71 Some(func)
72 } else {
73 None
74 }
75 }
76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
77 match self.kind(&Interner) {
78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
79 _ => None,
80 }
81 }
82
83 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
84 match self.kind(&Interner) {
85 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
86 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
87 _ => None,
88 }
89 }
90
91 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
92 match *self.kind(&Interner) {
93 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
94 TyKind::FnDef(callable, ..) => {
95 Some(db.lookup_intern_callable_def(callable.into()).into())
96 }
97 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
98 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
99 _ => None,
100 }
101 }
102
103 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
104 match self.kind(&Interner) {
105 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
106 _ => None,
107 }
108 }
109
110 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
111 match self.kind(&Interner) {
112 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
113 TyKind::FnDef(def, parameters) => {
114 let callable_def = db.lookup_intern_callable_def((*def).into());
115 let sig = db.callable_item_signature(callable_def);
116 Some(sig.substitute(&Interner, &parameters))
117 }
118 TyKind::Closure(.., substs) => {
119 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
120 sig_param.callable_sig(db)
121 }
122 _ => None,
123 }
124 }
125
126 fn dyn_trait(&self) -> Option<TraitId> {
127 let trait_ref = match self.kind(&Interner) {
128 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
129 match b.skip_binders() {
130 WhereClause::Implemented(trait_ref) => Some(trait_ref),
131 _ => None,
132 }
133 }),
134 _ => None,
135 }?;
136 Some(from_chalk_trait_id(trait_ref.trait_id))
137 }
138
139 fn strip_references(&self) -> &Ty {
140 let mut t: &Ty = self;
141 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
142 t = ty;
143 }
144 t
145 }
146
147 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
148 match self.kind(&Interner) {
149 TyKind::OpaqueType(opaque_ty_id, ..) => {
150 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
151 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
152 let krate = def.module(db.upcast()).krate();
153 if let Some(future_trait) = db
154 .lang_item(krate, "future_trait".into())
155 .and_then(|item| item.as_trait())
156 {
157 // This is only used by type walking.
158 // Parameters will be walked outside, and projection predicate is not used.
159 // So just provide the Future trait.
160 let impl_bound = Binders::empty(
161 &Interner,
162 WhereClause::Implemented(TraitRef {
163 trait_id: to_chalk_trait_id(future_trait),
164 substitution: Substitution::empty(&Interner),
165 }),
166 );
167 Some(vec![impl_bound])
168 } else {
169 None
170 }
171 }
172 ImplTraitId::ReturnTypeImplTrait(..) => None,
173 }
174 }
175 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
176 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
177 {
178 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
179 db.return_type_impl_traits(func).map(|it| {
180 let data = (*it)
181 .as_ref()
182 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
183 data.substitute(&Interner, &opaque_ty.substitution)
184 })
185 }
186 // It always has an parameter for Future::Output type.
187 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
188 };
189
190 predicates.map(|it| it.into_value_and_skipped_binders().0)
191 }
192 TyKind::Placeholder(idx) => {
193 let id = from_placeholder_idx(db, *idx);
194 let generic_params = db.generic_params(id.parent);
195 let param_data = &generic_params.types[id.local_id];
196 match param_data.provenance {
197 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
198 let substs = TyBuilder::type_params_subst(db, id.parent);
199 let predicates = db
200 .generic_predicates(id.parent)
201 .into_iter()
202 .map(|pred| pred.clone().substitute(&Interner, &substs))
203 .filter(|wc| match &wc.skip_binders() {
204 WhereClause::Implemented(tr) => {
205 &tr.self_type_parameter(&Interner) == self
206 }
207 WhereClause::AliasEq(AliasEq {
208 alias: AliasTy::Projection(proj),
209 ty: _,
210 }) => &proj.self_type_parameter(&Interner) == self,
211 _ => false,
212 })
213 .collect::<Vec<_>>();
214
215 Some(predicates)
216 }
217 _ => None,
218 }
219 }
220 _ => None,
221 }
222 }
223
224 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
225 match self.kind(&Interner) {
226 TyKind::AssociatedType(id, ..) => {
227 match from_assoc_type_id(*id).lookup(db.upcast()).container {
228 AssocContainerId::TraitId(trait_id) => Some(trait_id),
229 _ => None,
230 }
231 }
232 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
233 match from_assoc_type_id(projection_ty.associated_ty_id)
234 .lookup(db.upcast())
235 .container
236 {
237 AssocContainerId::TraitId(trait_id) => Some(trait_id),
238 _ => None,
239 }
240 }
241 _ => None,
242 }
243 }
244
245 fn equals_ctor(&self, other: &Ty) -> bool {
246 match (self.kind(&Interner), other.kind(&Interner)) {
247 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
248 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
249 true
250 }
251 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
252 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
253 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
254 ty_id == ty_id2
255 }
256 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
257 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
258 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
259 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
260 mutability == mutability2
261 }
262 (
263 TyKind::Function(FnPointer { num_binders, sig, .. }),
264 TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }),
265 ) => num_binders == num_binders2 && sig == sig2,
266 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
267 cardinality == cardinality2
268 }
269 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
270 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
271 _ => false,
272 }
273 }
274}
275
276pub trait ProjectionTyExt {
277 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
278 fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
279}
280
281impl ProjectionTyExt for ProjectionTy {
282 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
283 TraitRef {
284 trait_id: to_chalk_trait_id(self.trait_(db)),
285 substitution: self.substitution.clone(),
286 }
287 }
288
289 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
290 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
291 AssocContainerId::TraitId(it) => it,
292 _ => panic!("projection ty without parent trait"),
293 }
294 }
295}
296
297pub trait TraitRefExt {
298 fn hir_trait_id(&self) -> TraitId;
299}
300
301impl TraitRefExt for TraitRef {
302 fn hir_trait_id(&self) -> TraitId {
303 from_chalk_trait_id(self.trait_id)
304 }
13} 305}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 4300680d9..1690926ad 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -1,18 +1,19 @@
1//! FIXME: write short doc here 1//! The home of `HirDatabase`, which is the Salsa database containing all the
2//! type inference-related queries.
2 3
3use std::sync::Arc; 4use std::sync::Arc;
4 5
5use base_db::{impl_intern_key, salsa, CrateId, Upcast}; 6use base_db::{impl_intern_key, salsa, CrateId, Upcast};
6use hir_def::{ 7use hir_def::{
7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, 8 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
8 LocalFieldId, TypeParamId, VariantId, 9 LifetimeParamId, LocalFieldId, TypeParamId, VariantId,
9}; 10};
10use la_arena::ArenaMap; 11use la_arena::ArenaMap;
11 12
12use crate::{ 13use crate::{
14 chalk_db,
13 method_resolution::{InherentImpls, TraitImpls}, 15 method_resolution::{InherentImpls, TraitImpls},
14 traits::chalk, 16 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, Interner, PolyFnSig,
15 Binders, CallableDefId, FnDefId, ImplTraitId, InferenceResult, PolyFnSig,
16 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId, 17 QuantifiedWhereClause, ReturnTypeImplTraits, TraitRef, Ty, TyDefId, ValueTyDefId,
17}; 18};
18use hir_expand::name::Name; 19use hir_expand::name::Name;
@@ -86,37 +87,46 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
86 #[salsa::interned] 87 #[salsa::interned]
87 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId; 88 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId;
88 #[salsa::interned] 89 #[salsa::interned]
90 fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
91 #[salsa::interned]
92 fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId;
93 #[salsa::interned]
89 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; 94 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
90 #[salsa::interned] 95 #[salsa::interned]
91 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; 96 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
92 97
93 #[salsa::invoke(chalk::associated_ty_data_query)] 98 #[salsa::invoke(chalk_db::associated_ty_data_query)]
94 fn associated_ty_data(&self, id: chalk::AssocTypeId) -> Arc<chalk::AssociatedTyDatum>; 99 fn associated_ty_data(&self, id: chalk_db::AssocTypeId) -> Arc<chalk_db::AssociatedTyDatum>;
95 100
96 #[salsa::invoke(chalk::trait_datum_query)] 101 #[salsa::invoke(chalk_db::trait_datum_query)]
97 fn trait_datum(&self, krate: CrateId, trait_id: chalk::TraitId) -> Arc<chalk::TraitDatum>; 102 fn trait_datum(&self, krate: CrateId, trait_id: chalk_db::TraitId)
103 -> Arc<chalk_db::TraitDatum>;
98 104
99 #[salsa::invoke(chalk::struct_datum_query)] 105 #[salsa::invoke(chalk_db::struct_datum_query)]
100 fn struct_datum(&self, krate: CrateId, struct_id: chalk::AdtId) -> Arc<chalk::StructDatum>; 106 fn struct_datum(
107 &self,
108 krate: CrateId,
109 struct_id: chalk_db::AdtId,
110 ) -> Arc<chalk_db::StructDatum>;
101 111
102 #[salsa::invoke(crate::traits::chalk::impl_datum_query)] 112 #[salsa::invoke(chalk_db::impl_datum_query)]
103 fn impl_datum(&self, krate: CrateId, impl_id: chalk::ImplId) -> Arc<chalk::ImplDatum>; 113 fn impl_datum(&self, krate: CrateId, impl_id: chalk_db::ImplId) -> Arc<chalk_db::ImplDatum>;
104 114
105 #[salsa::invoke(crate::traits::chalk::fn_def_datum_query)] 115 #[salsa::invoke(chalk_db::fn_def_datum_query)]
106 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk::FnDefDatum>; 116 fn fn_def_datum(&self, krate: CrateId, fn_def_id: FnDefId) -> Arc<chalk_db::FnDefDatum>;
107 117
108 #[salsa::invoke(crate::traits::chalk::fn_def_variance_query)] 118 #[salsa::invoke(chalk_db::fn_def_variance_query)]
109 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk::Variances; 119 fn fn_def_variance(&self, krate: CrateId, fn_def_id: FnDefId) -> chalk_db::Variances;
110 120
111 #[salsa::invoke(crate::traits::chalk::adt_variance_query)] 121 #[salsa::invoke(chalk_db::adt_variance_query)]
112 fn adt_variance(&self, krate: CrateId, adt_id: chalk::AdtId) -> chalk::Variances; 122 fn adt_variance(&self, krate: CrateId, adt_id: chalk_db::AdtId) -> chalk_db::Variances;
113 123
114 #[salsa::invoke(crate::traits::chalk::associated_ty_value_query)] 124 #[salsa::invoke(chalk_db::associated_ty_value_query)]
115 fn associated_ty_value( 125 fn associated_ty_value(
116 &self, 126 &self,
117 krate: CrateId, 127 krate: CrateId,
118 id: chalk::AssociatedTyValueId, 128 id: chalk_db::AssociatedTyValueId,
119 ) -> Arc<chalk::AssociatedTyValue>; 129 ) -> Arc<chalk_db::AssociatedTyValue>;
120 130
121 #[salsa::invoke(crate::traits::trait_solve_query)] 131 #[salsa::invoke(crate::traits::trait_solve_query)]
122 fn trait_solve( 132 fn trait_solve(
@@ -125,12 +135,12 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 135 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
126 ) -> Option<crate::Solution>; 136 ) -> Option<crate::Solution>;
127 137
128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 138 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
129 fn program_clauses_for_chalk_env( 139 fn program_clauses_for_chalk_env(
130 &self, 140 &self,
131 krate: CrateId, 141 krate: CrateId,
132 env: chalk_ir::Environment<chalk::Interner>, 142 env: chalk_ir::Environment<Interner>,
133 ) -> chalk_ir::ProgramClauses<chalk::Interner>; 143 ) -> chalk_ir::ProgramClauses<Interner>;
134} 144}
135 145
136fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { 146fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
@@ -156,6 +166,14 @@ pub struct InternedTypeParamId(salsa::InternId);
156impl_intern_key!(InternedTypeParamId); 166impl_intern_key!(InternedTypeParamId);
157 167
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 168#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
169pub struct InternedLifetimeParamId(salsa::InternId);
170impl_intern_key!(InternedLifetimeParamId);
171
172#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
173pub struct InternedConstParamId(salsa::InternId);
174impl_intern_key!(InternedConstParamId);
175
176#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub struct InternedOpaqueTyId(salsa::InternId); 177pub struct InternedOpaqueTyId(salsa::InternId);
160impl_intern_key!(InternedOpaqueTyId); 178impl_intern_key!(InternedOpaqueTyId);
161 179
diff --git a/crates/hir_ty/src/diagnostics.rs b/crates/hir_ty/src/diagnostics.rs
index 86f937e1d..84fc8ce14 100644
--- a/crates/hir_ty/src/diagnostics.rs
+++ b/crates/hir_ty/src/diagnostics.rs
@@ -1,4 +1,4 @@
1//! FIXME: write short doc here 1//! Type inference-based diagnostics.
2mod expr; 2mod expr;
3mod match_check; 3mod match_check;
4mod unsafe_check; 4mod unsafe_check;
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index db278d0db..79602c3dd 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -14,7 +14,6 @@ use crate::{
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data,
18 AdtId, InferenceResult, Interner, TyExt, TyKind, 17 AdtId, InferenceResult, Interner, TyExt, TyKind,
19}; 18};
20 19
@@ -104,7 +103,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
104 let root = source_ptr.file_syntax(db.upcast()); 103 let root = source_ptr.file_syntax(db.upcast());
105 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { 104 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) {
106 if let Some(_) = record_expr.record_expr_field_list() { 105 if let Some(_) = record_expr.record_expr_field_list() {
107 let variant_data = variant_data(db.upcast(), variant_def); 106 let variant_data = variant_def.variant_data(db.upcast());
108 let missed_fields = missed_fields 107 let missed_fields = missed_fields
109 .into_iter() 108 .into_iter()
110 .map(|idx| variant_data.fields()[idx].name.clone()) 109 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -135,7 +134,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
135 let root = source_ptr.file_syntax(db.upcast()); 134 let root = source_ptr.file_syntax(db.upcast());
136 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { 135 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
137 if let Some(_) = record_pat.record_pat_field_list() { 136 if let Some(_) = record_pat.record_pat_field_list() {
138 let variant_data = variant_data(db.upcast(), variant_def); 137 let variant_data = variant_def.variant_data(db.upcast());
139 let missed_fields = missed_fields 138 let missed_fields = missed_fields
140 .into_iter() 139 .into_iter()
141 .map(|idx| variant_data.fields()[idx].name.clone()) 140 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -315,7 +314,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
315 if pat_ty == match_expr_ty 314 if pat_ty == match_expr_ty
316 || match_expr_ty 315 || match_expr_ty
317 .as_reference() 316 .as_reference()
318 .map(|(match_expr_ty, _)| match_expr_ty == pat_ty) 317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
319 .unwrap_or(false) 318 .unwrap_or(false)
320 { 319 {
321 // If we had a NotUsefulMatchArm diagnostic, we could 320 // If we had a NotUsefulMatchArm diagnostic, we could
@@ -453,7 +452,7 @@ pub fn record_literal_missing_fields(
453 return None; 452 return None;
454 } 453 }
455 454
456 let variant_data = variant_data(db.upcast(), variant_def); 455 let variant_data = variant_def.variant_data(db.upcast());
457 456
458 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
459 let missed_fields: Vec<LocalFieldId> = variant_data 458 let missed_fields: Vec<LocalFieldId> = variant_data
@@ -483,7 +482,7 @@ pub fn record_pattern_missing_fields(
483 return None; 482 return None;
484 } 483 }
485 484
486 let variant_data = variant_data(db.upcast(), variant_def); 485 let variant_data = variant_def.variant_data(db.upcast());
487 486
488 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
489 let missed_fields: Vec<LocalFieldId> = variant_data 488 let missed_fields: Vec<LocalFieldId> = variant_data
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 34291578a..e9762622f 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index b5efe9df5..ed97dc0e3 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,9 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; 14use crate::{
15 db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind,
16};
15 17
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 19 owner: DefWithBodyId,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index f31e6b108..e7c9dabc2 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,8 +1,13 @@
1//! FIXME: write short doc here 1//! The `HirDisplay` trait, which serves two purposes: Turning various bits from
2//! HIR back into source code, and just displaying them for debugging/testing
3//! purposes.
2 4
3use std::{array, fmt}; 5use std::{
6 array,
7 fmt::{self, Debug},
8};
4 9
5use chalk_ir::Mutability; 10use chalk_ir::BoundVar;
6use hir_def::{ 11use hir_def::{
7 db::DefDatabase, 12 db::DefDatabase,
8 find_path, 13 find_path,
@@ -16,10 +21,12 @@ use hir_def::{
16use hir_expand::name::Name; 21use hir_expand::name::Name;
17 22
18use crate::{ 23use crate::{
19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 24 const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
20 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, 25 from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, primitive, subst_prefix,
21 CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, 26 to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const,
22 ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, 27 ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
28 LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
29 Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
23}; 30};
24 31
25pub struct HirFormatter<'a> { 32pub struct HirFormatter<'a> {
@@ -46,6 +53,10 @@ pub trait HirDisplay {
46 where 53 where
47 Self: Sized, 54 Self: Sized,
48 { 55 {
56 assert!(
57 !matches!(display_target, DisplayTarget::SourceCode { .. }),
58 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
59 );
49 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target } 60 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
50 } 61 }
51 62
@@ -230,7 +241,7 @@ where
230 Err(HirDisplayError::FmtError) => Err(fmt::Error), 241 Err(HirDisplayError::FmtError) => Err(fmt::Error),
231 Err(HirDisplayError::DisplaySourceCodeError(_)) => { 242 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
232 // This should never happen 243 // This should never happen
233 panic!("HirDisplay failed when calling Display::fmt!") 244 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
234 } 245 }
235 } 246 }
236 } 247 }
@@ -251,16 +262,12 @@ impl HirDisplay for ProjectionTy {
251 } 262 }
252 263
253 let trait_ = f.db.trait_data(self.trait_(f.db)); 264 let trait_ = f.db.trait_data(self.trait_(f.db));
254 let first_parameter = self.self_type_parameter(&Interner).into_displayable( 265 write!(f, "<")?;
255 f.db, 266 self.self_type_parameter(&Interner).hir_fmt(f)?;
256 f.max_size, 267 write!(f, " as {}", trait_.name)?;
257 f.omit_verbose_types,
258 f.display_target,
259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len(&Interner) > 1 { 268 if self.substitution.len(&Interner) > 1 {
262 write!(f, "<")?; 269 write!(f, "<")?;
263 f.write_joined(&self.substitution.interned()[1..], ", ")?; 270 f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
264 write!(f, ">")?; 271 write!(f, ">")?;
265 } 272 }
266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 273 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -282,10 +289,35 @@ impl HirDisplay for GenericArg {
282 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 289 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
283 match self.interned() { 290 match self.interned() {
284 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), 291 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
292 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
293 crate::GenericArgData::Const(c) => c.hir_fmt(f),
294 }
295 }
296}
297
298impl HirDisplay for Const {
299 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
300 let data = self.interned();
301 match data.value {
302 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
303 ConstValue::InferenceVar(..) => write!(f, "_"),
304 ConstValue::Placeholder(idx) => {
305 let id = const_from_placeholder_idx(f.db, idx);
306 let generics = generics(f.db.upcast(), id.parent);
307 let param_data = &generics.params.consts[id.local_id];
308 write!(f, "{}", param_data.name)
309 }
310 ConstValue::Concrete(_) => write!(f, "_"),
285 } 311 }
286 } 312 }
287} 313}
288 314
315impl HirDisplay for BoundVar {
316 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
317 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
318 }
319}
320
289impl HirDisplay for Ty { 321impl HirDisplay for Ty {
290 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 322 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
291 if f.should_truncate() { 323 if f.should_truncate() {
@@ -305,15 +337,14 @@ impl HirDisplay for Ty {
305 t.hir_fmt(f)?; 337 t.hir_fmt(f)?;
306 write!(f, "]")?; 338 write!(f, "]")?;
307 } 339 }
308 TyKind::Array(t) => { 340 TyKind::Array(t, c) => {
309 write!(f, "[")?; 341 write!(f, "[")?;
310 t.hir_fmt(f)?; 342 t.hir_fmt(f)?;
311 write!(f, "; _]")?; 343 write!(f, "; ")?;
344 c.hir_fmt(f)?;
345 write!(f, "]")?;
312 } 346 }
313 TyKind::Raw(m, t) | TyKind::Ref(m, t) => { 347 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
314 let ty_display =
315 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
316
317 if matches!(self.kind(&Interner), TyKind::Raw(..)) { 348 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
318 write!( 349 write!(
319 f, 350 f,
@@ -368,16 +399,16 @@ impl HirDisplay for Ty {
368 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) 399 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
369 && predicates.len() <= 2 400 && predicates.len() <= 2
370 { 401 {
371 return write!(f, "{}", ty_display); 402 return t.hir_fmt(f);
372 } 403 }
373 } 404 }
374 405
375 if predicates.len() > 1 { 406 if predicates.len() > 1 {
376 write!(f, "(")?; 407 write!(f, "(")?;
377 write!(f, "{}", ty_display)?; 408 t.hir_fmt(f)?;
378 write!(f, ")")?; 409 write!(f, ")")?;
379 } else { 410 } else {
380 write!(f, "{}", ty_display)?; 411 t.hir_fmt(f)?;
381 } 412 }
382 } 413 }
383 TyKind::Tuple(_, substs) => { 414 TyKind::Tuple(_, substs) => {
@@ -387,7 +418,7 @@ impl HirDisplay for Ty {
387 write!(f, ",)")?; 418 write!(f, ",)")?;
388 } else { 419 } else {
389 write!(f, "(")?; 420 write!(f, "(")?;
390 f.write_joined(&*substs.interned(), ", ")?; 421 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
391 write!(f, ")")?; 422 write!(f, ")")?;
392 } 423 }
393 } 424 }
@@ -415,7 +446,7 @@ impl HirDisplay for Ty {
415 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 446 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
416 if total_len > 0 { 447 if total_len > 0 {
417 write!(f, "<")?; 448 write!(f, "<")?;
418 f.write_joined(&parameters.interned()[..total_len], ", ")?; 449 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
419 write!(f, ">")?; 450 write!(f, ">")?;
420 } 451 }
421 } 452 }
@@ -424,14 +455,8 @@ impl HirDisplay for Ty {
424 write!(f, ")")?; 455 write!(f, ")")?;
425 let ret = sig.ret(); 456 let ret = sig.ret();
426 if !ret.is_unit() { 457 if !ret.is_unit() {
427 let ret_display = ret.into_displayable( 458 write!(f, " -> ")?;
428 f.db, 459 ret.hir_fmt(f)?;
429 f.max_size,
430 f.omit_verbose_types,
431 f.display_target,
432 );
433
434 write!(f, " -> {}", ret_display)?;
435 } 460 }
436 } 461 }
437 TyKind::Adt(AdtId(def_id), parameters) => { 462 TyKind::Adt(AdtId(def_id), parameters) => {
@@ -468,7 +493,7 @@ impl HirDisplay for Ty {
468 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 493 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
469 .filter(|defaults| !defaults.is_empty()) 494 .filter(|defaults| !defaults.is_empty())
470 { 495 {
471 None => parameters.interned().as_ref(), 496 None => parameters.as_slice(&Interner),
472 Some(default_parameters) => { 497 Some(default_parameters) => {
473 let mut default_from = 0; 498 let mut default_from = 0;
474 for (i, parameter) in parameters.iter(&Interner).enumerate() { 499 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -480,9 +505,11 @@ impl HirDisplay for Ty {
480 default_from = i + 1; 505 default_from = i + 1;
481 } 506 }
482 (_, Some(default_parameter)) => { 507 (_, Some(default_parameter)) => {
483 let actual_default = default_parameter 508 let actual_default =
484 .clone() 509 default_parameter.clone().substitute(
485 .substitute(&Interner, &parameters.prefix(i)); 510 &Interner,
511 &subst_prefix(parameters, i),
512 );
486 if parameter.assert_ty_ref(&Interner) != &actual_default 513 if parameter.assert_ty_ref(&Interner) != &actual_default
487 { 514 {
488 default_from = i + 1; 515 default_from = i + 1;
@@ -490,11 +517,11 @@ impl HirDisplay for Ty {
490 } 517 }
491 } 518 }
492 } 519 }
493 &parameters.interned()[0..default_from] 520 &parameters.as_slice(&Interner)[0..default_from]
494 } 521 }
495 } 522 }
496 } else { 523 } else {
497 parameters.interned().as_ref() 524 parameters.as_slice(&Interner)
498 }; 525 };
499 if !parameters_to_write.is_empty() { 526 if !parameters_to_write.is_empty() {
500 write!(f, "<")?; 527 write!(f, "<")?;
@@ -517,7 +544,7 @@ impl HirDisplay for Ty {
517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 544 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
518 if parameters.len(&Interner) > 0 { 545 if parameters.len(&Interner) > 0 {
519 write!(f, "<")?; 546 write!(f, "<")?;
520 f.write_joined(&*parameters.interned(), ", ")?; 547 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
521 write!(f, ">")?; 548 write!(f, ">")?;
522 } 549 }
523 } else { 550 } else {
@@ -571,13 +598,8 @@ impl HirDisplay for Ty {
571 write!(f, "|")?; 598 write!(f, "|")?;
572 }; 599 };
573 600
574 let ret_display = sig.ret().into_displayable( 601 write!(f, " -> ")?;
575 f.db, 602 sig.ret().hir_fmt(f)?;
576 f.max_size,
577 f.omit_verbose_types,
578 f.display_target,
579 );
580 write!(f, " -> {}", ret_display)?;
581 } else { 603 } else {
582 write!(f, "{{closure}}")?; 604 write!(f, "{{closure}}")?;
583 } 605 }
@@ -598,12 +620,12 @@ impl HirDisplay for Ty {
598 .map(|pred| pred.clone().substitute(&Interner, &substs)) 620 .map(|pred| pred.clone().substitute(&Interner, &substs))
599 .filter(|wc| match &wc.skip_binders() { 621 .filter(|wc| match &wc.skip_binders() {
600 WhereClause::Implemented(tr) => { 622 WhereClause::Implemented(tr) => {
601 tr.self_type_parameter(&Interner) == self 623 &tr.self_type_parameter(&Interner) == self
602 } 624 }
603 WhereClause::AliasEq(AliasEq { 625 WhereClause::AliasEq(AliasEq {
604 alias: AliasTy::Projection(proj), 626 alias: AliasTy::Projection(proj),
605 ty: _, 627 ty: _,
606 }) => proj.self_type_parameter(&Interner) == self, 628 }) => &proj.self_type_parameter(&Interner) == self,
607 _ => false, 629 _ => false,
608 }) 630 })
609 .collect::<Vec<_>>(); 631 .collect::<Vec<_>>();
@@ -611,7 +633,7 @@ impl HirDisplay for Ty {
611 } 633 }
612 } 634 }
613 } 635 }
614 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 636 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
615 TyKind::Dyn(dyn_ty) => { 637 TyKind::Dyn(dyn_ty) => {
616 write_bounds_like_dyn_trait_with_prefix( 638 write_bounds_like_dyn_trait_with_prefix(
617 "dyn", 639 "dyn",
@@ -646,6 +668,8 @@ impl HirDisplay for Ty {
646 write!(f, "{{unknown}}")?; 668 write!(f, "{{unknown}}")?;
647 } 669 }
648 TyKind::InferenceVar(..) => write!(f, "_")?, 670 TyKind::InferenceVar(..) => write!(f, "_")?,
671 TyKind::Generator(..) => write!(f, "{{generator}}")?,
672 TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
649 } 673 }
650 Ok(()) 674 Ok(())
651 } 675 }
@@ -665,9 +689,8 @@ impl HirDisplay for CallableSig {
665 write!(f, ")")?; 689 write!(f, ")")?;
666 let ret = self.ret(); 690 let ret = self.ret();
667 if !ret.is_unit() { 691 if !ret.is_unit() {
668 let ret_display = 692 write!(f, " -> ")?;
669 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 693 ret.hir_fmt(f)?;
670 write!(f, " -> {}", ret_display)?;
671 } 694 }
672 Ok(()) 695 Ok(())
673 } 696 }
@@ -724,17 +747,17 @@ fn write_bounds_like_dyn_trait(
724 if !first { 747 if !first {
725 write!(f, " + ")?; 748 write!(f, " + ")?;
726 } 749 }
727 // We assume that the self type is $0 (i.e. the 750 // We assume that the self type is ^0.0 (i.e. the
728 // existential) here, which is the only thing that's 751 // existential) here, which is the only thing that's
729 // possible in actual Rust, and hence don't print it 752 // possible in actual Rust, and hence don't print it
730 write!(f, "{}", f.db.trait_data(trait_).name)?; 753 write!(f, "{}", f.db.trait_data(trait_).name)?;
731 if let [_, params @ ..] = &*trait_ref.substitution.interned() { 754 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
732 if is_fn_trait { 755 if is_fn_trait {
733 if let Some(args) = 756 if let Some(args) =
734 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 757 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
735 { 758 {
736 write!(f, "(")?; 759 write!(f, "(")?;
737 f.write_joined(&*args.interned(), ", ")?; 760 f.write_joined(args.as_slice(&Interner), ", ")?;
738 write!(f, ")")?; 761 write!(f, ")")?;
739 } 762 }
740 } else if !params.is_empty() { 763 } else if !params.is_empty() {
@@ -766,6 +789,10 @@ fn write_bounds_like_dyn_trait(
766 } 789 }
767 ty.hir_fmt(f)?; 790 ty.hir_fmt(f)?;
768 } 791 }
792
793 // FIXME implement these
794 WhereClause::LifetimeOutlives(_) => {}
795 WhereClause::TypeOutlives(_) => {}
769 } 796 }
770 first = false; 797 first = false;
771 } 798 }
@@ -775,31 +802,29 @@ fn write_bounds_like_dyn_trait(
775 Ok(()) 802 Ok(())
776} 803}
777 804
778impl TraitRef { 805fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
779 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> { 806 if f.should_truncate() {
780 if f.should_truncate() { 807 return write!(f, "{}", TYPE_HINT_TRUNCATION);
781 return write!(f, "{}", TYPE_HINT_TRUNCATION); 808 }
782 }
783 809
784 self.self_type_parameter(&Interner).hir_fmt(f)?; 810 tr.self_type_parameter(&Interner).hir_fmt(f)?;
785 if use_as { 811 if use_as {
786 write!(f, " as ")?; 812 write!(f, " as ")?;
787 } else { 813 } else {
788 write!(f, ": ")?; 814 write!(f, ": ")?;
789 }
790 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
791 if self.substitution.len(&Interner) > 1 {
792 write!(f, "<")?;
793 f.write_joined(&self.substitution.interned()[1..], ", ")?;
794 write!(f, ">")?;
795 }
796 Ok(())
797 } 815 }
816 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
817 if tr.substitution.len(&Interner) > 1 {
818 write!(f, "<")?;
819 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
820 write!(f, ">")?;
821 }
822 Ok(())
798} 823}
799 824
800impl HirDisplay for TraitRef { 825impl HirDisplay for TraitRef {
801 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 826 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
802 self.hir_fmt_ext(f, false) 827 fmt_trait_ref(self, f, false)
803 } 828 }
804} 829}
805 830
@@ -813,7 +838,7 @@ impl HirDisplay for WhereClause {
813 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 838 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
814 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 839 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
815 write!(f, "<")?; 840 write!(f, "<")?;
816 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 841 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
817 write!( 842 write!(
818 f, 843 f,
819 ">::{} = ", 844 ">::{} = ",
@@ -822,20 +847,44 @@ impl HirDisplay for WhereClause {
822 ty.hir_fmt(f)?; 847 ty.hir_fmt(f)?;
823 } 848 }
824 WhereClause::AliasEq(_) => write!(f, "{{error}}")?, 849 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
850
851 // FIXME implement these
852 WhereClause::TypeOutlives(..) => {}
853 WhereClause::LifetimeOutlives(..) => {}
825 } 854 }
826 Ok(()) 855 Ok(())
827 } 856 }
828} 857}
829 858
859impl HirDisplay for LifetimeOutlives {
860 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
861 self.a.hir_fmt(f)?;
862 write!(f, ": ")?;
863 self.b.hir_fmt(f)
864 }
865}
866
830impl HirDisplay for Lifetime { 867impl HirDisplay for Lifetime {
831 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 868 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
869 self.interned().hir_fmt(f)
870 }
871}
872
873impl HirDisplay for LifetimeData {
874 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
832 match self { 875 match self {
833 Lifetime::Parameter(id) => { 876 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
877 LifetimeData::InferenceVar(_) => write!(f, "_"),
878 LifetimeData::Placeholder(idx) => {
879 let id = lt_from_placeholder_idx(f.db, *idx);
834 let generics = generics(f.db.upcast(), id.parent); 880 let generics = generics(f.db.upcast(), id.parent);
835 let param_data = &generics.params.lifetimes[id.local_id]; 881 let param_data = &generics.params.lifetimes[id.local_id];
836 write!(f, "{}", &param_data.name) 882 write!(f, "{}", param_data.name)
837 } 883 }
838 Lifetime::Static => write!(f, "'static"), 884 LifetimeData::Static => write!(f, "'static"),
885 LifetimeData::Empty(_) => Ok(()),
886 LifetimeData::Erased => Ok(()),
887 LifetimeData::Phantom(_, _) => Ok(()),
839 } 888 }
840 } 889 }
841} 890}
@@ -846,9 +895,11 @@ impl HirDisplay for DomainGoal {
846 DomainGoal::Holds(wc) => { 895 DomainGoal::Holds(wc) => {
847 write!(f, "Holds(")?; 896 write!(f, "Holds(")?;
848 wc.hir_fmt(f)?; 897 wc.hir_fmt(f)?;
849 write!(f, ")") 898 write!(f, ")")?;
850 } 899 }
900 _ => write!(f, "?")?,
851 } 901 }
902 Ok(())
852 } 903 }
853} 904}
854 905
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 1c3faf5cb..bf2da2d4a 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::{cast::Cast, Mutability}; 21use chalk_ir::{cast::Cast, DebruijnIndex, Mutability};
22use hir_def::{ 22use hir_def::{
23 body::Body, 23 body::Body,
24 data::{ConstData, FunctionData, StaticData}, 24 data::{ConstData, FunctionData, StaticData},
@@ -38,11 +38,11 @@ use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 TypeWalk,
42}; 41};
43use crate::{ 42use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 43 db::HirDatabase, fold_tys, infer::diagnostics::InferenceDiagnostic,
45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, 44 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
45 TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -131,10 +131,7 @@ pub struct InferenceResult {
131 method_resolutions: FxHashMap<ExprId, FunctionId>, 131 method_resolutions: FxHashMap<ExprId, FunctionId>,
132 /// For each field access expr, records the field it resolves to. 132 /// For each field access expr, records the field it resolves to.
133 field_resolutions: FxHashMap<ExprId, FieldId>, 133 field_resolutions: FxHashMap<ExprId, FieldId>,
134 /// For each field in record literal, records the field it resolves to. 134 /// For each struct literal or pattern, records the variant it resolves to.
135 record_field_resolutions: FxHashMap<ExprId, FieldId>,
136 record_pat_field_resolutions: FxHashMap<PatId, FieldId>,
137 /// For each struct literal, records the variant it resolves to.
138 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, 135 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
139 /// For each associated item record what it resolves to 136 /// For each associated item record what it resolves to
140 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, 137 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
@@ -153,12 +150,6 @@ impl InferenceResult {
153 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { 150 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
154 self.field_resolutions.get(&expr).copied() 151 self.field_resolutions.get(&expr).copied()
155 } 152 }
156 pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> {
157 self.record_field_resolutions.get(&expr).copied()
158 }
159 pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> {
160 self.record_pat_field_resolutions.get(&pat).copied()
161 }
162 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { 153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
163 self.variant_resolutions.get(&id.into()).copied() 154 self.variant_resolutions.get(&id.into()).copied()
164 } 155 }
@@ -332,7 +323,7 @@ impl<'a> InferenceContext<'a> {
332 } 323 }
333 324
334 fn insert_type_vars(&mut self, ty: Ty) -> Ty { 325 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
335 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 326 fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
336 } 327 }
337 328
338 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
@@ -345,17 +336,24 @@ impl<'a> InferenceContext<'a> {
345 self.last_obligations_check = Some(self.table.revision); 336 self.last_obligations_check = Some(self.table.revision);
346 let obligations = mem::replace(&mut self.obligations, Vec::new()); 337 let obligations = mem::replace(&mut self.obligations, Vec::new());
347 for obligation in obligations { 338 for obligation in obligations {
348 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 339 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
349 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
350 let solution = 341 let solution =
351 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
352 343
353 match solution { 344 match solution {
354 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
355 canonicalized.apply_solution(self, substs.0); 346 canonicalized.apply_solution(
347 self,
348 Canonical {
349 binders: canonical_subst.binders,
350 // FIXME: handle constraints
351 value: canonical_subst.value.subst,
352 },
353 );
356 } 354 }
357 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
358 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
359 self.obligations.push(obligation); 357 self.obligations.push(obligation);
360 } 358 }
361 Some(_) => { 359 Some(_) => {
@@ -436,12 +434,16 @@ impl<'a> InferenceContext<'a> {
436 /// to do it as well. 434 /// to do it as well.
437 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
438 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
439 ty.fold(&mut |ty| match ty.kind(&Interner) { 437 fold_tys(
440 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 ty,
441 self.normalize_projection_ty(proj_ty.clone()) 439 |ty, _| match ty.kind(&Interner) {
442 } 440 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
443 _ => ty, 441 self.normalize_projection_ty(proj_ty.clone())
444 }) 442 }
443 _ => ty,
444 },
445 DebruijnIndex::INNERMOST,
446 )
445 } 447 }
446 448
447 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 449 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
@@ -489,36 +491,13 @@ impl<'a> InferenceContext<'a> {
489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 491 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
490 let substs = generics.type_params_subst(self.db); 492 let substs = generics.type_params_subst(self.db);
491 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs); 493 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
492 match unresolved { 494 self.resolve_variant_on_alias(ty, unresolved, path)
493 None => {
494 let variant = ty_variant(&ty);
495 (ty, variant)
496 }
497 Some(1) => {
498 let segment = path.mod_path().segments().last().unwrap();
499 // this could be an enum variant or associated type
500 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
501 let enum_data = self.db.enum_data(enum_id);
502 if let Some(local_id) = enum_data.variant(segment) {
503 let variant = EnumVariantId { parent: enum_id, local_id };
504 return (ty, Some(variant.into()));
505 }
506 }
507 // FIXME potentially resolve assoc type
508 (self.err_ty(), None)
509 }
510 Some(_) => {
511 // FIXME diagnostic
512 (self.err_ty(), None)
513 }
514 }
515 } 495 }
516 TypeNs::TypeAliasId(it) => { 496 TypeNs::TypeAliasId(it) => {
517 let ty = TyBuilder::def_ty(self.db, it.into()) 497 let ty = TyBuilder::def_ty(self.db, it.into())
518 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 498 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
519 .build(); 499 .build();
520 let variant = ty_variant(&ty); 500 self.resolve_variant_on_alias(ty, unresolved, path)
521 forbid_unresolved_segments((ty, variant), unresolved)
522 } 501 }
523 TypeNs::AdtSelfType(_) => { 502 TypeNs::AdtSelfType(_) => {
524 // FIXME this could happen in array size expressions, once we're checking them 503 // FIXME this could happen in array size expressions, once we're checking them
@@ -545,16 +524,43 @@ impl<'a> InferenceContext<'a> {
545 (TyKind::Error.intern(&Interner), None) 524 (TyKind::Error.intern(&Interner), None)
546 } 525 }
547 } 526 }
527 }
548 528
549 fn ty_variant(ty: &Ty) -> Option<VariantId> { 529 fn resolve_variant_on_alias(
550 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 530 &mut self,
551 AdtId::StructId(s) => Some(VariantId::StructId(s)), 531 ty: Ty,
552 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 532 unresolved: Option<usize>,
553 AdtId::EnumId(_) => { 533 path: &Path,
554 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` 534 ) -> (Ty, Option<VariantId>) {
555 None 535 match unresolved {
536 None => {
537 let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
538 AdtId::StructId(s) => Some(VariantId::StructId(s)),
539 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
540 AdtId::EnumId(_) => {
541 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
542 None
543 }
544 });
545 (ty, variant)
546 }
547 Some(1) => {
548 let segment = path.mod_path().segments().last().unwrap();
549 // this could be an enum variant or associated type
550 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
551 let enum_data = self.db.enum_data(enum_id);
552 if let Some(local_id) = enum_data.variant(segment) {
553 let variant = EnumVariantId { parent: enum_id, local_id };
554 return (ty, Some(variant.into()));
555 }
556 } 556 }
557 }) 557 // FIXME potentially resolve assoc type
558 (self.err_ty(), None)
559 }
560 Some(_) => {
561 // FIXME diagnostic
562 (self.err_ty(), None)
563 }
558 } 564 }
559 } 565 }
560 566
@@ -692,25 +698,6 @@ impl<'a> InferenceContext<'a> {
692 } 698 }
693} 699}
694 700
695/// The kinds of placeholders we need during type inference. There's separate
696/// values for general types, and for integer and float variables. The latter
697/// two are used for inference of literal values (e.g. `100` could be one of
698/// several integer types).
699#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
700pub struct InferenceVar {
701 index: u32,
702}
703
704impl InferenceVar {
705 fn to_inner(self) -> unify::TypeVarId {
706 unify::TypeVarId(self.index)
707 }
708
709 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
710 InferenceVar { index }
711 }
712}
713
714/// When inferring an expression, we propagate downward whatever type hint we 701/// When inferring an expression, we propagate downward whatever type hint we
715/// are able in the form of an `Expectation`. 702/// are able in the form of an `Expectation`.
716#[derive(Clone, PartialEq, Eq, Debug)] 703#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 32c273afc..1f463a425 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{cast::Cast, 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::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind}; 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -71,17 +71,19 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (from_ty.interned_mut(), to_ty.kind(&Interner)) { 74 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => {
77 from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner);
78 }
76 // `&mut T` -> `&T` 79 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 80 (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
78 | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { 81 from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner);
79 *m1 = *m2;
80 } 82 }
81 // `&T` -> `*const T` 83 // `&T` -> `*const T`
82 // `&mut T` -> `*mut T`/`*const T` 84 // `&mut T` -> `*mut T`/`*const T`
83 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) 85 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
84 | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { 86 | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => {
85 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); 87 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
86 } 88 }
87 89
@@ -111,7 +113,9 @@ impl<'a> InferenceContext<'a> {
111 // Auto Deref if cannot coerce 113 // Auto Deref if cannot coerce
112 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 114 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
113 // FIXME: DerefMut 115 // FIXME: DerefMut
114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2), 116 (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => {
117 self.unify_autoderef_behind_ref(st1, st2)
118 }
115 119
116 // Otherwise, normal unify 120 // Otherwise, normal unify
117 _ => self.unify(&from_ty, to_ty), 121 _ => self.unify(&from_ty, to_ty),
@@ -137,7 +141,7 @@ impl<'a> InferenceContext<'a> {
137 b.push(from_ty.clone()).push(to_ty.clone()).build() 141 b.push(from_ty.clone()).push(to_ty.clone()).build()
138 }; 142 };
139 143
140 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); 144 let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner));
141 145
142 let canonicalizer = self.canonicalizer(); 146 let canonicalizer = self.canonicalizer();
143 let canonicalized = canonicalizer.canonicalize_obligation(goal); 147 let canonicalized = canonicalizer.canonicalize_obligation(goal);
@@ -146,7 +150,14 @@ impl<'a> InferenceContext<'a> {
146 150
147 match solution { 151 match solution {
148 Solution::Unique(v) => { 152 Solution::Unique(v) => {
149 canonicalized.apply_solution(self, v.0); 153 canonicalized.apply_solution(
154 self,
155 Canonical {
156 binders: v.binders,
157 // FIXME handle constraints
158 value: v.value.subst,
159 },
160 );
150 } 161 }
151 _ => return None, 162 _ => return None,
152 }; 163 };
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 6966d26e7..50497eecb 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::{cast::Cast, Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, fold::Shift, 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},
@@ -15,15 +15,16 @@ use stdx::always;
15use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
16 16
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef, dummy_usize_const,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 mapping::from_chalk,
20 method_resolution, op, 21 method_resolution, op,
21 primitive::{self, UintTy}, 22 primitive::{self, UintTy},
22 to_chalk_trait_id, 23 static_lifetime, to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait}, 24 traits::FnTrait,
24 utils::{generics, variant_data, Generics}, 25 utils::{generics, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar, 26 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 Substitution, TraitRef, Ty, TyBuilder, TyKind, 27 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27}; 28};
28 29
29use super::{ 30use super::{
@@ -180,7 +181,8 @@ impl<'a> InferenceContext<'a> {
180 let inner_ty = self.infer_expr(*body, &Expectation::none()); 181 let inner_ty = self.infer_expr(*body, &Expectation::none());
181 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); 182 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
182 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); 183 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
183 TyKind::OpaqueType(opaque_ty_id, Substitution::single(inner_ty)).intern(&Interner) 184 TyKind::OpaqueType(opaque_ty_id, Substitution::from1(&Interner, inner_ty))
185 .intern(&Interner)
184 } 186 }
185 Expr::Loop { body, label } => { 187 Expr::Loop { body, label } => {
186 self.breakables.push(BreakableContext { 188 self.breakables.push(BreakableContext {
@@ -259,14 +261,17 @@ impl<'a> InferenceContext<'a> {
259 }; 261 };
260 sig_tys.push(ret_ty.clone()); 262 sig_tys.push(ret_ty.clone());
261 let sig_ty = TyKind::Function(FnPointer { 263 let sig_ty = TyKind::Function(FnPointer {
262 num_args: sig_tys.len() - 1, 264 num_binders: 0,
263 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, 265 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
264 substs: Substitution::from_iter(&Interner, sig_tys.clone()), 266 substitution: FnSubst(
267 Substitution::from_iter(&Interner, sig_tys.clone()).shifted_in(&Interner),
268 ),
265 }) 269 })
266 .intern(&Interner); 270 .intern(&Interner);
267 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); 271 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
268 let closure_ty = 272 let closure_ty =
269 TyKind::Closure(closure_id, Substitution::single(sig_ty)).intern(&Interner); 273 TyKind::Closure(closure_id, Substitution::from1(&Interner, sig_ty))
274 .intern(&Interner);
270 275
271 // Eagerly try to relate the closure type with the expected 276 // Eagerly try to relate the closure type with the expected
272 // type, otherwise we often won't have enough information to 277 // type, otherwise we often won't have enough information to
@@ -313,7 +318,13 @@ impl<'a> InferenceContext<'a> {
313 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
314 } 319 }
315 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
316 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 321 .infer_method_call(
322 tgt_expr,
323 *receiver,
324 &args,
325 &method_name,
326 generic_args.as_deref(),
327 ),
317 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
318 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
319 330
@@ -394,16 +405,19 @@ impl<'a> InferenceContext<'a> {
394 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
395 } 406 }
396 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
397 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
398 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
399 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
400 } 411 }
401 412
402 self.unify(&ty, &expected.ty); 413 self.unify(&ty, &expected.ty);
403 414
404 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 415 let substs = ty
416 .as_adt()
417 .map(|(_, s)| s.clone())
418 .unwrap_or_else(|| Substitution::empty(&Interner));
405 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); 419 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
406 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); 420 let variant_data = def_id.map(|it| it.variant_data(self.db.upcast()));
407 for field in fields.iter() { 421 for field in fields.iter() {
408 let field_def = 422 let field_def =
409 variant_data.as_ref().and_then(|it| match it.field(&field.name) { 423 variant_data.as_ref().and_then(|it| match it.field(&field.name) {
@@ -415,9 +429,6 @@ impl<'a> InferenceContext<'a> {
415 None 429 None
416 } 430 }
417 }); 431 });
418 if let Some(field_def) = field_def {
419 self.result.record_field_resolutions.insert(field.expr, field_def);
420 }
421 let field_ty = field_def.map_or(self.err_ty(), |it| { 432 let field_ty = field_def.map_or(self.err_ty(), |it| {
422 field_types[it.local_id].clone().substitute(&Interner, &substs) 433 field_types[it.local_id].clone().substitute(&Interner, &substs)
423 }); 434 });
@@ -452,7 +463,11 @@ impl<'a> InferenceContext<'a> {
452 }; 463 };
453 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
454 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
455 substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() 466 substs
467 .as_slice(&Interner)
468 .get(idx)
469 .map(|a| a.assert_ty_ref(&Interner))
470 .cloned()
456 }), 471 }),
457 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 472 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
458 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 473 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
@@ -523,7 +538,7 @@ impl<'a> InferenceContext<'a> {
523 let inner_ty = self.infer_expr_inner(*expr, &expectation); 538 let inner_ty = self.infer_expr_inner(*expr, &expectation);
524 match rawness { 539 match rawness {
525 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), 540 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
526 Rawness::Ref => TyKind::Ref(mutability, inner_ty), 541 Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty),
527 } 542 }
528 .intern(&Interner) 543 .intern(&Interner)
529 } 544 }
@@ -698,7 +713,7 @@ impl<'a> InferenceContext<'a> {
698 } 713 }
699 Expr::Array(array) => { 714 Expr::Array(array) => {
700 let elem_ty = match expected.ty.kind(&Interner) { 715 let elem_ty = match expected.ty.kind(&Interner) {
701 TyKind::Array(st) | TyKind::Slice(st) => st.clone(), 716 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
702 _ => self.table.new_type_var(), 717 _ => self.table.new_type_var(),
703 }; 718 };
704 719
@@ -722,17 +737,19 @@ impl<'a> InferenceContext<'a> {
722 } 737 }
723 } 738 }
724 739
725 TyKind::Array(elem_ty).intern(&Interner) 740 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
726 } 741 }
727 Expr::Literal(lit) => match lit { 742 Expr::Literal(lit) => match lit {
728 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 743 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
729 Literal::String(..) => { 744 Literal::String(..) => {
730 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner) 745 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner))
746 .intern(&Interner)
731 } 747 }
732 Literal::ByteString(..) => { 748 Literal::ByteString(..) => {
733 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 749 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
734 let array_type = TyKind::Array(byte_type).intern(&Interner); 750 let array_type =
735 TyKind::Ref(Mutability::Not, array_type).intern(&Interner) 751 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
752 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
736 } 753 }
737 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 754 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
738 Literal::Int(_v, ty) => match ty { 755 Literal::Int(_v, ty) => match ty {
@@ -868,7 +885,9 @@ impl<'a> InferenceContext<'a> {
868 // Apply autoref so the below unification works correctly 885 // Apply autoref so the below unification works correctly
869 // FIXME: return correct autorefs from lookup_method 886 // FIXME: return correct autorefs from lookup_method
870 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 887 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
871 Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner), 888 Some((_, lifetime, mutability)) => {
889 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
890 }
872 _ => derefed_receiver_ty, 891 _ => derefed_receiver_ty,
873 }; 892 };
874 self.unify(&expected_receiver_ty, &actual_receiver_ty); 893 self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -962,8 +981,10 @@ impl<'a> InferenceContext<'a> {
962 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container 981 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
963 { 982 {
964 // construct a TraitRef 983 // construct a TraitRef
965 let substs = 984 let substs = crate::subst_prefix(
966 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 985 &*parameters,
986 generics(self.db.upcast(), trait_.into()).len(),
987 );
967 self.push_obligation( 988 self.push_obligation(
968 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } 989 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
969 .cast(&Interner), 990 .cast(&Interner),
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 252ae914a..aea354cde 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,14 +7,13 @@ use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
9 path::Path, 9 path::Path,
10 FieldId,
11}; 10};
12use hir_expand::name::Name; 11use hir_expand::name::Name;
13 12
14use super::{BindingMode, Expectation, InferenceContext}; 13use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 14use crate::{
16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, 15 lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
17 TyKind, 16 TyExt, TyKind,
18}; 17};
19 18
20impl<'a> InferenceContext<'a> { 19impl<'a> InferenceContext<'a> {
@@ -28,13 +27,14 @@ impl<'a> InferenceContext<'a> {
28 ellipsis: Option<usize>, 27 ellipsis: Option<usize>,
29 ) -> Ty { 28 ) -> Ty {
30 let (ty, def) = self.resolve_variant(path); 29 let (ty, def) = self.resolve_variant(path);
31 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 30 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
32 if let Some(variant) = def { 31 if let Some(variant) = def {
33 self.write_variant_resolution(id.into(), variant); 32 self.write_variant_resolution(id.into(), variant);
34 } 33 }
35 self.unify(&ty, expected); 34 self.unify(&ty, expected);
36 35
37 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 36 let substs =
37 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
38 38
39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
40 let (pre, post) = match ellipsis { 40 let (pre, post) = match ellipsis {
@@ -68,23 +68,19 @@ impl<'a> InferenceContext<'a> {
68 id: PatId, 68 id: PatId,
69 ) -> Ty { 69 ) -> Ty {
70 let (ty, def) = self.resolve_variant(path); 70 let (ty, def) = self.resolve_variant(path);
71 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 71 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
72 if let Some(variant) = def { 72 if let Some(variant) = def {
73 self.write_variant_resolution(id.into(), variant); 73 self.write_variant_resolution(id.into(), variant);
74 } 74 }
75 75
76 self.unify(&ty, expected); 76 self.unify(&ty, expected);
77 77
78 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 78 let substs =
79 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
79 80
80 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 81 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
81 for subpat in subpats { 82 for subpat in subpats {
82 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 83 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
83 if let Some(local_id) = matching_field {
84 let field_def = FieldId { parent: def.unwrap(), local_id };
85 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def);
86 }
87
88 let expected_ty = matching_field.map_or(self.err_ty(), |field| { 84 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
89 field_tys[field].clone().substitute(&Interner, &substs) 85 field_tys[field].clone().substitute(&Interner, &substs)
90 }); 86 });
@@ -104,7 +100,7 @@ impl<'a> InferenceContext<'a> {
104 let body = Arc::clone(&self.body); // avoid borrow checker problem 100 let body = Arc::clone(&self.body); // avoid borrow checker problem
105 101
106 if is_non_ref_pat(&body, pat) { 102 if is_non_ref_pat(&body, pat) {
107 while let Some((inner, mutability)) = expected.as_reference() { 103 while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
108 expected = inner; 104 expected = inner;
109 default_bm = match default_bm { 105 default_bm = match default_bm {
110 BindingMode::Move => BindingMode::Ref(mutability), 106 BindingMode::Move => BindingMode::Ref(mutability),
@@ -126,7 +122,7 @@ impl<'a> InferenceContext<'a> {
126 let ty = match &body[pat] { 122 let ty = match &body[pat] {
127 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
128 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
129 Some(parameters) => &*parameters.interned(), 125 Some(parameters) => &*parameters.as_slice(&Interner),
130 _ => &[], 126 _ => &[],
131 }; 127 };
132 128
@@ -162,7 +158,7 @@ impl<'a> InferenceContext<'a> {
162 Pat::Ref { pat, mutability } => { 158 Pat::Ref { pat, mutability } => {
163 let mutability = lower_to_chalk_mutability(*mutability); 159 let mutability = lower_to_chalk_mutability(*mutability);
164 let expectation = match expected.as_reference() { 160 let expectation = match expected.as_reference() {
165 Some((inner_ty, exp_mut)) => { 161 Some((inner_ty, _lifetime, exp_mut)) => {
166 if mutability != exp_mut { 162 if mutability != exp_mut {
167 // FIXME: emit type error? 163 // FIXME: emit type error?
168 } 164 }
@@ -171,10 +167,10 @@ impl<'a> InferenceContext<'a> {
171 _ => self.result.standard_types.unknown.clone(), 167 _ => self.result.standard_types.unknown.clone(),
172 }; 168 };
173 let subty = self.infer_pat(*pat, &expectation, default_bm); 169 let subty = self.infer_pat(*pat, &expectation, default_bm);
174 TyKind::Ref(mutability, subty).intern(&Interner) 170 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
175 } 171 }
176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 172 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
177 p.as_ref(), 173 p.as_deref(),
178 subpats, 174 subpats,
179 expected, 175 expected,
180 default_bm, 176 default_bm,
@@ -182,7 +178,7 @@ impl<'a> InferenceContext<'a> {
182 *ellipsis, 178 *ellipsis,
183 ), 179 ),
184 Pat::Record { path: p, args: fields, ellipsis: _ } => { 180 Pat::Record { path: p, args: fields, ellipsis: _ } => {
185 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 181 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
186 } 182 }
187 Pat::Path(path) => { 183 Pat::Path(path) => {
188 // FIXME use correct resolver for the surrounding expression 184 // FIXME use correct resolver for the surrounding expression
@@ -204,7 +200,8 @@ impl<'a> InferenceContext<'a> {
204 200
205 let bound_ty = match mode { 201 let bound_ty = match mode {
206 BindingMode::Ref(mutability) => { 202 BindingMode::Ref(mutability) => {
207 TyKind::Ref(mutability, inner_ty.clone()).intern(&Interner) 203 TyKind::Ref(mutability, static_lifetime(), inner_ty.clone())
204 .intern(&Interner)
208 } 205 }
209 BindingMode::Move => inner_ty.clone(), 206 BindingMode::Move => inner_ty.clone(),
210 }; 207 };
@@ -213,17 +210,20 @@ impl<'a> InferenceContext<'a> {
213 return inner_ty; 210 return inner_ty;
214 } 211 }
215 Pat::Slice { prefix, slice, suffix } => { 212 Pat::Slice { prefix, slice, suffix } => {
216 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.kind(&Interner) { 213 let elem_ty = match expected.kind(&Interner) {
217 TyKind::Array(st) => (TyKind::Array, st.clone()), 214 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
218 TyKind::Slice(st) => (TyKind::Slice, st.clone()), 215 _ => self.err_ty(),
219 _ => (TyKind::Slice, self.err_ty()),
220 }; 216 };
221 217
222 for pat_id in prefix.iter().chain(suffix) { 218 for pat_id in prefix.iter().chain(suffix) {
223 self.infer_pat(*pat_id, &elem_ty, default_bm); 219 self.infer_pat(*pat_id, &elem_ty, default_bm);
224 } 220 }
225 221
226 let pat_ty = container_ty(elem_ty).intern(&Interner); 222 let pat_ty = match expected.kind(&Interner) {
223 TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
224 _ => TyKind::Slice(elem_ty),
225 }
226 .intern(&Interner);
227 if let Some(slice_pat_id) = slice { 227 if let Some(slice_pat_id) = slice {
228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 228 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
229 } 229 }
@@ -242,7 +242,7 @@ impl<'a> InferenceContext<'a> {
242 let (inner_ty, alloc_ty) = match expected.as_adt() { 242 let (inner_ty, alloc_ty) = match expected.as_adt() {
243 Some((adt, subst)) if adt == box_adt => ( 243 Some((adt, subst)) if adt == box_adt => (
244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 244 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
245 subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), 245 subst.as_slice(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()),
246 ), 246 ),
247 _ => (self.result.standard_types.unknown.clone(), None), 247 _ => (self.result.standard_types.unknown.clone(), None),
248 }; 248 };
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 14f705173..495282eba 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -10,7 +10,10 @@ use hir_def::{
10}; 10};
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; 13use crate::{
14 method_resolution, Interner, Substitution, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
15 ValueTyDefId,
16};
14 17
15use super::{ExprOrPatId, InferenceContext, TraitRef}; 18use super::{ExprOrPatId, InferenceContext, TraitRef};
16 19
@@ -98,7 +101,7 @@ impl<'a> InferenceContext<'a> {
98 let substs = ctx.substs_from_path(path, typable, true); 101 let substs = ctx.substs_from_path(path, typable, true);
99 let ty = TyBuilder::value_ty(self.db, typable) 102 let ty = TyBuilder::value_ty(self.db, typable)
100 .use_parent_substs(&parent_substs) 103 .use_parent_substs(&parent_substs)
101 .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) 104 .fill(substs.as_slice(&Interner)[parent_substs.len(&Interner)..].iter().cloned())
102 .build(); 105 .build();
103 Some(ty) 106 Some(ty)
104 } 107 }
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index c90a16720..a887e20b0 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -2,13 +2,17 @@
2 2
3use std::borrow::Cow; 3use std::borrow::Cow;
4 4
5use chalk_ir::{FloatTy, IntTy, TyVariableKind, UniverseIndex, VariableKind}; 5use chalk_ir::{
6 cast::Cast, fold::Fold, interner::HasInterner, FloatTy, IntTy, TyVariableKind, UniverseIndex,
7 VariableKind,
8};
6use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue}; 9use ena::unify::{InPlaceUnificationTable, NoError, UnifyKey, UnifyValue};
7 10
8use super::{DomainGoal, InferenceContext}; 11use super::{DomainGoal, InferenceContext};
9use crate::{ 12use crate::{
10 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, 13 fold_tys, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
11 InEnvironment, InferenceVar, Interner, Scalar, Substitution, Ty, TyKind, TypeWalk, WhereClause, 14 DebruijnIndex, FnPointer, FnSubst, InEnvironment, InferenceVar, Interner, Scalar, Substitution,
15 Ty, TyExt, TyKind, WhereClause,
12}; 16};
13 17
14impl<'a> InferenceContext<'a> { 18impl<'a> InferenceContext<'a> {
@@ -33,7 +37,10 @@ where
33} 37}
34 38
35#[derive(Debug)] 39#[derive(Debug)]
36pub(super) struct Canonicalized<T> { 40pub(super) struct Canonicalized<T>
41where
42 T: HasInterner<Interner = Interner>,
43{
37 pub(super) value: Canonical<T>, 44 pub(super) value: Canonical<T>,
38 free_vars: Vec<(InferenceVar, TyVariableKind)>, 45 free_vars: Vec<(InferenceVar, TyVariableKind)>,
39} 46}
@@ -47,11 +54,16 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
47 }) 54 })
48 } 55 }
49 56
50 fn do_canonicalize<T: TypeWalk>(&mut self, t: T, binders: DebruijnIndex) -> T { 57 fn do_canonicalize<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
51 t.fold_binders( 58 &mut self,
52 &mut |ty, binders| match ty.kind(&Interner) { 59 t: T,
60 binders: DebruijnIndex,
61 ) -> T {
62 fold_tys(
63 t,
64 |ty, binders| match ty.kind(&Interner) {
53 &TyKind::InferenceVar(var, kind) => { 65 &TyKind::InferenceVar(var, kind) => {
54 let inner = var.to_inner(); 66 let inner = from_inference_var(var);
55 if self.var_stack.contains(&inner) { 67 if self.var_stack.contains(&inner) {
56 // recursive type 68 // recursive type
57 return self.ctx.table.type_variable_table.fallback_value(var, kind); 69 return self.ctx.table.type_variable_table.fallback_value(var, kind);
@@ -65,7 +77,7 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
65 result 77 result
66 } else { 78 } else {
67 let root = self.ctx.table.var_unification_table.find(inner); 79 let root = self.ctx.table.var_unification_table.find(inner);
68 let position = self.add(InferenceVar::from_inner(root), kind); 80 let position = self.add(to_inference_var(root), kind);
69 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner) 81 TyKind::BoundVar(BoundVar::new(binders, position)).intern(&Interner)
70 } 82 }
71 } 83 }
@@ -75,7 +87,10 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
75 ) 87 )
76 } 88 }
77 89
78 fn into_canonicalized<T>(self, result: T) -> Canonicalized<T> { 90 fn into_canonicalized<T: HasInterner<Interner = Interner>>(
91 self,
92 result: T,
93 ) -> Canonicalized<T> {
79 let kinds = self 94 let kinds = self
80 .free_vars 95 .free_vars
81 .iter() 96 .iter()
@@ -102,28 +117,18 @@ impl<'a, 'b> Canonicalizer<'a, 'b> {
102 DomainGoal::Holds(wc) => { 117 DomainGoal::Holds(wc) => {
103 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST)) 118 DomainGoal::Holds(self.do_canonicalize(wc, DebruijnIndex::INNERMOST))
104 } 119 }
120 _ => unimplemented!(),
105 }; 121 };
106 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment }) 122 self.into_canonicalized(InEnvironment { goal: result, environment: obligation.environment })
107 } 123 }
108} 124}
109 125
110impl<T> Canonicalized<T> { 126impl<T: HasInterner<Interner = Interner>> Canonicalized<T> {
111 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty { 127 pub(super) fn decanonicalize_ty(&self, ty: Ty) -> Ty {
112 ty.fold_binders( 128 crate::fold_free_vars(ty, |bound, _binders| {
113 &mut |ty, binders| { 129 let (v, k) = self.free_vars[bound.index];
114 if let TyKind::BoundVar(bound) = ty.kind(&Interner) { 130 TyKind::InferenceVar(v, k).intern(&Interner)
115 if bound.debruijn >= binders { 131 })
116 let (v, k) = self.free_vars[bound.index];
117 TyKind::InferenceVar(v, k).intern(&Interner)
118 } else {
119 ty
120 }
121 } else {
122 ty
123 }
124 },
125 DebruijnIndex::INNERMOST,
126 )
127 } 132 }
128 133
129 pub(super) fn apply_solution( 134 pub(super) fn apply_solution(
@@ -135,15 +140,17 @@ impl<T> Canonicalized<T> {
135 let new_vars = Substitution::from_iter( 140 let new_vars = Substitution::from_iter(
136 &Interner, 141 &Interner,
137 solution.binders.iter(&Interner).map(|k| match k.kind { 142 solution.binders.iter(&Interner).map(|k| match k.kind {
138 VariableKind::Ty(TyVariableKind::General) => ctx.table.new_type_var(), 143 VariableKind::Ty(TyVariableKind::General) => {
139 VariableKind::Ty(TyVariableKind::Integer) => ctx.table.new_integer_var(), 144 ctx.table.new_type_var().cast(&Interner)
140 VariableKind::Ty(TyVariableKind::Float) => ctx.table.new_float_var(), 145 }
141 // HACK: Chalk can sometimes return new lifetime variables. We 146 VariableKind::Ty(TyVariableKind::Integer) => {
142 // want to just skip them, but to not mess up the indices of 147 ctx.table.new_integer_var().cast(&Interner)
143 // other variables, we'll just create a new type variable in 148 }
144 // their place instead. This should not matter (we never see the 149 VariableKind::Ty(TyVariableKind::Float) => {
145 // actual *uses* of the lifetime variable). 150 ctx.table.new_float_var().cast(&Interner)
146 VariableKind::Lifetime => ctx.table.new_type_var(), 151 }
152 // Chalk can sometimes return new lifetime variables. We just use the static lifetime everywhere
153 VariableKind::Lifetime => static_lifetime().cast(&Interner),
147 _ => panic!("const variable in solution"), 154 _ => panic!("const variable in solution"),
148 }), 155 }),
149 ); 156 );
@@ -207,16 +214,16 @@ impl TypeVariableTable {
207 } 214 }
208 215
209 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) { 216 pub(super) fn set_diverging(&mut self, iv: InferenceVar, diverging: bool) {
210 self.inner[iv.to_inner().0 as usize].diverging = diverging; 217 self.inner[from_inference_var(iv).0 as usize].diverging = diverging;
211 } 218 }
212 219
213 fn is_diverging(&mut self, iv: InferenceVar) -> bool { 220 fn is_diverging(&mut self, iv: InferenceVar) -> bool {
214 self.inner[iv.to_inner().0 as usize].diverging 221 self.inner[from_inference_var(iv).0 as usize].diverging
215 } 222 }
216 223
217 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty { 224 fn fallback_value(&self, iv: InferenceVar, kind: TyVariableKind) -> Ty {
218 match kind { 225 match kind {
219 _ if self.inner[iv.to_inner().0 as usize].diverging => TyKind::Never, 226 _ if self.inner[from_inference_var(iv).0 as usize].diverging => TyKind::Never,
220 TyVariableKind::General => TyKind::Error, 227 TyVariableKind::General => TyKind::Error,
221 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)), 228 TyVariableKind::Integer => TyKind::Scalar(Scalar::Int(IntTy::I32)),
222 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)), 229 TyVariableKind::Float => TyKind::Scalar(Scalar::Float(FloatTy::F64)),
@@ -250,7 +257,7 @@ impl InferenceTable {
250 self.type_variable_table.push(TypeVariableData { diverging }); 257 self.type_variable_table.push(TypeVariableData { diverging });
251 let key = self.var_unification_table.new_key(TypeVarValue::Unknown); 258 let key = self.var_unification_table.new_key(TypeVarValue::Unknown);
252 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1); 259 assert_eq!(key.0 as usize, self.type_variable_table.inner.len() - 1);
253 TyKind::InferenceVar(InferenceVar::from_inner(key), kind).intern(&Interner) 260 TyKind::InferenceVar(to_inference_var(key), kind).intern(&Interner)
254 } 261 }
255 262
256 pub(crate) fn new_type_var(&mut self) -> Ty { 263 pub(crate) fn new_type_var(&mut self) -> Ty {
@@ -308,8 +315,8 @@ impl InferenceTable {
308 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2)) 315 (TyKind::Adt(_, substs1), TyKind::Adt(_, substs2))
309 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2)) 316 | (TyKind::FnDef(_, substs1), TyKind::FnDef(_, substs2))
310 | ( 317 | (
311 TyKind::Function(FnPointer { substs: substs1, .. }), 318 TyKind::Function(FnPointer { substitution: FnSubst(substs1), .. }),
312 TyKind::Function(FnPointer { substs: substs2, .. }), 319 TyKind::Function(FnPointer { substitution: FnSubst(substs2), .. }),
313 ) 320 )
314 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2)) 321 | (TyKind::Tuple(_, substs1), TyKind::Tuple(_, substs2))
315 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2)) 322 | (TyKind::OpaqueType(_, substs1), TyKind::OpaqueType(_, substs2))
@@ -317,9 +324,11 @@ impl InferenceTable {
317 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => { 324 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
318 self.unify_substs(substs1, substs2, depth + 1) 325 self.unify_substs(substs1, substs2, depth + 1)
319 } 326 }
320 (TyKind::Ref(_, ty1), TyKind::Ref(_, ty2)) 327 (TyKind::Array(ty1, c1), TyKind::Array(ty2, c2)) if c1 == c2 => {
328 self.unify_inner(ty1, ty2, depth + 1)
329 }
330 (TyKind::Ref(_, _, ty1), TyKind::Ref(_, _, ty2))
321 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2)) 331 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
322 | (TyKind::Array(ty1), TyKind::Array(ty2))
323 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1), 332 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
324 _ => true, /* we checked equals_ctor already */ 333 _ => true, /* we checked equals_ctor already */
325 } 334 }
@@ -367,8 +376,12 @@ impl InferenceTable {
367 == self.type_variable_table.is_diverging(*tv2) => 376 == self.type_variable_table.is_diverging(*tv2) =>
368 { 377 {
369 // both type vars are unknown since we tried to resolve them 378 // both type vars are unknown since we tried to resolve them
370 if !self.var_unification_table.unioned(tv1.to_inner(), tv2.to_inner()) { 379 if !self
371 self.var_unification_table.union(tv1.to_inner(), tv2.to_inner()); 380 .var_unification_table
381 .unioned(from_inference_var(*tv1), from_inference_var(*tv2))
382 {
383 self.var_unification_table
384 .union(from_inference_var(*tv1), from_inference_var(*tv2));
372 self.revision += 1; 385 self.revision += 1;
373 } 386 }
374 true 387 true
@@ -405,7 +418,7 @@ impl InferenceTable {
405 ) => { 418 ) => {
406 // the type var is unknown since we tried to resolve it 419 // the type var is unknown since we tried to resolve it
407 self.var_unification_table.union_value( 420 self.var_unification_table.union_value(
408 tv.to_inner(), 421 from_inference_var(*tv),
409 TypeVarValue::Known(other.clone().intern(&Interner)), 422 TypeVarValue::Known(other.clone().intern(&Interner)),
410 ); 423 );
411 self.revision += 1; 424 self.revision += 1;
@@ -460,7 +473,7 @@ impl InferenceTable {
460 } 473 }
461 match ty.kind(&Interner) { 474 match ty.kind(&Interner) {
462 TyKind::InferenceVar(tv, _) => { 475 TyKind::InferenceVar(tv, _) => {
463 let inner = tv.to_inner(); 476 let inner = from_inference_var(*tv);
464 match self.var_unification_table.inlined_probe_value(inner).known() { 477 match self.var_unification_table.inlined_probe_value(inner).known() {
465 Some(known_ty) => { 478 Some(known_ty) => {
466 // The known_ty can't be a type var itself 479 // The known_ty can't be a type var itself
@@ -481,55 +494,63 @@ impl InferenceTable {
481 /// be resolved as far as possible, i.e. contain no type variables with 494 /// be resolved as far as possible, i.e. contain no type variables with
482 /// known type. 495 /// known type.
483 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 496 fn resolve_ty_as_possible_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
484 ty.fold(&mut |ty| match ty.kind(&Interner) { 497 fold_tys(
485 &TyKind::InferenceVar(tv, kind) => { 498 ty,
486 let inner = tv.to_inner(); 499 |ty, _| match ty.kind(&Interner) {
487 if tv_stack.contains(&inner) { 500 &TyKind::InferenceVar(tv, kind) => {
488 cov_mark::hit!(type_var_cycles_resolve_as_possible); 501 let inner = from_inference_var(tv);
489 // recursive type 502 if tv_stack.contains(&inner) {
490 return self.type_variable_table.fallback_value(tv, kind); 503 cov_mark::hit!(type_var_cycles_resolve_as_possible);
491 } 504 // recursive type
492 if let Some(known_ty) = 505 return self.type_variable_table.fallback_value(tv, kind);
493 self.var_unification_table.inlined_probe_value(inner).known() 506 }
494 { 507 if let Some(known_ty) =
495 // known_ty may contain other variables that are known by now 508 self.var_unification_table.inlined_probe_value(inner).known()
496 tv_stack.push(inner); 509 {
497 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone()); 510 // known_ty may contain other variables that are known by now
498 tv_stack.pop(); 511 tv_stack.push(inner);
499 result 512 let result = self.resolve_ty_as_possible_inner(tv_stack, known_ty.clone());
500 } else { 513 tv_stack.pop();
501 ty 514 result
515 } else {
516 ty
517 }
502 } 518 }
503 } 519 _ => ty,
504 _ => ty, 520 },
505 }) 521 DebruijnIndex::INNERMOST,
522 )
506 } 523 }
507 524
508 /// Resolves the type completely; type variables without known type are 525 /// Resolves the type completely; type variables without known type are
509 /// replaced by TyKind::Unknown. 526 /// replaced by TyKind::Unknown.
510 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty { 527 fn resolve_ty_completely_inner(&mut self, tv_stack: &mut Vec<TypeVarId>, ty: Ty) -> Ty {
511 ty.fold(&mut |ty| match ty.kind(&Interner) { 528 fold_tys(
512 &TyKind::InferenceVar(tv, kind) => { 529 ty,
513 let inner = tv.to_inner(); 530 |ty, _| match ty.kind(&Interner) {
514 if tv_stack.contains(&inner) { 531 &TyKind::InferenceVar(tv, kind) => {
515 cov_mark::hit!(type_var_cycles_resolve_completely); 532 let inner = from_inference_var(tv);
516 // recursive type 533 if tv_stack.contains(&inner) {
517 return self.type_variable_table.fallback_value(tv, kind); 534 cov_mark::hit!(type_var_cycles_resolve_completely);
518 } 535 // recursive type
519 if let Some(known_ty) = 536 return self.type_variable_table.fallback_value(tv, kind);
520 self.var_unification_table.inlined_probe_value(inner).known() 537 }
521 { 538 if let Some(known_ty) =
522 // known_ty may contain other variables that are known by now 539 self.var_unification_table.inlined_probe_value(inner).known()
523 tv_stack.push(inner); 540 {
524 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone()); 541 // known_ty may contain other variables that are known by now
525 tv_stack.pop(); 542 tv_stack.push(inner);
526 result 543 let result = self.resolve_ty_completely_inner(tv_stack, known_ty.clone());
527 } else { 544 tv_stack.pop();
528 self.type_variable_table.fallback_value(tv, kind) 545 result
546 } else {
547 self.type_variable_table.fallback_value(tv, kind)
548 }
529 } 549 }
530 } 550 _ => ty,
531 _ => ty, 551 },
532 }) 552 DebruijnIndex::INNERMOST,
553 )
533 } 554 }
534} 555}
535 556
@@ -553,6 +574,14 @@ impl UnifyKey for TypeVarId {
553 } 574 }
554} 575}
555 576
577fn from_inference_var(var: InferenceVar) -> TypeVarId {
578 TypeVarId(var.index())
579}
580
581fn to_inference_var(TypeVarId(index): TypeVarId) -> InferenceVar {
582 index.into()
583}
584
556/// The value of a type variable: either we already know the type, or we don't 585/// The value of a type variable: either we already know the type, or we don't
557/// know it yet. 586/// know it yet.
558#[derive(Clone, PartialEq, Eq, Debug)] 587#[derive(Clone, PartialEq, Eq, Debug)]
diff --git a/crates/hir_ty/src/traits/chalk/interner.rs b/crates/hir_ty/src/interner.rs
index bd9395b7e..a1656115d 100644
--- a/crates/hir_ty/src/traits/chalk/interner.rs
+++ b/crates/hir_ty/src/interner.rs
@@ -1,61 +1,83 @@
1//! Implementation of the Chalk `Interner` trait, which allows customizing the 1//! Implementation of the Chalk `Interner` trait, which allows customizing the
2//! representation of the various objects Chalk deals with (types, goals etc.). 2//! representation of the various objects Chalk deals with (types, goals etc.).
3 3
4use super::tls; 4use crate::{chalk_db, tls, GenericArg};
5use base_db::salsa::InternId; 5use base_db::salsa::InternId;
6use chalk_ir::{GenericArg, Goal, GoalData}; 6use chalk_ir::{Goal, GoalData};
7use hir_def::TypeAliasId; 7use hir_def::{
8 intern::{impl_internable, InternStorage, Internable, Interned},
9 TypeAliasId,
10};
8use smallvec::SmallVec; 11use smallvec::SmallVec;
9use std::{fmt, sync::Arc}; 12use std::{fmt, sync::Arc};
10 13
11#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)] 14#[derive(Debug, Copy, Clone, Hash, PartialOrd, Ord, PartialEq, Eq)]
12pub struct Interner; 15pub struct Interner;
13 16
14pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 17#[derive(PartialEq, Eq, Hash, Debug)]
15pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>; 18pub struct InternedWrapper<T>(T);
16pub(crate) type TraitId = chalk_ir::TraitId<Interner>; 19
17pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>; 20impl<T> std::ops::Deref for InternedWrapper<T> {
18pub(crate) type AdtId = chalk_ir::AdtId<Interner>; 21 type Target = T;
19pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>; 22
20pub(crate) type ImplId = chalk_ir::ImplId<Interner>; 23 fn deref(&self) -> &Self::Target {
21pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>; 24 &self.0
22pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>; 25 }
23pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>; 26}
24pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>; 27
25pub(crate) type OpaqueTyId = chalk_ir::OpaqueTyId<Interner>; 28impl_internable!(
26pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>; 29 InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>,
27pub(crate) type Variances = chalk_ir::Variances<Interner>; 30 InternedWrapper<SmallVec<[GenericArg; 2]>>,
31 InternedWrapper<chalk_ir::TyData<Interner>>,
32 InternedWrapper<chalk_ir::LifetimeData<Interner>>,
33 InternedWrapper<chalk_ir::ConstData<Interner>>,
34 InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Interner>>>,
35 InternedWrapper<Vec<chalk_ir::ProgramClause<Interner>>>,
36 InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Interner>>>,
37 InternedWrapper<Vec<chalk_ir::Variance>>,
38);
28 39
29impl chalk_ir::interner::Interner for Interner { 40impl chalk_ir::interner::Interner for Interner {
30 type InternedType = Arc<chalk_ir::TyData<Self>>; 41 type InternedType = Interned<InternedWrapper<chalk_ir::TyData<Interner>>>;
31 type InternedLifetime = chalk_ir::LifetimeData<Self>; 42 type InternedLifetime = Interned<InternedWrapper<chalk_ir::LifetimeData<Self>>>;
32 type InternedConst = Arc<chalk_ir::ConstData<Self>>; 43 type InternedConst = Interned<InternedWrapper<chalk_ir::ConstData<Self>>>;
33 type InternedConcreteConst = (); 44 type InternedConcreteConst = ();
34 type InternedGenericArg = chalk_ir::GenericArgData<Self>; 45 type InternedGenericArg = chalk_ir::GenericArgData<Self>;
35 type InternedGoal = Arc<GoalData<Self>>; 46 type InternedGoal = Arc<GoalData<Self>>;
36 type InternedGoals = Vec<Goal<Self>>; 47 type InternedGoals = Vec<Goal<Self>>;
37 type InternedSubstitution = SmallVec<[GenericArg<Self>; 2]>; 48 type InternedSubstitution = Interned<InternedWrapper<SmallVec<[GenericArg; 2]>>>;
38 type InternedProgramClause = Arc<chalk_ir::ProgramClauseData<Self>>; 49 type InternedProgramClause = chalk_ir::ProgramClauseData<Self>;
39 type InternedProgramClauses = Arc<[chalk_ir::ProgramClause<Self>]>; 50 type InternedProgramClauses = Interned<InternedWrapper<Vec<chalk_ir::ProgramClause<Self>>>>;
40 type InternedQuantifiedWhereClauses = Vec<chalk_ir::QuantifiedWhereClause<Self>>; 51 type InternedQuantifiedWhereClauses =
41 type InternedVariableKinds = Vec<chalk_ir::VariableKind<Self>>; 52 Interned<InternedWrapper<Vec<chalk_ir::QuantifiedWhereClause<Self>>>>;
42 type InternedCanonicalVarKinds = Vec<chalk_ir::CanonicalVarKind<Self>>; 53 type InternedVariableKinds = Interned<InternedWrapper<Vec<chalk_ir::VariableKind<Interner>>>>;
54 type InternedCanonicalVarKinds =
55 Interned<InternedWrapper<Vec<chalk_ir::CanonicalVarKind<Self>>>>;
43 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>; 56 type InternedConstraints = Vec<chalk_ir::InEnvironment<chalk_ir::Constraint<Self>>>;
44 type InternedVariances = Arc<[chalk_ir::Variance]>; 57 type InternedVariances = Interned<InternedWrapper<Vec<chalk_ir::Variance>>>;
45 type DefId = InternId; 58 type DefId = InternId;
46 type InternedAdtId = hir_def::AdtId; 59 type InternedAdtId = hir_def::AdtId;
47 type Identifier = TypeAliasId; 60 type Identifier = TypeAliasId;
48 type FnAbi = (); 61 type FnAbi = ();
49 62
50 fn debug_adt_id(type_kind_id: AdtId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 63 fn debug_adt_id(
64 type_kind_id: chalk_db::AdtId,
65 fmt: &mut fmt::Formatter<'_>,
66 ) -> Option<fmt::Result> {
51 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt))) 67 tls::with_current_program(|prog| Some(prog?.debug_struct_id(type_kind_id, fmt)))
52 } 68 }
53 69
54 fn debug_trait_id(type_kind_id: TraitId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 70 fn debug_trait_id(
71 type_kind_id: chalk_db::TraitId,
72 fmt: &mut fmt::Formatter<'_>,
73 ) -> Option<fmt::Result> {
55 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt))) 74 tls::with_current_program(|prog| Some(prog?.debug_trait_id(type_kind_id, fmt)))
56 } 75 }
57 76
58 fn debug_assoc_type_id(id: AssocTypeId, fmt: &mut fmt::Formatter<'_>) -> Option<fmt::Result> { 77 fn debug_assoc_type_id(
78 id: chalk_db::AssocTypeId,
79 fmt: &mut fmt::Formatter<'_>,
80 ) -> Option<fmt::Result> {
59 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt))) 81 tls::with_current_program(|prog| Some(prog?.debug_assoc_type_id(id, fmt)))
60 } 82 }
61 83
@@ -99,7 +121,7 @@ impl chalk_ir::interner::Interner for Interner {
99 } 121 }
100 122
101 fn debug_generic_arg( 123 fn debug_generic_arg(
102 parameter: &GenericArg<Interner>, 124 parameter: &GenericArg,
103 fmt: &mut fmt::Formatter<'_>, 125 fmt: &mut fmt::Formatter<'_>,
104 ) -> Option<fmt::Result> { 126 ) -> Option<fmt::Result> {
105 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt))) 127 tls::with_current_program(|prog| Some(prog?.debug_generic_arg(parameter, fmt)))
@@ -194,30 +216,30 @@ impl chalk_ir::interner::Interner for Interner {
194 216
195 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType { 217 fn intern_ty(&self, kind: chalk_ir::TyKind<Self>) -> Self::InternedType {
196 let flags = kind.compute_flags(self); 218 let flags = kind.compute_flags(self);
197 Arc::new(chalk_ir::TyData { kind, flags }) 219 Interned::new(InternedWrapper(chalk_ir::TyData { kind, flags }))
198 } 220 }
199 221
200 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> { 222 fn ty_data<'a>(&self, ty: &'a Self::InternedType) -> &'a chalk_ir::TyData<Self> {
201 ty 223 &ty.0
202 } 224 }
203 225
204 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime { 226 fn intern_lifetime(&self, lifetime: chalk_ir::LifetimeData<Self>) -> Self::InternedLifetime {
205 lifetime 227 Interned::new(InternedWrapper(lifetime))
206 } 228 }
207 229
208 fn lifetime_data<'a>( 230 fn lifetime_data<'a>(
209 &self, 231 &self,
210 lifetime: &'a Self::InternedLifetime, 232 lifetime: &'a Self::InternedLifetime,
211 ) -> &'a chalk_ir::LifetimeData<Self> { 233 ) -> &'a chalk_ir::LifetimeData<Self> {
212 lifetime 234 &lifetime.0
213 } 235 }
214 236
215 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst { 237 fn intern_const(&self, constant: chalk_ir::ConstData<Self>) -> Self::InternedConst {
216 Arc::new(constant) 238 Interned::new(InternedWrapper(constant))
217 } 239 }
218 240
219 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> { 241 fn const_data<'a>(&self, constant: &'a Self::InternedConst) -> &'a chalk_ir::ConstData<Self> {
220 constant 242 &constant.0
221 } 243 }
222 244
223 fn const_eq( 245 fn const_eq(
@@ -264,23 +286,23 @@ impl chalk_ir::interner::Interner for Interner {
264 286
265 fn intern_substitution<E>( 287 fn intern_substitution<E>(
266 &self, 288 &self,
267 data: impl IntoIterator<Item = Result<GenericArg<Self>, E>>, 289 data: impl IntoIterator<Item = Result<GenericArg, E>>,
268 ) -> Result<Self::InternedSubstitution, E> { 290 ) -> Result<Self::InternedSubstitution, E> {
269 data.into_iter().collect() 291 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
270 } 292 }
271 293
272 fn substitution_data<'a>( 294 fn substitution_data<'a>(
273 &self, 295 &self,
274 substitution: &'a Self::InternedSubstitution, 296 substitution: &'a Self::InternedSubstitution,
275 ) -> &'a [GenericArg<Self>] { 297 ) -> &'a [GenericArg] {
276 substitution 298 &substitution.as_ref().0
277 } 299 }
278 300
279 fn intern_program_clause( 301 fn intern_program_clause(
280 &self, 302 &self,
281 data: chalk_ir::ProgramClauseData<Self>, 303 data: chalk_ir::ProgramClauseData<Self>,
282 ) -> Self::InternedProgramClause { 304 ) -> Self::InternedProgramClause {
283 Arc::new(data) 305 data
284 } 306 }
285 307
286 fn program_clause_data<'a>( 308 fn program_clause_data<'a>(
@@ -294,7 +316,7 @@ impl chalk_ir::interner::Interner for Interner {
294 &self, 316 &self,
295 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>, 317 data: impl IntoIterator<Item = Result<chalk_ir::ProgramClause<Self>, E>>,
296 ) -> Result<Self::InternedProgramClauses, E> { 318 ) -> Result<Self::InternedProgramClauses, E> {
297 data.into_iter().collect() 319 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
298 } 320 }
299 321
300 fn program_clauses_data<'a>( 322 fn program_clauses_data<'a>(
@@ -308,7 +330,7 @@ impl chalk_ir::interner::Interner for Interner {
308 &self, 330 &self,
309 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>, 331 data: impl IntoIterator<Item = Result<chalk_ir::QuantifiedWhereClause<Self>, E>>,
310 ) -> Result<Self::InternedQuantifiedWhereClauses, E> { 332 ) -> Result<Self::InternedQuantifiedWhereClauses, E> {
311 data.into_iter().collect() 333 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
312 } 334 }
313 335
314 fn quantified_where_clauses_data<'a>( 336 fn quantified_where_clauses_data<'a>(
@@ -322,21 +344,21 @@ impl chalk_ir::interner::Interner for Interner {
322 &self, 344 &self,
323 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>, 345 data: impl IntoIterator<Item = Result<chalk_ir::VariableKind<Self>, E>>,
324 ) -> Result<Self::InternedVariableKinds, E> { 346 ) -> Result<Self::InternedVariableKinds, E> {
325 data.into_iter().collect() 347 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
326 } 348 }
327 349
328 fn variable_kinds_data<'a>( 350 fn variable_kinds_data<'a>(
329 &self, 351 &self,
330 parameter_kinds: &'a Self::InternedVariableKinds, 352 parameter_kinds: &'a Self::InternedVariableKinds,
331 ) -> &'a [chalk_ir::VariableKind<Self>] { 353 ) -> &'a [chalk_ir::VariableKind<Self>] {
332 &parameter_kinds 354 &parameter_kinds.as_ref().0
333 } 355 }
334 356
335 fn intern_canonical_var_kinds<E>( 357 fn intern_canonical_var_kinds<E>(
336 &self, 358 &self,
337 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>, 359 data: impl IntoIterator<Item = Result<chalk_ir::CanonicalVarKind<Self>, E>>,
338 ) -> Result<Self::InternedCanonicalVarKinds, E> { 360 ) -> Result<Self::InternedCanonicalVarKinds, E> {
339 data.into_iter().collect() 361 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
340 } 362 }
341 363
342 fn canonical_var_kinds_data<'a>( 364 fn canonical_var_kinds_data<'a>(
@@ -376,7 +398,7 @@ impl chalk_ir::interner::Interner for Interner {
376 &self, 398 &self,
377 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>, 399 data: impl IntoIterator<Item = Result<chalk_ir::Variance, E>>,
378 ) -> Result<Self::InternedVariances, E> { 400 ) -> Result<Self::InternedVariances, E> {
379 data.into_iter().collect() 401 Ok(Interned::new(InternedWrapper(data.into_iter().collect::<Result<_, _>>()?)))
380 } 402 }
381 403
382 fn variances_data<'a>( 404 fn variances_data<'a>(
@@ -390,3 +412,12 @@ impl chalk_ir::interner::Interner for Interner {
390impl chalk_ir::interner::HasInterner for Interner { 412impl chalk_ir::interner::HasInterner for Interner {
391 type Interner = Self; 413 type Interner = Self;
392} 414}
415
416#[macro_export]
417macro_rules! has_interner {
418 ($t:ty) => {
419 impl HasInterner for $t {
420 type Interner = crate::Interner;
421 }
422 };
423}
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index daf379ef8..113234fa4 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -1,27 +1,29 @@
1//! The type system. We currently use this to infer types for completion, hover 1//! The type system. We currently use this to infer types for completion, hover
2//! information and various assists. 2//! information and various assists.
3
3#[allow(unused)] 4#[allow(unused)]
4macro_rules! eprintln { 5macro_rules! eprintln {
5 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) }; 6 ($($tt:tt)*) => { stdx::eprintln!($($tt)*) };
6} 7}
7 8
8mod autoderef; 9mod autoderef;
9pub mod primitive;
10pub mod traits;
11pub mod method_resolution;
12mod op;
13mod lower;
14pub(crate) mod infer;
15pub(crate) mod utils;
16mod chalk_cast;
17mod chalk_ext;
18mod builder; 10mod builder;
11mod chalk_db;
12mod chalk_ext;
13mod infer;
14mod interner;
15mod lower;
16mod mapping;
17mod op;
18mod tls;
19mod utils;
19mod walk; 20mod walk;
20mod types;
21
22pub mod display;
23pub mod db; 21pub mod db;
24pub mod diagnostics; 22pub mod diagnostics;
23pub mod display;
24pub mod method_resolution;
25pub mod primitive;
26pub mod traits;
25 27
26#[cfg(test)] 28#[cfg(test)]
27mod tests; 29mod tests;
@@ -30,35 +32,36 @@ mod test_db;
30 32
31use std::sync::Arc; 33use std::sync::Arc;
32 34
33use itertools::Itertools; 35use chalk_ir::{
34use smallvec::SmallVec; 36 fold::{Fold, Shift},
35 37 interner::HasInterner,
36use base_db::salsa; 38 UintTy,
37use hir_def::{
38 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup,
39 TraitId, TypeAliasId, TypeParamId,
40}; 39};
40use hir_def::{expr::ExprId, type_ref::Rawness, TypeParamId};
41 41
42use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 42use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43 43
44pub use autoderef::autoderef; 44pub use autoderef::autoderef;
45pub use builder::TyBuilder; 45pub use builder::TyBuilder;
46pub use chalk_ext::TyExt; 46pub use chalk_ext::*;
47pub use infer::{could_unify, InferenceResult, InferenceVar}; 47pub use infer::{could_unify, InferenceResult};
48pub use interner::Interner;
48pub use lower::{ 49pub use lower::{
49 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 50 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
50 TyDefId, TyLoweringContext, ValueTyDefId, 51 TyDefId, TyLoweringContext, ValueTyDefId,
51}; 52};
53pub use mapping::{
54 const_from_placeholder_idx, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
55 from_placeholder_idx, lt_from_placeholder_idx, to_assoc_type_id, to_chalk_trait_id,
56 to_foreign_def_id, to_placeholder_idx,
57};
52pub use traits::TraitEnvironment; 58pub use traits::TraitEnvironment;
53pub use types::*;
54pub use walk::TypeWalk; 59pub use walk::TypeWalk;
55 60
56pub use chalk_ir::{ 61pub use chalk_ir::{
57 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, 62 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
58}; 63};
59 64
60pub use crate::traits::chalk::Interner;
61
62pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>; 65pub type ForeignDefId = chalk_ir::ForeignDefId<Interner>;
63pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>; 66pub type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
64pub type FnDefId = chalk_ir::FnDefId<Interner>; 67pub type FnDefId = chalk_ir::FnDefId<Interner>;
@@ -69,49 +72,53 @@ pub type PlaceholderIndex = chalk_ir::PlaceholderIndex;
69pub type VariableKind = chalk_ir::VariableKind<Interner>; 72pub type VariableKind = chalk_ir::VariableKind<Interner>;
70pub type VariableKinds = chalk_ir::VariableKinds<Interner>; 73pub type VariableKinds = chalk_ir::VariableKinds<Interner>;
71pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; 74pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
75pub type Binders<T> = chalk_ir::Binders<T>;
76pub type Substitution = chalk_ir::Substitution<Interner>;
77pub type GenericArg = chalk_ir::GenericArg<Interner>;
78pub type GenericArgData = chalk_ir::GenericArgData<Interner>;
79
80pub type Ty = chalk_ir::Ty<Interner>;
81pub type TyKind = chalk_ir::TyKind<Interner>;
82pub type DynTy = chalk_ir::DynTy<Interner>;
83pub type FnPointer = chalk_ir::FnPointer<Interner>;
84// pub type FnSubst = chalk_ir::FnSubst<Interner>;
85pub use chalk_ir::FnSubst;
86pub type ProjectionTy = chalk_ir::ProjectionTy<Interner>;
87pub type AliasTy = chalk_ir::AliasTy<Interner>;
88pub type OpaqueTy = chalk_ir::OpaqueTy<Interner>;
89pub type InferenceVar = chalk_ir::InferenceVar;
90
91pub type Lifetime = chalk_ir::Lifetime<Interner>;
92pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
93pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
94
95pub type Const = chalk_ir::Const<Interner>;
96pub type ConstData = chalk_ir::ConstData<Interner>;
97pub type ConstValue = chalk_ir::ConstValue<Interner>;
98pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
72 99
73pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 100pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
74 101pub type TraitRef = chalk_ir::TraitRef<Interner>;
75impl ProjectionTy { 102pub type QuantifiedWhereClause = Binders<WhereClause>;
76 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { 103pub type QuantifiedWhereClauses = chalk_ir::QuantifiedWhereClauses<Interner>;
77 TraitRef { 104pub type Canonical<T> = chalk_ir::Canonical<T>;
78 trait_id: to_chalk_trait_id(self.trait_(db)),
79 substitution: self.substitution.clone(),
80 }
81 }
82
83 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty {
84 &self.substitution.interned()[0].assert_ty_ref(interner)
85 }
86
87 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
88 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
89 AssocContainerId::TraitId(it) => it,
90 _ => panic!("projection ty without parent trait"),
91 }
92 }
93}
94 105
95pub type FnSig = chalk_ir::FnSig<Interner>; 106pub type FnSig = chalk_ir::FnSig<Interner>;
96 107
97impl Substitution { 108pub type InEnvironment<T> = chalk_ir::InEnvironment<T>;
98 pub fn single(ty: Ty) -> Substitution { 109pub type DomainGoal = chalk_ir::DomainGoal<Interner>;
99 Substitution::intern({ 110pub type AliasEq = chalk_ir::AliasEq<Interner>;
100 let mut v = SmallVec::new(); 111pub type Solution = chalk_solve::Solution<Interner>;
101 v.push(ty.cast(&Interner)); 112pub type ConstrainedSubst = chalk_ir::ConstrainedSubst<Interner>;
102 v 113pub type Guidance = chalk_solve::Guidance<Interner>;
103 }) 114pub type WhereClause = chalk_ir::WhereClause<Interner>;
104 } 115
105 116// FIXME: get rid of this
106 pub fn prefix(&self, n: usize) -> Substitution { 117pub fn subst_prefix(s: &Substitution, n: usize) -> Substitution {
107 Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into()) 118 Substitution::from_iter(
108 } 119 &Interner,
109 120 s.as_slice(&Interner)[..std::cmp::min(s.len(&Interner), n)].iter().cloned(),
110 pub fn suffix(&self, n: usize) -> Substitution { 121 )
111 Substitution::intern(
112 self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(),
113 )
114 }
115} 122}
116 123
117/// Return an index of a parameter in the generic type parameter list by it's id. 124/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -119,25 +126,17 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
119 generics(db.upcast(), id.parent).param_idx(id) 126 generics(db.upcast(), id.parent).param_idx(id)
120} 127}
121 128
122impl<T> Binders<T> { 129pub(crate) fn wrap_empty_binders<T>(value: T) -> Binders<T>
123 pub fn wrap_empty(value: T) -> Self 130where
124 where 131 T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>,
125 T: TypeWalk, 132{
126 { 133 Binders::empty(&Interner, value.shifted_in_from(&Interner, DebruijnIndex::ONE))
127 Binders::empty(&Interner, value.shifted_in_from(DebruijnIndex::ONE))
128 }
129}
130
131impl<T: TypeWalk> Binders<T> {
132 /// Substitutes all variables.
133 pub fn substitute(self, interner: &Interner, subst: &Substitution) -> T {
134 let (value, binders) = self.into_value_and_skipped_binders();
135 assert_eq!(subst.len(interner), binders.len(interner));
136 value.subst_bound_vars(subst)
137 }
138} 134}
139 135
140pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> { 136pub(crate) fn make_only_type_binders<T: HasInterner<Interner = Interner>>(
137 num_vars: usize,
138 value: T,
139) -> Binders<T> {
141 Binders::new( 140 Binders::new(
142 VariableKinds::from_iter( 141 VariableKinds::from_iter(
143 &Interner, 142 &Interner,
@@ -148,42 +147,18 @@ pub fn make_only_type_binders<T>(num_vars: usize, value: T) -> Binders<T> {
148 ) 147 )
149} 148}
150 149
151impl TraitRef { 150// FIXME: get rid of this
152 pub fn self_type_parameter(&self, interner: &Interner) -> &Ty { 151pub fn make_canonical<T: HasInterner<Interner = Interner>>(
153 &self.substitution.at(interner, 0).assert_ty_ref(interner) 152 value: T,
154 } 153 kinds: impl IntoIterator<Item = TyVariableKind>,
155 154) -> Canonical<T> {
156 pub fn hir_trait_id(&self) -> TraitId { 155 let kinds = kinds.into_iter().map(|tk| {
157 from_chalk_trait_id(self.trait_id) 156 chalk_ir::CanonicalVarKind::new(
158 } 157 chalk_ir::VariableKind::Ty(tk),
159} 158 chalk_ir::UniverseIndex::ROOT,
160 159 )
161impl WhereClause { 160 });
162 pub fn is_implemented(&self) -> bool { 161 Canonical { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
163 matches!(self, WhereClause::Implemented(_))
164 }
165
166 pub fn trait_ref(&self, db: &dyn HirDatabase) -> Option<TraitRef> {
167 match self {
168 WhereClause::Implemented(tr) => Some(tr.clone()),
169 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(proj), .. }) => {
170 Some(proj.trait_ref(db))
171 }
172 WhereClause::AliasEq(_) => None,
173 }
174 }
175}
176
177impl<T> Canonical<T> {
178 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
179 let kinds = kinds.into_iter().map(|tk| {
180 chalk_ir::CanonicalVarKind::new(
181 chalk_ir::VariableKind::Ty(tk),
182 chalk_ir::UniverseIndex::ROOT,
183 )
184 });
185 Self { value, binders: chalk_ir::CanonicalVarKinds::from_iter(&Interner, kinds) }
186 }
187} 162}
188 163
189/// A function signature as seen by type inference: Several parameter types and 164/// A function signature as seen by type inference: Several parameter types and
@@ -194,6 +169,8 @@ pub struct CallableSig {
194 is_varargs: bool, 169 is_varargs: bool,
195} 170}
196 171
172has_interner!(CallableSig);
173
197/// A polymorphic function signature. 174/// A polymorphic function signature.
198pub type PolyFnSig = Binders<CallableSig>; 175pub type PolyFnSig = Binders<CallableSig>;
199 176
@@ -207,11 +184,12 @@ impl CallableSig {
207 CallableSig { 184 CallableSig {
208 // FIXME: what to do about lifetime params? -> return PolyFnSig 185 // FIXME: what to do about lifetime params? -> return PolyFnSig
209 params_and_return: fn_ptr 186 params_and_return: fn_ptr
210 .substs 187 .substitution
211 .clone() 188 .clone()
212 .shifted_out_to(DebruijnIndex::ONE) 189 .shifted_out_to(&Interner, DebruijnIndex::ONE)
213 .expect("unexpected lifetime vars in fn ptr") 190 .expect("unexpected lifetime vars in fn ptr")
214 .interned() 191 .0
192 .as_slice(&Interner)
215 .iter() 193 .iter()
216 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 194 .map(|arg| arg.assert_ty_ref(&Interner).clone())
217 .collect(), 195 .collect(),
@@ -228,275 +206,20 @@ impl CallableSig {
228 } 206 }
229} 207}
230 208
231impl Ty { 209impl Fold<Interner> for CallableSig {
232 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 210 type Result = CallableSig;
233 match self.kind(&Interner) {
234 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
235 _ => None,
236 }
237 }
238
239 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
240 match self.kind(&Interner) {
241 TyKind::Ref(mutability, ty) => Some((ty, Rawness::Ref, *mutability)),
242 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
243 _ => None,
244 }
245 }
246
247 pub fn strip_references(&self) -> &Ty {
248 let mut t: &Ty = self;
249
250 while let TyKind::Ref(_mutability, ty) = t.kind(&Interner) {
251 t = ty;
252 }
253 211
254 t 212 fn fold_with<'i>(
255 } 213 self,
256 214 folder: &mut dyn chalk_ir::fold::Folder<'i, Interner>,
257 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> { 215 outer_binder: DebruijnIndex,
258 match self.kind(&Interner) { 216 ) -> chalk_ir::Fallible<Self::Result>
259 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)), 217 where
260 _ => None, 218 Interner: 'i,
261 } 219 {
262 } 220 let vec = self.params_and_return.to_vec();
263 221 let folded = vec.fold_with(folder, outer_binder)?;
264 pub fn as_tuple(&self) -> Option<&Substitution> { 222 Ok(CallableSig { params_and_return: folded.into(), is_varargs: self.is_varargs })
265 match self.kind(&Interner) {
266 TyKind::Tuple(_, substs) => Some(substs),
267 _ => None,
268 }
269 }
270
271 pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
272 match *self.kind(&Interner) {
273 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
274 TyKind::FnDef(callable, ..) => {
275 Some(db.lookup_intern_callable_def(callable.into()).into())
276 }
277 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
278 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
279 _ => None,
280 }
281 }
282
283 pub fn is_never(&self) -> bool {
284 matches!(self.kind(&Interner), TyKind::Never)
285 }
286
287 pub fn is_unknown(&self) -> bool {
288 matches!(self.kind(&Interner), TyKind::Error)
289 }
290
291 pub fn equals_ctor(&self, other: &Ty) -> bool {
292 match (self.kind(&Interner), other.kind(&Interner)) {
293 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
294 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true,
295 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
296 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
297 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
298 ty_id == ty_id2
299 }
300 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
301 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
302 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
303 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
304 mutability == mutability2
305 }
306 (
307 TyKind::Function(FnPointer { num_args, sig, .. }),
308 TyKind::Function(FnPointer { num_args: num_args2, sig: sig2, .. }),
309 ) => num_args == num_args2 && sig == sig2,
310 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
311 cardinality == cardinality2
312 }
313 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
314 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
315 _ => false,
316 }
317 }
318
319 /// If this is a `dyn Trait` type, this returns the `Trait` part.
320 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
321 match self.kind(&Interner) {
322 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
323 match b.skip_binders() {
324 WhereClause::Implemented(trait_ref) => Some(trait_ref),
325 _ => None,
326 }
327 }),
328 _ => None,
329 }
330 }
331
332 /// If this is a `dyn Trait`, returns that trait.
333 pub fn dyn_trait(&self) -> Option<TraitId> {
334 self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id)
335 }
336
337 fn builtin_deref(&self) -> Option<Ty> {
338 match self.kind(&Interner) {
339 TyKind::Ref(.., ty) => Some(ty.clone()),
340 TyKind::Raw(.., ty) => Some(ty.clone()),
341 _ => None,
342 }
343 }
344
345 pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
346 match self.kind(&Interner) {
347 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
348 _ => None,
349 }
350 }
351
352 pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
353 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
354 Some(func)
355 } else {
356 None
357 }
358 }
359
360 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
361 match self.kind(&Interner) {
362 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
363 TyKind::FnDef(def, parameters) => {
364 let callable_def = db.lookup_intern_callable_def((*def).into());
365 let sig = db.callable_item_signature(callable_def);
366 Some(sig.substitute(&Interner, &parameters))
367 }
368 TyKind::Closure(.., substs) => {
369 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
370 sig_param.callable_sig(db)
371 }
372 _ => None,
373 }
374 }
375
376 /// Returns the type parameters of this type if it has some (i.e. is an ADT
377 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
378 pub fn substs(&self) -> Option<&Substitution> {
379 match self.kind(&Interner) {
380 TyKind::Adt(_, substs)
381 | TyKind::FnDef(_, substs)
382 | TyKind::Function(FnPointer { substs, .. })
383 | TyKind::Tuple(_, substs)
384 | TyKind::OpaqueType(_, substs)
385 | TyKind::AssociatedType(_, substs)
386 | TyKind::Closure(.., substs) => Some(substs),
387 _ => None,
388 }
389 }
390
391 fn substs_mut(&mut self) -> Option<&mut Substitution> {
392 match self.interned_mut() {
393 TyKind::Adt(_, substs)
394 | TyKind::FnDef(_, substs)
395 | TyKind::Function(FnPointer { substs, .. })
396 | TyKind::Tuple(_, substs)
397 | TyKind::OpaqueType(_, substs)
398 | TyKind::AssociatedType(_, substs)
399 | TyKind::Closure(.., substs) => Some(substs),
400 _ => None,
401 }
402 }
403
404 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
405 match self.kind(&Interner) {
406 TyKind::OpaqueType(opaque_ty_id, ..) => {
407 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
408 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
409 let krate = def.module(db.upcast()).krate();
410 if let Some(future_trait) = db
411 .lang_item(krate, "future_trait".into())
412 .and_then(|item| item.as_trait())
413 {
414 // This is only used by type walking.
415 // Parameters will be walked outside, and projection predicate is not used.
416 // So just provide the Future trait.
417 let impl_bound = Binders::empty(
418 &Interner,
419 WhereClause::Implemented(TraitRef {
420 trait_id: to_chalk_trait_id(future_trait),
421 substitution: Substitution::empty(&Interner),
422 }),
423 );
424 Some(vec![impl_bound])
425 } else {
426 None
427 }
428 }
429 ImplTraitId::ReturnTypeImplTrait(..) => None,
430 }
431 }
432 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
433 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
434 {
435 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
436 db.return_type_impl_traits(func).map(|it| {
437 let data = (*it)
438 .as_ref()
439 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
440 data.substitute(&Interner, &opaque_ty.substitution)
441 })
442 }
443 // It always has an parameter for Future::Output type.
444 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
445 };
446
447 predicates.map(|it| it.into_value_and_skipped_binders().0)
448 }
449 TyKind::Placeholder(idx) => {
450 let id = from_placeholder_idx(db, *idx);
451 let generic_params = db.generic_params(id.parent);
452 let param_data = &generic_params.types[id.local_id];
453 match param_data.provenance {
454 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
455 let substs = TyBuilder::type_params_subst(db, id.parent);
456 let predicates = db
457 .generic_predicates(id.parent)
458 .into_iter()
459 .map(|pred| pred.clone().substitute(&Interner, &substs))
460 .filter(|wc| match &wc.skip_binders() {
461 WhereClause::Implemented(tr) => {
462 tr.self_type_parameter(&Interner) == self
463 }
464 WhereClause::AliasEq(AliasEq {
465 alias: AliasTy::Projection(proj),
466 ty: _,
467 }) => proj.self_type_parameter(&Interner) == self,
468 _ => false,
469 })
470 .collect_vec();
471
472 Some(predicates)
473 }
474 _ => None,
475 }
476 }
477 _ => None,
478 }
479 }
480
481 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
482 match self.kind(&Interner) {
483 TyKind::AssociatedType(id, ..) => {
484 match from_assoc_type_id(*id).lookup(db.upcast()).container {
485 AssocContainerId::TraitId(trait_id) => Some(trait_id),
486 _ => None,
487 }
488 }
489 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
490 match from_assoc_type_id(projection_ty.associated_ty_id)
491 .lookup(db.upcast())
492 .container
493 {
494 AssocContainerId::TraitId(trait_id) => Some(trait_id),
495 _ => None,
496 }
497 }
498 _ => None,
499 }
500 } 223 }
501} 224}
502 225
@@ -511,45 +234,75 @@ pub struct ReturnTypeImplTraits {
511 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>, 234 pub(crate) impl_traits: Vec<ReturnTypeImplTrait>,
512} 235}
513 236
237has_interner!(ReturnTypeImplTraits);
238
514#[derive(Clone, PartialEq, Eq, Debug, Hash)] 239#[derive(Clone, PartialEq, Eq, Debug, Hash)]
515pub(crate) struct ReturnTypeImplTrait { 240pub(crate) struct ReturnTypeImplTrait {
516 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>, 241 pub(crate) bounds: Binders<Vec<QuantifiedWhereClause>>,
517} 242}
518 243
519pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId { 244pub fn static_lifetime() -> Lifetime {
520 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id)) 245 LifetimeData::Static.intern(&Interner)
521}
522
523pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
524 salsa::InternKey::from_intern_id(id.0)
525} 246}
526 247
527pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId { 248pub fn dummy_usize_const() -> Const {
528 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id)) 249 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
250 chalk_ir::ConstData {
251 ty: usize_ty,
252 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
253 }
254 .intern(&Interner)
529} 255}
530 256
531pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId { 257pub(crate) fn fold_free_vars<T: HasInterner<Interner = Interner> + Fold<Interner>>(
532 salsa::InternKey::from_intern_id(id.0) 258 t: T,
533} 259 f: impl FnMut(BoundVar, DebruijnIndex) -> Ty,
260) -> T::Result {
261 use chalk_ir::{fold::Folder, Fallible};
262 struct FreeVarFolder<F>(F);
263 impl<'i, F: FnMut(BoundVar, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for FreeVarFolder<F> {
264 fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
265 self
266 }
534 267
535pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId { 268 fn interner(&self) -> &'i Interner {
536 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT); 269 &Interner
537 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx)); 270 }
538 db.lookup_intern_type_param_id(interned_id)
539}
540 271
541pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex { 272 fn fold_free_var_ty(
542 let interned_id = db.intern_type_param_id(id); 273 &mut self,
543 PlaceholderIndex { 274 bound_var: BoundVar,
544 ui: chalk_ir::UniverseIndex::ROOT, 275 outer_binder: DebruijnIndex,
545 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(), 276 ) -> Fallible<Ty> {
277 Ok(self.0(bound_var, outer_binder))
278 }
546 } 279 }
280 t.fold_with(&mut FreeVarFolder(f), DebruijnIndex::INNERMOST).expect("fold failed unexpectedly")
547} 281}
548 282
549pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { 283pub(crate) fn fold_tys<T: HasInterner<Interner = Interner> + Fold<Interner>>(
550 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) 284 t: T,
551} 285 f: impl FnMut(Ty, DebruijnIndex) -> Ty,
286 binders: DebruijnIndex,
287) -> T::Result {
288 use chalk_ir::{
289 fold::{Folder, SuperFold},
290 Fallible,
291 };
292 struct TyFolder<F>(F);
293 impl<'i, F: FnMut(Ty, DebruijnIndex) -> Ty + 'i> Folder<'i, Interner> for TyFolder<F> {
294 fn as_dyn(&mut self) -> &mut dyn Folder<'i, Interner> {
295 self
296 }
552 297
553pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId { 298 fn interner(&self) -> &'i Interner {
554 salsa::InternKey::from_intern_id(id.0) 299 &Interner
300 }
301
302 fn fold_ty(&mut self, ty: Ty, outer_binder: DebruijnIndex) -> Fallible<Ty> {
303 let ty = ty.super_fold_with(self.as_dyn(), outer_binder)?;
304 Ok(self.0(ty, outer_binder))
305 }
306 }
307 t.fold_with(&mut TyFolder(f), binders).expect("fold failed unexpectedly")
555} 308}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index 48c26f471..a035686bc 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -8,7 +8,7 @@
8use std::{iter, sync::Arc}; 8use std::{iter, sync::Arc};
9 9
10use base_db::CrateId; 10use base_db::CrateId;
11use chalk_ir::{cast::Cast, Mutability, Safety}; 11use chalk_ir::{cast::Cast, fold::Shift, interner::HasInterner, Mutability, Safety};
12use hir_def::{ 12use hir_def::{
13 adt::StructKind, 13 adt::StructKind,
14 builtin_type::BuiltinType, 14 builtin_type::BuiltinType,
@@ -27,16 +27,16 @@ use stdx::impl_from;
27 27
28use crate::{ 28use crate::{
29 db::HirDatabase, 29 db::HirDatabase,
30 to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, 30 dummy_usize_const,
31 traits::chalk::{Interner, ToChalk}, 31 mapping::ToChalk,
32 static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
32 utils::{ 33 utils::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 34 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, Generics,
34 variant_data, Generics,
35 }, 35 },
36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, 37 FnSubst, ImplTraitId, Interner, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause,
38 ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, 38 QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution,
39 TyBuilder, TyKind, TypeWalk, WhereClause, 39 TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
40}; 40};
41 41
42#[derive(Debug)] 42#[derive(Debug)]
@@ -166,7 +166,7 @@ impl<'a> TyLoweringContext<'a> {
166 } 166 }
167 TypeRef::Array(inner) => { 167 TypeRef::Array(inner) => {
168 let inner_ty = self.lower_ty(inner); 168 let inner_ty = self.lower_ty(inner);
169 TyKind::Array(inner_ty).intern(&Interner) 169 TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
170 } 170 }
171 TypeRef::Slice(inner) => { 171 TypeRef::Slice(inner) => {
172 let inner_ty = self.lower_ty(inner); 172 let inner_ty = self.lower_ty(inner);
@@ -174,16 +174,19 @@ impl<'a> TyLoweringContext<'a> {
174 } 174 }
175 TypeRef::Reference(inner, _, mutability) => { 175 TypeRef::Reference(inner, _, mutability) => {
176 let inner_ty = self.lower_ty(inner); 176 let inner_ty = self.lower_ty(inner);
177 TyKind::Ref(lower_to_chalk_mutability(*mutability), inner_ty).intern(&Interner) 177 let lifetime = static_lifetime();
178 TyKind::Ref(lower_to_chalk_mutability(*mutability), lifetime, inner_ty)
179 .intern(&Interner)
178 } 180 }
179 TypeRef::Placeholder => TyKind::Error.intern(&Interner), 181 TypeRef::Placeholder => TyKind::Error.intern(&Interner),
180 TypeRef::Fn(params, is_varargs) => { 182 TypeRef::Fn(params, is_varargs) => {
181 let substs = 183 let substs = self.with_shifted_in(DebruijnIndex::ONE, |ctx| {
182 Substitution::from_iter(&Interner, params.iter().map(|tr| self.lower_ty(tr))); 184 Substitution::from_iter(&Interner, params.iter().map(|tr| ctx.lower_ty(tr)))
185 });
183 TyKind::Function(FnPointer { 186 TyKind::Function(FnPointer {
184 num_args: substs.len(&Interner) - 1, 187 num_binders: 0, // FIXME lower `for<'a> fn()` correctly
185 sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs }, 188 sig: FnSig { abi: (), safety: Safety::Safe, variadic: *is_varargs },
186 substs, 189 substitution: FnSubst(substs),
187 }) 190 })
188 .intern(&Interner) 191 .intern(&Interner)
189 } 192 }
@@ -197,7 +200,7 @@ impl<'a> TyLoweringContext<'a> {
197 ) 200 )
198 }); 201 });
199 let bounds = crate::make_only_type_binders(1, bounds); 202 let bounds = crate::make_only_type_binders(1, bounds);
200 TyKind::Dyn(DynTy { bounds }).intern(&Interner) 203 TyKind::Dyn(DynTy { bounds, lifetime: static_lifetime() }).intern(&Interner)
201 } 204 }
202 TypeRef::ImplTrait(bounds) => { 205 TypeRef::ImplTrait(bounds) => {
203 match self.impl_trait_mode { 206 match self.impl_trait_mode {
@@ -384,9 +387,12 @@ impl<'a> TyLoweringContext<'a> {
384 1, 387 1,
385 QuantifiedWhereClauses::from_iter( 388 QuantifiedWhereClauses::from_iter(
386 &Interner, 389 &Interner,
387 Some(Binders::wrap_empty(WhereClause::Implemented(trait_ref))), 390 Some(crate::wrap_empty_binders(WhereClause::Implemented(
391 trait_ref,
392 ))),
388 ), 393 ),
389 ), 394 ),
395 lifetime: static_lifetime(),
390 }; 396 };
391 TyKind::Dyn(dyn_ty).intern(&Interner) 397 TyKind::Dyn(dyn_ty).intern(&Interner)
392 }; 398 };
@@ -483,7 +489,7 @@ impl<'a> TyLoweringContext<'a> {
483 }; 489 };
484 // We need to shift in the bound vars, since 490 // We need to shift in the bound vars, since
485 // associated_type_shorthand_candidates does not do that 491 // associated_type_shorthand_candidates does not do that
486 let substs = substs.shifted_in_from(self.in_binders); 492 let substs = substs.shifted_in_from(&Interner, self.in_binders);
487 // FIXME handle type parameters on the segment 493 // FIXME handle type parameters on the segment
488 return Some( 494 return Some(
489 TyKind::Alias(AliasTy::Projection(ProjectionTy { 495 TyKind::Alias(AliasTy::Projection(ProjectionTy {
@@ -720,7 +726,7 @@ impl<'a> TyLoweringContext<'a> {
720 let trait_ref = match bound { 726 let trait_ref = match bound {
721 TypeBound::Path(path) => { 727 TypeBound::Path(path) => {
722 bindings = self.lower_trait_ref_from_path(path, Some(self_ty)); 728 bindings = self.lower_trait_ref_from_path(path, Some(self_ty));
723 bindings.clone().map(WhereClause::Implemented).map(|b| Binders::wrap_empty(b)) 729 bindings.clone().map(WhereClause::Implemented).map(|b| crate::wrap_empty_binders(b))
724 } 730 }
725 TypeBound::Lifetime(_) => None, 731 TypeBound::Lifetime(_) => None,
726 TypeBound::Error => None, 732 TypeBound::Error => None,
@@ -767,7 +773,7 @@ impl<'a> TyLoweringContext<'a> {
767 let ty = self.lower_ty(type_ref); 773 let ty = self.lower_ty(type_ref);
768 let alias_eq = 774 let alias_eq =
769 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty }; 775 AliasEq { alias: AliasTy::Projection(projection_ty.clone()), ty };
770 preds.push(Binders::wrap_empty(WhereClause::AliasEq(alias_eq))); 776 preds.push(crate::wrap_empty_binders(WhereClause::AliasEq(alias_eq)));
771 } 777 }
772 for bound in &binding.bounds { 778 for bound in &binding.bounds {
773 preds.extend(self.lower_type_bound( 779 preds.extend(self.lower_type_bound(
@@ -842,7 +848,7 @@ pub fn associated_type_shorthand_candidates<R>(
842 // FIXME: how to correctly handle higher-ranked bounds here? 848 // FIXME: how to correctly handle higher-ranked bounds here?
843 WhereClause::Implemented(tr) => search( 849 WhereClause::Implemented(tr) => search(
844 tr.clone() 850 tr.clone()
845 .shifted_out_to(DebruijnIndex::ONE) 851 .shifted_out_to(&Interner, DebruijnIndex::ONE)
846 .expect("FIXME unexpected higher-ranked trait bound"), 852 .expect("FIXME unexpected higher-ranked trait bound"),
847 ), 853 ),
848 _ => None, 854 _ => None,
@@ -873,7 +879,7 @@ pub(crate) fn field_types_query(
873 db: &dyn HirDatabase, 879 db: &dyn HirDatabase,
874 variant_id: VariantId, 880 variant_id: VariantId,
875) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> { 881) -> Arc<ArenaMap<LocalFieldId, Binders<Ty>>> {
876 let var_data = variant_data(db.upcast(), variant_id); 882 let var_data = variant_id.variant_data(db.upcast());
877 let (resolver, def): (_, GenericDefId) = match variant_id { 883 let (resolver, def): (_, GenericDefId) = match variant_id {
878 VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()), 884 VariantId::StructId(it) => (it.resolver(db.upcast()), it.into()),
879 VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()), 885 VariantId::UnionId(it) => (it.resolver(db.upcast()), it.into()),
@@ -945,8 +951,7 @@ pub(crate) fn trait_environment_query(
945 traits_in_scope 951 traits_in_scope
946 .push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id())); 952 .push((tr.self_type_parameter(&Interner).clone(), tr.hir_trait_id()));
947 } 953 }
948 let program_clause: chalk_ir::ProgramClause<Interner> = 954 let program_clause: chalk_ir::ProgramClause<Interner> = pred.clone().cast(&Interner);
949 pred.clone().to_chalk(db).cast(&Interner);
950 clauses.push(program_clause.into_from_env_clause(&Interner)); 955 clauses.push(program_clause.into_from_env_clause(&Interner));
951 } 956 }
952 } 957 }
@@ -969,7 +974,7 @@ pub(crate) fn trait_environment_query(
969 let substs = TyBuilder::type_params_subst(db, trait_id); 974 let substs = TyBuilder::type_params_subst(db, trait_id);
970 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; 975 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
971 let pred = WhereClause::Implemented(trait_ref); 976 let pred = WhereClause::Implemented(trait_ref);
972 let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); 977 let program_clause: chalk_ir::ProgramClause<Interner> = pred.cast(&Interner);
973 clauses.push(program_clause.into_from_env_clause(&Interner)); 978 clauses.push(program_clause.into_from_env_clause(&Interner));
974 } 979 }
975 980
@@ -1011,22 +1016,16 @@ pub(crate) fn generic_defaults_query(
1011 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t)); 1016 p.default.as_ref().map_or(TyKind::Error.intern(&Interner), |t| ctx.lower_ty(t));
1012 1017
1013 // Each default can only refer to previous parameters. 1018 // Each default can only refer to previous parameters.
1014 ty = ty.fold_binders( 1019 ty = crate::fold_free_vars(ty, |bound, binders| {
1015 &mut |ty, binders| match ty.kind(&Interner) { 1020 if bound.index >= idx && bound.debruijn == DebruijnIndex::INNERMOST {
1016 TyKind::BoundVar(BoundVar { debruijn, index }) if *debruijn == binders => { 1021 // type variable default referring to parameter coming
1017 if *index >= idx { 1022 // after it. This is forbidden (FIXME: report
1018 // type variable default referring to parameter coming 1023 // diagnostic)
1019 // after it. This is forbidden (FIXME: report 1024 TyKind::Error.intern(&Interner)
1020 // diagnostic) 1025 } else {
1021 TyKind::Error.intern(&Interner) 1026 bound.shifted_in_from(binders).to_ty(&Interner)
1022 } else { 1027 }
1023 ty 1028 });
1024 }
1025 }
1026 _ => ty,
1027 },
1028 DebruijnIndex::INNERMOST,
1029 );
1030 1029
1031 crate::make_only_type_binders(idx, ty) 1030 crate::make_only_type_binders(idx, ty)
1032 }) 1031 })
@@ -1302,6 +1301,6 @@ pub(crate) fn lower_to_chalk_mutability(m: hir_def::type_ref::Mutability) -> Mut
1302 } 1301 }
1303} 1302}
1304 1303
1305fn make_binders<T>(generics: &Generics, value: T) -> Binders<T> { 1304fn make_binders<T: HasInterner<Interner = Interner>>(generics: &Generics, value: T) -> Binders<T> {
1306 crate::make_only_type_binders(generics.len(), value) 1305 crate::make_only_type_binders(generics.len(), value)
1307} 1306}
diff --git a/crates/hir_ty/src/mapping.rs b/crates/hir_ty/src/mapping.rs
new file mode 100644
index 000000000..5e86fafe5
--- /dev/null
+++ b/crates/hir_ty/src/mapping.rs
@@ -0,0 +1,154 @@
1//! This module contains the implementations of the `ToChalk` trait, which
2//! handles conversion between our data types and their corresponding types in
3//! Chalk (in both directions); plus some helper functions for more specialized
4//! conversions.
5
6use chalk_solve::rust_ir;
7
8use base_db::salsa::{self, InternKey};
9use hir_def::{ConstParamId, LifetimeParamId, TraitId, TypeAliasId, TypeParamId};
10
11use crate::{
12 chalk_db, db::HirDatabase, AssocTypeId, CallableDefId, ChalkTraitId, FnDefId, ForeignDefId,
13 Interner, OpaqueTyId, PlaceholderIndex,
14};
15
16pub(crate) trait ToChalk {
17 type Chalk;
18 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk;
19 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self;
20}
21
22pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T
23where
24 T: ToChalk<Chalk = ChalkT>,
25{
26 T::from_chalk(db, chalk)
27}
28
29impl ToChalk for hir_def::ImplId {
30 type Chalk = chalk_db::ImplId;
31
32 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::ImplId {
33 chalk_ir::ImplId(self.as_intern_id())
34 }
35
36 fn from_chalk(_db: &dyn HirDatabase, impl_id: chalk_db::ImplId) -> hir_def::ImplId {
37 InternKey::from_intern_id(impl_id.0)
38 }
39}
40
41impl ToChalk for CallableDefId {
42 type Chalk = FnDefId;
43
44 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
45 db.intern_callable_def(self).into()
46 }
47
48 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
49 db.lookup_intern_callable_def(fn_def_id.into())
50 }
51}
52
53pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
54
55impl ToChalk for TypeAliasAsValue {
56 type Chalk = chalk_db::AssociatedTyValueId;
57
58 fn to_chalk(self, _db: &dyn HirDatabase) -> chalk_db::AssociatedTyValueId {
59 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
60 }
61
62 fn from_chalk(
63 _db: &dyn HirDatabase,
64 assoc_ty_value_id: chalk_db::AssociatedTyValueId,
65 ) -> TypeAliasAsValue {
66 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
67 }
68}
69
70impl From<FnDefId> for crate::db::InternedCallableDefId {
71 fn from(fn_def_id: FnDefId) -> Self {
72 InternKey::from_intern_id(fn_def_id.0)
73 }
74}
75
76impl From<crate::db::InternedCallableDefId> for FnDefId {
77 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self {
78 chalk_ir::FnDefId(callable_def_id.as_intern_id())
79 }
80}
81
82impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
83 fn from(id: OpaqueTyId) -> Self {
84 InternKey::from_intern_id(id.0)
85 }
86}
87
88impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
89 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
90 chalk_ir::OpaqueTyId(id.as_intern_id())
91 }
92}
93
94impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
95 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
96 Self::from_intern_id(id.0)
97 }
98}
99
100impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> {
101 fn from(id: crate::db::InternedClosureId) -> Self {
102 chalk_ir::ClosureId(id.as_intern_id())
103 }
104}
105
106pub fn to_foreign_def_id(id: TypeAliasId) -> ForeignDefId {
107 chalk_ir::ForeignDefId(salsa::InternKey::as_intern_id(&id))
108}
109
110pub fn from_foreign_def_id(id: ForeignDefId) -> TypeAliasId {
111 salsa::InternKey::from_intern_id(id.0)
112}
113
114pub fn to_assoc_type_id(id: TypeAliasId) -> AssocTypeId {
115 chalk_ir::AssocTypeId(salsa::InternKey::as_intern_id(&id))
116}
117
118pub fn from_assoc_type_id(id: AssocTypeId) -> TypeAliasId {
119 salsa::InternKey::from_intern_id(id.0)
120}
121
122pub fn from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> TypeParamId {
123 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
124 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
125 db.lookup_intern_type_param_id(interned_id)
126}
127
128pub fn to_placeholder_idx(db: &dyn HirDatabase, id: TypeParamId) -> PlaceholderIndex {
129 let interned_id = db.intern_type_param_id(id);
130 PlaceholderIndex {
131 ui: chalk_ir::UniverseIndex::ROOT,
132 idx: salsa::InternKey::as_intern_id(&interned_id).as_usize(),
133 }
134}
135
136pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> LifetimeParamId {
137 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
138 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
139 db.lookup_intern_lifetime_param_id(interned_id)
140}
141
142pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
143 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
144 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
145 db.lookup_intern_const_param_id(interned_id)
146}
147
148pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
149 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
150}
151
152pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
153 salsa::InternKey::from_intern_id(id.0)
154}
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 19a1fa793..ece884241 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -8,62 +8,103 @@ use arrayvec::ArrayVec;
8use base_db::CrateId; 8use base_db::CrateId;
9use chalk_ir::{cast::Cast, Mutability, UniverseIndex}; 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, nameres::DefMap, AssocContainerId, AssocItemId, FunctionId,
12 ImplId, Lookup, ModuleId, TraitId, 12 GenericDefId, HasModule, ImplId, Lookup, ModuleId, TraitId,
13}; 13};
14use hir_expand::name::Name; 14use hir_expand::name::Name;
15use rustc_hash::{FxHashMap, FxHashSet}; 15use rustc_hash::{FxHashMap, FxHashSet};
16use stdx::always;
16 17
17use crate::{ 18use crate::{
18 autoderef, 19 autoderef,
19 db::HirDatabase, 20 db::HirDatabase,
20 from_foreign_def_id, 21 from_foreign_def_id,
21 primitive::{self, FloatTy, IntTy, UintTy}, 22 primitive::{self, FloatTy, IntTy, UintTy},
23 static_lifetime,
22 utils::all_super_traits, 24 utils::all_super_traits,
23 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, 25 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, ForeignDefId, InEnvironment, Interner,
24 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind, 26 Scalar, Substitution, TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyExt, TyKind,
25 TypeWalk,
26}; 27};
27 28
28/// This is used as a key for indexing impls. 29/// This is used as a key for indexing impls.
29#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 30#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
30pub enum TyFingerprint { 31pub enum TyFingerprint {
32 // These are lang item impls:
31 Str, 33 Str,
32 Slice, 34 Slice,
33 Array, 35 Array,
34 Never, 36 Never,
35 RawPtr(Mutability), 37 RawPtr(Mutability),
36 Scalar(Scalar), 38 Scalar(Scalar),
39 // These can have user-defined impls:
37 Adt(hir_def::AdtId), 40 Adt(hir_def::AdtId),
38 Dyn(TraitId), 41 Dyn(TraitId),
39 Tuple(usize),
40 ForeignType(ForeignDefId), 42 ForeignType(ForeignDefId),
41 FnPtr(usize, FnSig), 43 // These only exist for trait impls
44 Unit,
45 Unnameable,
46 Function(u32),
42} 47}
43 48
44impl TyFingerprint { 49impl TyFingerprint {
45 /// Creates a TyFingerprint for looking up an impl. Only certain types can 50 /// Creates a TyFingerprint for looking up an inherent impl. Only certain
46 /// have impls: if we have some `struct S`, we can have an `impl S`, but not 51 /// types can have inherent impls: if we have some `struct S`, we can have
47 /// `impl &S`. Hence, this will return `None` for reference types and such. 52 /// an `impl S`, but not `impl &S`. Hence, this will return `None` for
48 pub fn for_impl(ty: &Ty) -> Option<TyFingerprint> { 53 /// reference types and such.
49 let fp = match *ty.kind(&Interner) { 54 pub fn for_inherent_impl(ty: &Ty) -> Option<TyFingerprint> {
55 let fp = match ty.kind(&Interner) {
50 TyKind::Str => TyFingerprint::Str, 56 TyKind::Str => TyFingerprint::Str,
51 TyKind::Never => TyFingerprint::Never, 57 TyKind::Never => TyFingerprint::Never,
52 TyKind::Slice(..) => TyFingerprint::Slice, 58 TyKind::Slice(..) => TyFingerprint::Slice,
53 TyKind::Array(..) => TyFingerprint::Array, 59 TyKind::Array(..) => TyFingerprint::Array,
54 TyKind::Scalar(scalar) => TyFingerprint::Scalar(scalar), 60 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
55 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(adt), 61 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
56 TyKind::Tuple(cardinality, _) => TyFingerprint::Tuple(cardinality), 62 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
57 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(mutability), 63 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
58 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(alias_id),
59 TyKind::Function(FnPointer { num_args, sig, .. }) => {
60 TyFingerprint::FnPtr(num_args, sig)
61 }
62 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?, 64 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
63 _ => return None, 65 _ => return None,
64 }; 66 };
65 Some(fp) 67 Some(fp)
66 } 68 }
69
70 /// Creates a TyFingerprint for looking up a trait impl.
71 pub fn for_trait_impl(ty: &Ty) -> Option<TyFingerprint> {
72 let fp = match ty.kind(&Interner) {
73 TyKind::Str => TyFingerprint::Str,
74 TyKind::Never => TyFingerprint::Never,
75 TyKind::Slice(..) => TyFingerprint::Slice,
76 TyKind::Array(..) => TyFingerprint::Array,
77 TyKind::Scalar(scalar) => TyFingerprint::Scalar(*scalar),
78 TyKind::Adt(AdtId(adt), _) => TyFingerprint::Adt(*adt),
79 TyKind::Raw(mutability, ..) => TyFingerprint::RawPtr(*mutability),
80 TyKind::Foreign(alias_id, ..) => TyFingerprint::ForeignType(*alias_id),
81 TyKind::Dyn(_) => ty.dyn_trait().map(|trait_| TyFingerprint::Dyn(trait_))?,
82 TyKind::Ref(_, _, ty) => return TyFingerprint::for_trait_impl(ty),
83 TyKind::Tuple(_, subst) => {
84 let first_ty = subst.interned().get(0).map(|arg| arg.assert_ty_ref(&Interner));
85 if let Some(ty) = first_ty {
86 return TyFingerprint::for_trait_impl(ty);
87 } else {
88 TyFingerprint::Unit
89 }
90 }
91 TyKind::AssociatedType(_, _)
92 | TyKind::OpaqueType(_, _)
93 | TyKind::FnDef(_, _)
94 | TyKind::Closure(_, _)
95 | TyKind::Generator(..)
96 | TyKind::GeneratorWitness(..) => TyFingerprint::Unnameable,
97 TyKind::Function(fn_ptr) => {
98 TyFingerprint::Function(fn_ptr.substitution.0.len(&Interner) as u32)
99 }
100 TyKind::Alias(_)
101 | TyKind::Placeholder(_)
102 | TyKind::BoundVar(_)
103 | TyKind::InferenceVar(_, _)
104 | TyKind::Error => return None,
105 };
106 Some(fp)
107 }
67} 108}
68 109
69pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [ 110pub(crate) const ALL_INT_FPS: [TyFingerprint; 12] = [
@@ -99,25 +140,38 @@ impl TraitImpls {
99 let mut impls = Self { map: FxHashMap::default() }; 140 let mut impls = Self { map: FxHashMap::default() };
100 141
101 let crate_def_map = db.crate_def_map(krate); 142 let crate_def_map = db.crate_def_map(krate);
102 for (_module_id, module_data) in crate_def_map.modules() { 143 collect_def_map(db, &crate_def_map, &mut impls);
103 for impl_id in module_data.scope.impls() { 144
104 let target_trait = match db.impl_trait(impl_id) { 145 return Arc::new(impls);
105 Some(tr) => tr.skip_binders().hir_trait_id(), 146
106 None => continue, 147 fn collect_def_map(db: &dyn HirDatabase, def_map: &DefMap, impls: &mut TraitImpls) {
107 }; 148 for (_module_id, module_data) in def_map.modules() {
108 let self_ty = db.impl_self_ty(impl_id); 149 for impl_id in module_data.scope.impls() {
109 let self_ty_fp = TyFingerprint::for_impl(self_ty.skip_binders()); 150 let target_trait = match db.impl_trait(impl_id) {
110 impls 151 Some(tr) => tr.skip_binders().hir_trait_id(),
111 .map 152 None => continue,
112 .entry(target_trait) 153 };
113 .or_default() 154 let self_ty = db.impl_self_ty(impl_id);
114 .entry(self_ty_fp) 155 let self_ty_fp = TyFingerprint::for_trait_impl(self_ty.skip_binders());
115 .or_default() 156 impls
116 .push(impl_id); 157 .map
158 .entry(target_trait)
159 .or_default()
160 .entry(self_ty_fp)
161 .or_default()
162 .push(impl_id);
163 }
164
165 // To better support custom derives, collect impls in all unnamed const items.
166 // const _: () = { ... };
167 for konst in module_data.scope.unnamed_consts() {
168 let body = db.body(konst.into());
169 for (_, block_def_map) in body.blocks(db.upcast()) {
170 collect_def_map(db, &block_def_map, impls);
171 }
172 }
117 } 173 }
118 } 174 }
119
120 Arc::new(impls)
121 } 175 }
122 176
123 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> { 177 pub(crate) fn trait_impls_in_deps_query(db: &dyn HirDatabase, krate: CrateId) -> Arc<Self> {
@@ -143,10 +197,13 @@ impl TraitImpls {
143 } 197 }
144 198
145 /// Queries all trait impls for the given type. 199 /// Queries all trait impls for the given type.
146 pub fn for_self_ty(&self, fp: TyFingerprint) -> impl Iterator<Item = ImplId> + '_ { 200 pub fn for_self_ty_without_blanket_impls(
201 &self,
202 fp: TyFingerprint,
203 ) -> impl Iterator<Item = ImplId> + '_ {
147 self.map 204 self.map
148 .values() 205 .values()
149 .flat_map(move |impls| impls.get(&None).into_iter().chain(impls.get(&Some(fp)))) 206 .flat_map(move |impls| impls.get(&Some(fp)).into_iter())
150 .flat_map(|it| it.iter().copied()) 207 .flat_map(|it| it.iter().copied())
151 } 208 }
152 209
@@ -201,17 +258,22 @@ impl InherentImpls {
201 } 258 }
202 259
203 let self_ty = db.impl_self_ty(impl_id); 260 let self_ty = db.impl_self_ty(impl_id);
204 if let Some(fp) = TyFingerprint::for_impl(self_ty.skip_binders()) { 261 let fp = TyFingerprint::for_inherent_impl(self_ty.skip_binders());
262 always!(fp.is_some());
263 if let Some(fp) = fp {
205 map.entry(fp).or_default().push(impl_id); 264 map.entry(fp).or_default().push(impl_id);
206 } 265 }
207 } 266 }
208 } 267 }
209 268
269 // NOTE: We're not collecting inherent impls from unnamed consts here, we intentionally only
270 // support trait impls there.
271
210 Arc::new(Self { map }) 272 Arc::new(Self { map })
211 } 273 }
212 274
213 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] { 275 pub fn for_self_ty(&self, self_ty: &Ty) -> &[ImplId] {
214 match TyFingerprint::for_impl(self_ty) { 276 match TyFingerprint::for_inherent_impl(self_ty) {
215 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]), 277 Some(fp) => self.map.get(&fp).map(|vec| vec.as_ref()).unwrap_or(&[]),
216 None => &[], 278 None => &[],
217 } 279 }
@@ -222,15 +284,14 @@ impl InherentImpls {
222 } 284 }
223} 285}
224 286
225impl Ty { 287pub fn def_crates(
226 pub fn def_crates( 288 db: &dyn HirDatabase,
227 &self, 289 ty: &Ty,
228 db: &dyn HirDatabase, 290 cur_crate: CrateId,
229 cur_crate: CrateId, 291) -> Option<ArrayVec<CrateId, 2>> {
230 ) -> Option<ArrayVec<CrateId, 2>> { 292 // Types like slice can have inherent impls in several crates, (core and alloc).
231 // Types like slice can have inherent impls in several crates, (core and alloc). 293 // The corresponding impls are marked with lang items, so we can use them to find the required crates.
232 // The corresponding impls are marked with lang items, so we can use them to find the required crates. 294 macro_rules! lang_item_crate {
233 macro_rules! lang_item_crate {
234 ($($name:expr),+ $(,)?) => {{ 295 ($($name:expr),+ $(,)?) => {{
235 let mut v = ArrayVec::<LangItemTarget, 2>::new(); 296 let mut v = ArrayVec::<LangItemTarget, 2>::new();
236 $( 297 $(
@@ -240,51 +301,50 @@ impl Ty {
240 }}; 301 }};
241 } 302 }
242 303
243 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect()); 304 let mod_to_crate_ids = |module: ModuleId| Some(std::iter::once(module.krate()).collect());
244 305
245 let lang_item_targets = match self.kind(&Interner) { 306 let lang_item_targets = match ty.kind(&Interner) {
246 TyKind::Adt(AdtId(def_id), _) => { 307 TyKind::Adt(AdtId(def_id), _) => {
247 return mod_to_crate_ids(def_id.module(db.upcast())); 308 return mod_to_crate_ids(def_id.module(db.upcast()));
248 } 309 }
249 TyKind::Foreign(id) => { 310 TyKind::Foreign(id) => {
250 return mod_to_crate_ids( 311 return mod_to_crate_ids(
251 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()), 312 from_foreign_def_id(*id).lookup(db.upcast()).module(db.upcast()),
252 ); 313 );
253 } 314 }
254 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"), 315 TyKind::Scalar(Scalar::Bool) => lang_item_crate!("bool"),
255 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"), 316 TyKind::Scalar(Scalar::Char) => lang_item_crate!("char"),
256 TyKind::Scalar(Scalar::Float(f)) => match f { 317 TyKind::Scalar(Scalar::Float(f)) => match f {
257 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime) 318 // There are two lang items: one in libcore (fXX) and one in libstd (fXX_runtime)
258 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"), 319 FloatTy::F32 => lang_item_crate!("f32", "f32_runtime"),
259 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"), 320 FloatTy::F64 => lang_item_crate!("f64", "f64_runtime"),
260 }, 321 },
261 &TyKind::Scalar(Scalar::Int(t)) => { 322 &TyKind::Scalar(Scalar::Int(t)) => {
262 lang_item_crate!(primitive::int_ty_to_string(t)) 323 lang_item_crate!(primitive::int_ty_to_string(t))
263 } 324 }
264 &TyKind::Scalar(Scalar::Uint(t)) => { 325 &TyKind::Scalar(Scalar::Uint(t)) => {
265 lang_item_crate!(primitive::uint_ty_to_string(t)) 326 lang_item_crate!(primitive::uint_ty_to_string(t))
266 } 327 }
267 TyKind::Str => lang_item_crate!("str_alloc", "str"), 328 TyKind::Str => lang_item_crate!("str_alloc", "str"),
268 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"), 329 TyKind::Slice(_) => lang_item_crate!("slice_alloc", "slice"),
269 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"), 330 TyKind::Raw(Mutability::Not, _) => lang_item_crate!("const_ptr"),
270 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"), 331 TyKind::Raw(Mutability::Mut, _) => lang_item_crate!("mut_ptr"),
271 TyKind::Dyn(_) => { 332 TyKind::Dyn(_) => {
272 return self.dyn_trait().and_then(|trait_| { 333 return ty.dyn_trait().and_then(|trait_| {
273 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast())) 334 mod_to_crate_ids(GenericDefId::TraitId(trait_).module(db.upcast()))
274 }); 335 });
275 } 336 }
276 _ => return None, 337 _ => return None,
277 }; 338 };
278 let res = lang_item_targets 339 let res = lang_item_targets
279 .into_iter() 340 .into_iter()
280 .filter_map(|it| match it { 341 .filter_map(|it| match it {
281 LangItemTarget::ImplDefId(it) => Some(it), 342 LangItemTarget::ImplDefId(it) => Some(it),
282 _ => None, 343 _ => None,
283 }) 344 })
284 .map(|it| it.lookup(db.upcast()).container.krate()) 345 .map(|it| it.lookup(db.upcast()).container.krate())
285 .collect(); 346 .collect();
286 Some(res) 347 Some(res)
287 }
288} 348}
289 349
290/// Look up the method with the given name, returning the actual autoderefed 350/// Look up the method with the given name, returning the actual autoderefed
@@ -453,7 +513,8 @@ fn iterate_method_candidates_with_autoref(
453 } 513 }
454 let refed = Canonical { 514 let refed = Canonical {
455 binders: deref_chain[0].binders.clone(), 515 binders: deref_chain[0].binders.clone(),
456 value: TyKind::Ref(Mutability::Not, deref_chain[0].value.clone()).intern(&Interner), 516 value: TyKind::Ref(Mutability::Not, static_lifetime(), deref_chain[0].value.clone())
517 .intern(&Interner),
457 }; 518 };
458 if iterate_method_candidates_by_receiver( 519 if iterate_method_candidates_by_receiver(
459 &refed, 520 &refed,
@@ -470,7 +531,8 @@ fn iterate_method_candidates_with_autoref(
470 } 531 }
471 let ref_muted = Canonical { 532 let ref_muted = Canonical {
472 binders: deref_chain[0].binders.clone(), 533 binders: deref_chain[0].binders.clone(),
473 value: TyKind::Ref(Mutability::Mut, deref_chain[0].value.clone()).intern(&Interner), 534 value: TyKind::Ref(Mutability::Mut, static_lifetime(), deref_chain[0].value.clone())
535 .intern(&Interner),
474 }; 536 };
475 if iterate_method_candidates_by_receiver( 537 if iterate_method_candidates_by_receiver(
476 &ref_muted, 538 &ref_muted,
@@ -592,6 +654,7 @@ fn iterate_trait_method_candidates(
592 } 654 }
593 } 655 }
594 known_implemented = true; 656 known_implemented = true;
657 // FIXME: we shouldn't be ignoring the binders here
595 if callback(&self_ty.value, *item) { 658 if callback(&self_ty.value, *item) {
596 return true; 659 return true;
597 } 660 }
@@ -609,7 +672,7 @@ fn iterate_inherent_methods(
609 visible_from_module: Option<ModuleId>, 672 visible_from_module: Option<ModuleId>,
610 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool, 673 callback: &mut dyn FnMut(&Ty, AssocItemId) -> bool,
611) -> bool { 674) -> bool {
612 let def_crates = match self_ty.value.def_crates(db, krate) { 675 let def_crates = match def_crates(db, &self_ty.value, krate) {
613 Some(k) => k, 676 Some(k) => k,
614 None => return false, 677 None => return false,
615 }; 678 };
@@ -709,8 +772,9 @@ pub(crate) fn inherent_impl_substs(
709) -> Option<Substitution> { 772) -> Option<Substitution> {
710 // we create a var for each type parameter of the impl; we need to keep in 773 // we create a var for each type parameter of the impl; we need to keep in
711 // mind here that `self_ty` might have vars of its own 774 // mind here that `self_ty` might have vars of its own
775 let self_ty_vars = self_ty.binders.len(&Interner);
712 let vars = TyBuilder::subst_for_def(db, impl_id) 776 let vars = TyBuilder::subst_for_def(db, impl_id)
713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) 777 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty_vars)
714 .build(); 778 .build();
715 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars); 779 let self_ty_with_vars = db.impl_self_ty(impl_id).substitute(&Interner, &vars);
716 let mut kinds = self_ty.binders.interned().to_vec(); 780 let mut kinds = self_ty.binders.interned().to_vec();
@@ -725,33 +789,27 @@ pub(crate) fn inherent_impl_substs(
725 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 789 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
726 value: (self_ty_with_vars, self_ty.value.clone()), 790 value: (self_ty_with_vars, self_ty.value.clone()),
727 }; 791 };
728 let substs = super::infer::unify(&tys); 792 let substs = super::infer::unify(&tys)?;
729 // We only want the substs for the vars we added, not the ones from self_ty. 793 // We only want the substs for the vars we added, not the ones from self_ty.
730 // Also, if any of the vars we added are still in there, we replace them by 794 // Also, if any of the vars we added are still in there, we replace them by
731 // Unknown. I think this can only really happen if self_ty contained 795 // Unknown. I think this can only really happen if self_ty contained
732 // Unknown, and in that case we want the result to contain Unknown in those 796 // Unknown, and in that case we want the result to contain Unknown in those
733 // places again. 797 // places again.
734 substs 798 let suffix =
735 .map(|s| fallback_bound_vars(s.suffix(vars.len(&Interner)), self_ty.binders.len(&Interner))) 799 Substitution::from_iter(&Interner, substs.iter(&Interner).cloned().skip(self_ty_vars));
800 Some(fallback_bound_vars(suffix, self_ty_vars))
736} 801}
737 802
738/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past 803/// This replaces any 'free' Bound vars in `s` (i.e. those with indices past
739/// num_vars_to_keep) by `TyKind::Unknown`. 804/// num_vars_to_keep) by `TyKind::Unknown`.
740fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution { 805fn fallback_bound_vars(s: Substitution, num_vars_to_keep: usize) -> Substitution {
741 s.fold_binders( 806 crate::fold_free_vars(s, |bound, binders| {
742 &mut |ty, binders| { 807 if bound.index >= num_vars_to_keep && bound.debruijn == DebruijnIndex::INNERMOST {
743 if let TyKind::BoundVar(bound) = ty.kind(&Interner) { 808 TyKind::Error.intern(&Interner)
744 if bound.index >= num_vars_to_keep && bound.debruijn >= binders { 809 } else {
745 TyKind::Error.intern(&Interner) 810 bound.shifted_in_from(binders).to_ty(&Interner)
746 } else { 811 }
747 ty 812 })
748 }
749 } else {
750 ty
751 }
752 },
753 DebruijnIndex::INNERMOST,
754 )
755} 813}
756 814
757fn transform_receiver_ty( 815fn transform_receiver_ty(
@@ -826,7 +884,7 @@ fn generic_implements_goal(
826 let obligation = trait_ref.cast(&Interner); 884 let obligation = trait_ref.cast(&Interner);
827 Canonical { 885 Canonical {
828 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 886 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
829 value: InEnvironment::new(env.env.clone(), obligation), 887 value: InEnvironment::new(&env.env, obligation),
830 } 888 }
831} 889}
832 890
@@ -837,7 +895,9 @@ fn autoderef_method_receiver(
837) -> Vec<Canonical<Ty>> { 895) -> Vec<Canonical<Ty>> {
838 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 896 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
839 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 897 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
840 if let Some(TyKind::Array(parameters)) = deref_chain.last().map(|ty| ty.value.kind(&Interner)) { 898 if let Some(TyKind::Array(parameters, _)) =
899 deref_chain.last().map(|ty| ty.value.kind(&Interner))
900 {
841 let kinds = deref_chain.last().unwrap().binders.clone(); 901 let kinds = deref_chain.last().unwrap().binders.clone();
842 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); 902 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
843 deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) 903 deref_chain.push(Canonical { value: unsized_ty, binders: kinds })
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 0491c5cb4..0222de2bc 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -9,21 +9,55 @@ pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => TyBuilder::unit(), 10 BinaryOp::Assignment { .. } => TyBuilder::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 match lhs_ty.kind(&Interner) { 12 // all integer combinations are valid here
13 if matches!(
14 lhs_ty.kind(&Interner),
13 TyKind::Scalar(Scalar::Int(_)) 15 TyKind::Scalar(Scalar::Int(_))
14 | TyKind::Scalar(Scalar::Uint(_)) 16 | TyKind::Scalar(Scalar::Uint(_))
15 | TyKind::Scalar(Scalar::Float(_)) => lhs_ty, 17 | TyKind::InferenceVar(_, TyVariableKind::Integer)
16 TyKind::InferenceVar(_, TyVariableKind::Integer) 18 ) && matches!(
17 | TyKind::InferenceVar(_, TyVariableKind::Float) => lhs_ty, 19 rhs_ty.kind(&Interner),
18 _ => TyKind::Error.intern(&Interner), 20 TyKind::Scalar(Scalar::Int(_))
21 | TyKind::Scalar(Scalar::Uint(_))
22 | TyKind::InferenceVar(_, TyVariableKind::Integer)
23 ) {
24 lhs_ty
25 } else {
26 TyKind::Error.intern(&Interner)
19 } 27 }
20 } 28 }
21 BinaryOp::ArithOp(_) => match rhs_ty.kind(&Interner) { 29 BinaryOp::ArithOp(_) => match (lhs_ty.kind(&Interner), rhs_ty.kind(&Interner)) {
22 TyKind::Scalar(Scalar::Int(_)) 30 // (int, int) | (uint, uint) | (float, float)
23 | TyKind::Scalar(Scalar::Uint(_)) 31 (TyKind::Scalar(Scalar::Int(_)), TyKind::Scalar(Scalar::Int(_)))
24 | TyKind::Scalar(Scalar::Float(_)) => rhs_ty, 32 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::Scalar(Scalar::Uint(_)))
25 TyKind::InferenceVar(_, TyVariableKind::Integer) 33 | (TyKind::Scalar(Scalar::Float(_)), TyKind::Scalar(Scalar::Float(_))) => rhs_ty,
26 | TyKind::InferenceVar(_, TyVariableKind::Float) => rhs_ty, 34 // ({int}, int) | ({int}, uint)
35 (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Int(_)))
36 | (TyKind::InferenceVar(_, TyVariableKind::Integer), TyKind::Scalar(Scalar::Uint(_))) => {
37 rhs_ty
38 }
39 // (int, {int}) | (uint, {int})
40 (TyKind::Scalar(Scalar::Int(_)), TyKind::InferenceVar(_, TyVariableKind::Integer))
41 | (TyKind::Scalar(Scalar::Uint(_)), TyKind::InferenceVar(_, TyVariableKind::Integer)) => {
42 lhs_ty
43 }
44 // ({float} | float)
45 (TyKind::InferenceVar(_, TyVariableKind::Float), TyKind::Scalar(Scalar::Float(_))) => {
46 rhs_ty
47 }
48 // (float, {float})
49 (TyKind::Scalar(Scalar::Float(_)), TyKind::InferenceVar(_, TyVariableKind::Float)) => {
50 lhs_ty
51 }
52 // ({int}, {int}) | ({float}, {float})
53 (
54 TyKind::InferenceVar(_, TyVariableKind::Integer),
55 TyKind::InferenceVar(_, TyVariableKind::Integer),
56 )
57 | (
58 TyKind::InferenceVar(_, TyVariableKind::Float),
59 TyKind::InferenceVar(_, TyVariableKind::Float),
60 ) => rhs_ty,
27 _ => TyKind::Error.intern(&Interner), 61 _ => TyKind::Error.intern(&Interner),
28 }, 62 },
29 } 63 }
diff --git a/crates/hir_ty/src/primitive.rs b/crates/hir_ty/src/primitive.rs
index 2449addfb..d7f48c69a 100644
--- a/crates/hir_ty/src/primitive.rs
+++ b/crates/hir_ty/src/primitive.rs
@@ -1,7 +1,4 @@
1//! Defines primitive types, which have a couple of peculiarities: 1//! A few helper functions for dealing with primitives.
2//!
3//! * during type inference, they can be uncertain (ie, `let x = 92;`)
4//! * they don't belong to any particular crate.
5 2
6pub use chalk_ir::{FloatTy, IntTy, UintTy}; 3pub use chalk_ir::{FloatTy, IntTy, UintTy};
7pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}; 4pub use hir_def::builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint};
diff --git a/crates/hir_ty/src/tests/method_resolution.rs b/crates/hir_ty/src/tests/method_resolution.rs
index 61f18b0d2..4b2c82b41 100644
--- a/crates/hir_ty/src/tests/method_resolution.rs
+++ b/crates/hir_ty/src/tests/method_resolution.rs
@@ -1292,3 +1292,25 @@ mod b {
1292 "#]], 1292 "#]],
1293 ) 1293 )
1294} 1294}
1295
1296#[test]
1297fn impl_in_unnamed_const() {
1298 check_types(
1299 r#"
1300struct S;
1301
1302trait Tr {
1303 fn method(&self) -> u16;
1304}
1305
1306const _: () = {
1307 impl Tr for S {}
1308};
1309
1310fn f() {
1311 S.method();
1312 //^^^^^^^^^^ u16
1313}
1314 "#,
1315 );
1316}
diff --git a/crates/hir_ty/src/tests/regression.rs b/crates/hir_ty/src/tests/regression.rs
index b69f86050..9cd9f473d 100644
--- a/crates/hir_ty/src/tests/regression.rs
+++ b/crates/hir_ty/src/tests/regression.rs
@@ -974,3 +974,41 @@ fn param_overrides_fn() {
974 "#, 974 "#,
975 ) 975 )
976} 976}
977
978#[test]
979fn lifetime_from_chalk_during_deref() {
980 check_types(
981 r#"
982 #[lang = "deref"]
983 pub trait Deref {
984 type Target;
985 }
986
987 struct Box<T: ?Sized> {}
988 impl<T> Deref for Box<T> {
989 type Target = T;
990
991 fn deref(&self) -> &Self::Target {
992 loop {}
993 }
994 }
995
996 trait Iterator {
997 type Item;
998 }
999
1000 pub struct Iter<'a, T: 'a> {
1001 inner: Box<dyn IterTrait<'a, T, Item = &'a T> + 'a>,
1002 }
1003
1004 trait IterTrait<'a, T: 'a>: Iterator<Item = &'a T> {
1005 fn clone_box(&self);
1006 }
1007
1008 fn clone_iter<T>(s: Iter<T>) {
1009 s.inner.clone_box();
1010 //^^^^^^^^^^^^^^^^^^^ ()
1011 }
1012 "#,
1013 )
1014}
diff --git a/crates/hir_ty/src/tests/simple.rs b/crates/hir_ty/src/tests/simple.rs
index 361cd6302..84c5c05fd 100644
--- a/crates/hir_ty/src/tests/simple.rs
+++ b/crates/hir_ty/src/tests/simple.rs
@@ -2564,3 +2564,36 @@ fn f() {
2564 "#, 2564 "#,
2565 ) 2565 )
2566} 2566}
2567
2568#[test]
2569fn infer_type_alias_variant() {
2570 check_infer(
2571 r#"
2572type Qux = Foo;
2573enum Foo {
2574 Bar(i32),
2575 Baz { baz: f32 }
2576}
2577
2578fn f() {
2579 match Foo::Bar(3) {
2580 Qux::Bar(bar) => (),
2581 Qux::Baz { baz } => (),
2582 }
2583}
2584 "#,
2585 expect![[r#"
2586 72..166 '{ ... } }': ()
2587 78..164 'match ... }': ()
2588 84..92 'Foo::Bar': Bar(i32) -> Foo
2589 84..95 'Foo::Bar(3)': Foo
2590 93..94 '3': i32
2591 106..119 'Qux::Bar(bar)': Foo
2592 115..118 'bar': i32
2593 123..125 '()': ()
2594 135..151 'Qux::B... baz }': Foo
2595 146..149 'baz': f32
2596 155..157 '()': ()
2597 "#]],
2598 )
2599}
diff --git a/crates/hir_ty/src/tests/traits.rs b/crates/hir_ty/src/tests/traits.rs
index 65b71fdfa..ffc7c8ef4 100644
--- a/crates/hir_ty/src/tests/traits.rs
+++ b/crates/hir_ty/src/tests/traits.rs
@@ -263,15 +263,14 @@ mod ops {
263fn infer_from_bound_1() { 263fn infer_from_bound_1() {
264 check_infer( 264 check_infer(
265 r#" 265 r#"
266 trait Trait<T> {} 266trait Trait<T> {}
267 struct S<T>(T); 267struct S<T>(T);
268 impl<U> Trait<U> for S<U> {} 268impl<U> Trait<U> for S<U> {}
269 fn foo<T: Trait<u32>>(t: T) {} 269fn foo<T: Trait<u32>>(t: T) {}
270 fn test() { 270fn test() {
271 let s = S(unknown); 271 let s = S(unknown);
272 foo(s); 272 foo(s);
273 } 273}"#,
274 "#,
275 expect![[r#" 274 expect![[r#"
276 85..86 't': T 275 85..86 't': T
277 91..93 '{}': () 276 91..93 '{}': ()
@@ -291,15 +290,14 @@ fn infer_from_bound_1() {
291fn infer_from_bound_2() { 290fn infer_from_bound_2() {
292 check_infer( 291 check_infer(
293 r#" 292 r#"
294 trait Trait<T> {} 293trait Trait<T> {}
295 struct S<T>(T); 294struct S<T>(T);
296 impl<U> Trait<U> for S<U> {} 295impl<U> Trait<U> for S<U> {}
297 fn foo<U, T: Trait<U>>(t: T) -> U {} 296fn foo<U, T: Trait<U>>(t: T) -> U {}
298 fn test() { 297fn test() {
299 let s = S(unknown); 298 let s = S(unknown);
300 let x: u32 = foo(s); 299 let x: u32 = foo(s);
301 } 300}"#,
302 "#,
303 expect![[r#" 301 expect![[r#"
304 86..87 't': T 302 86..87 't': T
305 97..99 '{}': () 303 97..99 '{}': ()
@@ -321,13 +319,12 @@ fn trait_default_method_self_bound_implements_trait() {
321 cov_mark::check!(trait_self_implements_self); 319 cov_mark::check!(trait_self_implements_self);
322 check_infer( 320 check_infer(
323 r#" 321 r#"
324 trait Trait { 322trait Trait {
325 fn foo(&self) -> i64; 323 fn foo(&self) -> i64;
326 fn bar(&self) -> { 324 fn bar(&self) -> {
327 let x = self.foo(); 325 let x = self.foo();
328 } 326 }
329 } 327}"#,
330 "#,
331 expect![[r#" 328 expect![[r#"
332 26..30 'self': &Self 329 26..30 'self': &Self
333 52..56 'self': &Self 330 52..56 'self': &Self
@@ -343,15 +340,14 @@ fn trait_default_method_self_bound_implements_trait() {
343fn trait_default_method_self_bound_implements_super_trait() { 340fn trait_default_method_self_bound_implements_super_trait() {
344 check_infer( 341 check_infer(
345 r#" 342 r#"
346 trait SuperTrait { 343trait SuperTrait {
347 fn foo(&self) -> i64; 344 fn foo(&self) -> i64;
348 } 345}
349 trait Trait: SuperTrait { 346trait Trait: SuperTrait {
350 fn bar(&self) -> { 347 fn bar(&self) -> {
351 let x = self.foo(); 348 let x = self.foo();
352 } 349 }
353 } 350}"#,
354 "#,
355 expect![[r#" 351 expect![[r#"
356 31..35 'self': &Self 352 31..35 'self': &Self
357 85..89 'self': &Self 353 85..89 'self': &Self
@@ -367,18 +363,17 @@ fn trait_default_method_self_bound_implements_super_trait() {
367fn infer_project_associated_type() { 363fn infer_project_associated_type() {
368 check_infer( 364 check_infer(
369 r#" 365 r#"
370 trait Iterable { 366trait Iterable {
371 type Item; 367 type Item;
372 } 368}
373 struct S; 369struct S;
374 impl Iterable for S { type Item = u32; } 370impl Iterable for S { type Item = u32; }
375 fn test<T: Iterable>() { 371fn test<T: Iterable>() {
376 let x: <S as Iterable>::Item = 1; 372 let x: <S as Iterable>::Item = 1;
377 let y: <T as Iterable>::Item = no_matter; 373 let y: <T as Iterable>::Item = no_matter;
378 let z: T::Item = no_matter; 374 let z: T::Item = no_matter;
379 let a: <T>::Item = no_matter; 375 let a: <T>::Item = no_matter;
380 } 376}"#,
381 "#,
382 expect![[r#" 377 expect![[r#"
383 108..261 '{ ...ter; }': () 378 108..261 '{ ...ter; }': ()
384 118..119 'x': u32 379 118..119 'x': u32
@@ -397,20 +392,19 @@ fn infer_project_associated_type() {
397fn infer_return_associated_type() { 392fn infer_return_associated_type() {
398 check_infer( 393 check_infer(
399 r#" 394 r#"
400 trait Iterable { 395trait Iterable {
401 type Item; 396 type Item;
402 } 397}
403 struct S; 398struct S;
404 impl Iterable for S { type Item = u32; } 399impl Iterable for S { type Item = u32; }
405 fn foo1<T: Iterable>(t: T) -> T::Item {} 400fn foo1<T: Iterable>(t: T) -> T::Item {}
406 fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {} 401fn foo2<T: Iterable>(t: T) -> <T as Iterable>::Item {}
407 fn foo3<T: Iterable>(t: T) -> <T>::Item {} 402fn foo3<T: Iterable>(t: T) -> <T>::Item {}
408 fn test() { 403fn test() {
409 let x = foo1(S); 404 let x = foo1(S);
410 let y = foo2(S); 405 let y = foo2(S);
411 let z = foo3(S); 406 let z = foo3(S);
412 } 407}"#,
413 "#,
414 expect![[r#" 408 expect![[r#"
415 106..107 't': T 409 106..107 't': T
416 123..125 '{}': () 410 123..125 '{}': ()
@@ -439,13 +433,12 @@ fn infer_return_associated_type() {
439fn infer_associated_type_bound() { 433fn infer_associated_type_bound() {
440 check_infer( 434 check_infer(
441 r#" 435 r#"
442 trait Iterable { 436trait Iterable {
443 type Item; 437 type Item;
444 } 438}
445 fn test<T: Iterable<Item=u32>>() { 439fn test<T: Iterable<Item=u32>>() {
446 let y: T::Item = unknown; 440 let y: T::Item = unknown;
447 } 441}"#,
448 "#,
449 expect![[r#" 442 expect![[r#"
450 67..100 '{ ...own; }': () 443 67..100 '{ ...own; }': ()
451 77..78 'y': u32 444 77..78 'y': u32
@@ -458,9 +451,8 @@ fn infer_associated_type_bound() {
458fn infer_const_body() { 451fn infer_const_body() {
459 check_infer( 452 check_infer(
460 r#" 453 r#"
461 const A: u32 = 1 + 1; 454const A: u32 = 1 + 1;
462 static B: u64 = { let x = 1; x }; 455static B: u64 = { let x = 1; x };"#,
463 "#,
464 expect![[r#" 456 expect![[r#"
465 15..16 '1': u32 457 15..16 '1': u32
466 15..20 '1 + 1': u32 458 15..20 '1 + 1': u32
@@ -477,13 +469,12 @@ fn infer_const_body() {
477fn tuple_struct_fields() { 469fn tuple_struct_fields() {
478 check_infer( 470 check_infer(
479 r#" 471 r#"
480 struct S(i32, u64); 472struct S(i32, u64);
481 fn test() -> u64 { 473fn test() -> u64 {
482 let a = S(4, 6); 474 let a = S(4, 6);
483 let b = a.0; 475 let b = a.0;
484 a.1 476 a.1
485 } 477}"#,
486 "#,
487 expect![[r#" 478 expect![[r#"
488 37..86 '{ ... a.1 }': u64 479 37..86 '{ ... a.1 }': u64
489 47..48 'a': S 480 47..48 'a': S
@@ -504,13 +495,12 @@ fn tuple_struct_fields() {
504fn tuple_struct_with_fn() { 495fn tuple_struct_with_fn() {
505 check_infer( 496 check_infer(
506 r#" 497 r#"
507 struct S(fn(u32) -> u64); 498struct S(fn(u32) -> u64);
508 fn test() -> u64 { 499fn test() -> u64 {
509 let a = S(|i| 2*i); 500 let a = S(|i| 2*i);
510 let b = a.0(4); 501 let b = a.0(4);
511 a.0(2) 502 a.0(2)
512 } 503}"#,
513 "#,
514 expect![[r#" 504 expect![[r#"
515 43..101 '{ ...0(2) }': u64 505 43..101 '{ ...0(2) }': u64
516 53..54 'a': S 506 53..54 'a': S
@@ -949,27 +939,26 @@ fn test<T: ApplyL>(t: T) {
949fn argument_impl_trait() { 939fn argument_impl_trait() {
950 check_infer_with_mismatches( 940 check_infer_with_mismatches(
951 r#" 941 r#"
952 trait Trait<T> { 942trait Trait<T> {
953 fn foo(&self) -> T; 943 fn foo(&self) -> T;
954 fn foo2(&self) -> i64; 944 fn foo2(&self) -> i64;
955 } 945}
956 fn bar(x: impl Trait<u16>) {} 946fn bar(x: impl Trait<u16>) {}
957 struct S<T>(T); 947struct S<T>(T);
958 impl<T> Trait<T> for S<T> {} 948impl<T> Trait<T> for S<T> {}
959 949
960 fn test(x: impl Trait<u64>, y: &impl Trait<u32>) { 950fn test(x: impl Trait<u64>, y: &impl Trait<u32>) {
961 x; 951 x;
962 y; 952 y;
963 let z = S(1); 953 let z = S(1);
964 bar(z); 954 bar(z);
965 x.foo(); 955 x.foo();
966 y.foo(); 956 y.foo();
967 z.foo(); 957 z.foo();
968 x.foo2(); 958 x.foo2();
969 y.foo2(); 959 y.foo2();
970 z.foo2(); 960 z.foo2();
971 } 961}"#,
972 "#,
973 expect![[r#" 962 expect![[r#"
974 29..33 'self': &Self 963 29..33 'self': &Self
975 54..58 'self': &Self 964 54..58 'self': &Self
@@ -1007,30 +996,29 @@ fn argument_impl_trait() {
1007fn argument_impl_trait_type_args_1() { 996fn argument_impl_trait_type_args_1() {
1008 check_infer_with_mismatches( 997 check_infer_with_mismatches(
1009 r#" 998 r#"
1010 trait Trait {} 999trait Trait {}
1011 trait Foo { 1000trait Foo {
1012 // this function has an implicit Self param, an explicit type param, 1001 // this function has an implicit Self param, an explicit type param,
1013 // and an implicit impl Trait param! 1002 // and an implicit impl Trait param!
1014 fn bar<T>(x: impl Trait) -> T { loop {} } 1003 fn bar<T>(x: impl Trait) -> T { loop {} }
1015 } 1004}
1016 fn foo<T>(x: impl Trait) -> T { loop {} } 1005fn foo<T>(x: impl Trait) -> T { loop {} }
1017 struct S; 1006struct S;
1018 impl Trait for S {} 1007impl Trait for S {}
1019 struct F; 1008struct F;
1020 impl Foo for F {} 1009impl Foo for F {}
1021 1010
1022 fn test() { 1011fn test() {
1023 Foo::bar(S); 1012 Foo::bar(S);
1024 <F as Foo>::bar(S); 1013 <F as Foo>::bar(S);
1025 F::bar(S); 1014 F::bar(S);
1026 Foo::bar::<u32>(S); 1015 Foo::bar::<u32>(S);
1027 <F as Foo>::bar::<u32>(S); 1016 <F as Foo>::bar::<u32>(S);
1028 1017
1029 foo(S); 1018 foo(S);
1030 foo::<u32>(S); 1019 foo::<u32>(S);
1031 foo::<u32, i32>(S); // we should ignore the extraneous i32 1020 foo::<u32, i32>(S); // we should ignore the extraneous i32
1032 } 1021}"#,
1033 "#,
1034 expect![[r#" 1022 expect![[r#"
1035 155..156 'x': impl Trait 1023 155..156 'x': impl Trait
1036 175..186 '{ loop {} }': T 1024 175..186 '{ loop {} }': T
@@ -1073,21 +1061,20 @@ fn argument_impl_trait_type_args_1() {
1073fn argument_impl_trait_type_args_2() { 1061fn argument_impl_trait_type_args_2() {
1074 check_infer_with_mismatches( 1062 check_infer_with_mismatches(
1075 r#" 1063 r#"
1076 trait Trait {} 1064trait Trait {}
1077 struct S; 1065struct S;
1078 impl Trait for S {} 1066impl Trait for S {}
1079 struct F<T>; 1067struct F<T>;
1080 impl<T> F<T> { 1068impl<T> F<T> {
1081 fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} } 1069 fn foo<U>(self, x: impl Trait) -> (T, U) { loop {} }
1082 } 1070}
1083 1071
1084 fn test() { 1072fn test() {
1085 F.foo(S); 1073 F.foo(S);
1086 F::<u32>.foo(S); 1074 F::<u32>.foo(S);
1087 F::<u32>.foo::<i32>(S); 1075 F::<u32>.foo::<i32>(S);
1088 F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored 1076 F::<u32>.foo::<i32, u32>(S); // extraneous argument should be ignored
1089 } 1077}"#,
1090 "#,
1091 expect![[r#" 1078 expect![[r#"
1092 87..91 'self': F<T> 1079 87..91 'self': F<T>
1093 93..94 'x': impl Trait 1080 93..94 'x': impl Trait
@@ -1115,15 +1102,14 @@ fn argument_impl_trait_type_args_2() {
1115fn argument_impl_trait_to_fn_pointer() { 1102fn argument_impl_trait_to_fn_pointer() {
1116 check_infer_with_mismatches( 1103 check_infer_with_mismatches(
1117 r#" 1104 r#"
1118 trait Trait {} 1105trait Trait {}
1119 fn foo(x: impl Trait) { loop {} } 1106fn foo(x: impl Trait) { loop {} }
1120 struct S; 1107struct S;
1121 impl Trait for S {} 1108impl Trait for S {}
1122 1109
1123 fn test() { 1110fn test() {
1124 let f: fn(S) -> () = foo; 1111 let f: fn(S) -> () = foo;
1125 } 1112}"#,
1126 "#,
1127 expect![[r#" 1113 expect![[r#"
1128 22..23 'x': impl Trait 1114 22..23 'x': impl Trait
1129 37..48 '{ loop {} }': () 1115 37..48 '{ loop {} }': ()
@@ -1140,24 +1126,23 @@ fn argument_impl_trait_to_fn_pointer() {
1140fn impl_trait() { 1126fn impl_trait() {
1141 check_infer( 1127 check_infer(
1142 r#" 1128 r#"
1143 trait Trait<T> { 1129trait Trait<T> {
1144 fn foo(&self) -> T; 1130 fn foo(&self) -> T;
1145 fn foo2(&self) -> i64; 1131 fn foo2(&self) -> i64;
1146 } 1132}
1147 fn bar() -> impl Trait<u64> {} 1133fn bar() -> impl Trait<u64> {}
1148 1134
1149 fn test(x: impl Trait<u64>, y: &impl Trait<u64>) { 1135fn test(x: impl Trait<u64>, y: &impl Trait<u64>) {
1150 x; 1136 x;
1151 y; 1137 y;
1152 let z = bar(); 1138 let z = bar();
1153 x.foo(); 1139 x.foo();
1154 y.foo(); 1140 y.foo();
1155 z.foo(); 1141 z.foo();
1156 x.foo2(); 1142 x.foo2();
1157 y.foo2(); 1143 y.foo2();
1158 z.foo2(); 1144 z.foo2();
1159 } 1145}"#,
1160 "#,
1161 expect![[r#" 1146 expect![[r#"
1162 29..33 'self': &Self 1147 29..33 'self': &Self
1163 54..58 'self': &Self 1148 54..58 'self': &Self
@@ -1191,16 +1176,15 @@ fn simple_return_pos_impl_trait() {
1191 cov_mark::check!(lower_rpit); 1176 cov_mark::check!(lower_rpit);
1192 check_infer( 1177 check_infer(
1193 r#" 1178 r#"
1194 trait Trait<T> { 1179trait Trait<T> {
1195 fn foo(&self) -> T; 1180 fn foo(&self) -> T;
1196 } 1181}
1197 fn bar() -> impl Trait<u64> { loop {} } 1182fn bar() -> impl Trait<u64> { loop {} }
1198 1183
1199 fn test() { 1184fn test() {
1200 let a = bar(); 1185 let a = bar();
1201 a.foo(); 1186 a.foo();
1202 } 1187}"#,
1203 "#,
1204 expect![[r#" 1188 expect![[r#"
1205 29..33 'self': &Self 1189 29..33 'self': &Self
1206 71..82 '{ loop {} }': ! 1190 71..82 '{ loop {} }': !
@@ -1220,25 +1204,24 @@ fn simple_return_pos_impl_trait() {
1220fn more_return_pos_impl_trait() { 1204fn more_return_pos_impl_trait() {
1221 check_infer( 1205 check_infer(
1222 r#" 1206 r#"
1223 trait Iterator { 1207trait Iterator {
1224 type Item; 1208 type Item;
1225 fn next(&mut self) -> Self::Item; 1209 fn next(&mut self) -> Self::Item;
1226 } 1210}
1227 trait Trait<T> { 1211trait Trait<T> {
1228 fn foo(&self) -> T; 1212 fn foo(&self) -> T;
1229 } 1213}
1230 fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} } 1214fn bar() -> (impl Iterator<Item = impl Trait<u32>>, impl Trait<u64>) { loop {} }
1231 fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} } 1215fn baz<T>(t: T) -> (impl Iterator<Item = impl Trait<T>>, impl Trait<T>) { loop {} }
1232 1216
1233 fn test() { 1217fn test() {
1234 let (a, b) = bar(); 1218 let (a, b) = bar();
1235 a.next().foo(); 1219 a.next().foo();
1236 b.foo(); 1220 b.foo();
1237 let (c, d) = baz(1u128); 1221 let (c, d) = baz(1u128);
1238 c.next().foo(); 1222 c.next().foo();
1239 d.foo(); 1223 d.foo();
1240 } 1224}"#,
1241 "#,
1242 expect![[r#" 1225 expect![[r#"
1243 49..53 'self': &mut Self 1226 49..53 'self': &mut Self
1244 101..105 'self': &Self 1227 101..105 'self': &Self
@@ -1279,24 +1262,23 @@ fn more_return_pos_impl_trait() {
1279fn dyn_trait() { 1262fn dyn_trait() {
1280 check_infer( 1263 check_infer(
1281 r#" 1264 r#"
1282 trait Trait<T> { 1265trait Trait<T> {
1283 fn foo(&self) -> T; 1266 fn foo(&self) -> T;
1284 fn foo2(&self) -> i64; 1267 fn foo2(&self) -> i64;
1285 } 1268}
1286 fn bar() -> dyn Trait<u64> {} 1269fn bar() -> dyn Trait<u64> {}
1287 1270
1288 fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) { 1271fn test(x: dyn Trait<u64>, y: &dyn Trait<u64>) {
1289 x; 1272 x;
1290 y; 1273 y;
1291 let z = bar(); 1274 let z = bar();
1292 x.foo(); 1275 x.foo();
1293 y.foo(); 1276 y.foo();
1294 z.foo(); 1277 z.foo();
1295 x.foo2(); 1278 x.foo2();
1296 y.foo2(); 1279 y.foo2();
1297 z.foo2(); 1280 z.foo2();
1298 } 1281}"#,
1299 "#,
1300 expect![[r#" 1282 expect![[r#"
1301 29..33 'self': &Self 1283 29..33 'self': &Self
1302 54..58 'self': &Self 1284 54..58 'self': &Self
@@ -1329,22 +1311,21 @@ fn dyn_trait() {
1329fn dyn_trait_in_impl() { 1311fn dyn_trait_in_impl() {
1330 check_infer( 1312 check_infer(
1331 r#" 1313 r#"
1332 trait Trait<T, U> { 1314trait Trait<T, U> {
1333 fn foo(&self) -> (T, U); 1315 fn foo(&self) -> (T, U);
1334 } 1316}
1335 struct S<T, U> {} 1317struct S<T, U> {}
1336 impl<T, U> S<T, U> { 1318impl<T, U> S<T, U> {
1337 fn bar(&self) -> &dyn Trait<T, U> { loop {} } 1319 fn bar(&self) -> &dyn Trait<T, U> { loop {} }
1338 } 1320}
1339 trait Trait2<T, U> { 1321trait Trait2<T, U> {
1340 fn baz(&self) -> (T, U); 1322 fn baz(&self) -> (T, U);
1341 } 1323}
1342 impl<T, U> Trait2<T, U> for dyn Trait<T, U> { } 1324impl<T, U> Trait2<T, U> for dyn Trait<T, U> { }
1343 1325
1344 fn test(s: S<u32, i32>) { 1326fn test(s: S<u32, i32>) {
1345 s.bar().baz(); 1327 s.bar().baz();
1346 } 1328}"#,
1347 "#,
1348 expect![[r#" 1329 expect![[r#"
1349 32..36 'self': &Self 1330 32..36 'self': &Self
1350 102..106 'self': &S<T, U> 1331 102..106 'self': &S<T, U>
@@ -1365,20 +1346,19 @@ fn dyn_trait_in_impl() {
1365fn dyn_trait_bare() { 1346fn dyn_trait_bare() {
1366 check_infer( 1347 check_infer(
1367 r#" 1348 r#"
1368 trait Trait { 1349trait Trait {
1369 fn foo(&self) -> u64; 1350 fn foo(&self) -> u64;
1370 } 1351}
1371 fn bar() -> Trait {} 1352fn bar() -> Trait {}
1372 1353
1373 fn test(x: Trait, y: &Trait) -> u64 { 1354fn test(x: Trait, y: &Trait) -> u64 {
1374 x; 1355 x;
1375 y; 1356 y;
1376 let z = bar(); 1357 let z = bar();
1377 x.foo(); 1358 x.foo();
1378 y.foo(); 1359 y.foo();
1379 z.foo(); 1360 z.foo();
1380 } 1361}"#,
1381 "#,
1382 expect![[r#" 1362 expect![[r#"
1383 26..30 'self': &Self 1363 26..30 'self': &Self
1384 60..62 '{}': () 1364 60..62 '{}': ()
@@ -1404,17 +1384,24 @@ fn dyn_trait_bare() {
1404fn weird_bounds() { 1384fn weird_bounds() {
1405 check_infer( 1385 check_infer(
1406 r#" 1386 r#"
1407 trait Trait {} 1387trait Trait {}
1408 fn test(a: impl Trait + 'lifetime, b: impl 'lifetime, c: impl (Trait), d: impl ('lifetime), e: impl ?Sized, f: impl Trait + ?Sized) {} 1388fn test(
1409 "#, 1389 a: impl Trait + 'lifetime,
1390 b: impl 'lifetime,
1391 c: impl (Trait),
1392 d: impl ('lifetime),
1393 e: impl ?Sized,
1394 f: impl Trait + ?Sized
1395) {}
1396"#,
1410 expect![[r#" 1397 expect![[r#"
1411 23..24 'a': impl Trait 1398 28..29 'a': impl Trait
1412 50..51 'b': impl 1399 59..60 'b': impl
1413 69..70 'c': impl Trait 1400 82..83 'c': impl Trait
1414 86..87 'd': impl 1401 103..104 'd': impl
1415 107..108 'e': impl 1402 128..129 'e': impl
1416 123..124 'f': impl Trait 1403 148..149 'f': impl Trait
1417 147..149 '{}': () 1404 173..175 '{}': ()
1418 "#]], 1405 "#]],
1419 ); 1406 );
1420} 1407}
@@ -1439,27 +1426,26 @@ fn test(x: (impl Trait + UnknownTrait)) {
1439fn assoc_type_bindings() { 1426fn assoc_type_bindings() {
1440 check_infer( 1427 check_infer(
1441 r#" 1428 r#"
1442 trait Trait { 1429trait Trait {
1443 type Type; 1430 type Type;
1444 } 1431}
1445 1432
1446 fn get<T: Trait>(t: T) -> <T as Trait>::Type {} 1433fn get<T: Trait>(t: T) -> <T as Trait>::Type {}
1447 fn get2<U, T: Trait<Type = U>>(t: T) -> U {} 1434fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
1448 fn set<T: Trait<Type = u64>>(t: T) -> T {t} 1435fn set<T: Trait<Type = u64>>(t: T) -> T {t}
1449 1436
1450 struct S<T>; 1437struct S<T>;
1451 impl<T> Trait for S<T> { type Type = T; } 1438impl<T> Trait for S<T> { type Type = T; }
1452 1439
1453 fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) { 1440fn test<T: Trait<Type = u32>>(x: T, y: impl Trait<Type = i64>) {
1454 get(x); 1441 get(x);
1455 get2(x); 1442 get2(x);
1456 get(y); 1443 get(y);
1457 get2(y); 1444 get2(y);
1458 get(set(S)); 1445 get(set(S));
1459 get2(set(S)); 1446 get2(set(S));
1460 get2(S::<str>); 1447 get2(S::<str>);
1461 } 1448}"#,
1462 "#,
1463 expect![[r#" 1449 expect![[r#"
1464 49..50 't': T 1450 49..50 't': T
1465 77..79 '{}': () 1451 77..79 '{}': ()
@@ -1546,18 +1532,17 @@ mod iter {
1546fn projection_eq_within_chalk() { 1532fn projection_eq_within_chalk() {
1547 check_infer( 1533 check_infer(
1548 r#" 1534 r#"
1549 trait Trait1 { 1535trait Trait1 {
1550 type Type; 1536 type Type;
1551 } 1537}
1552 trait Trait2<T> { 1538trait Trait2<T> {
1553 fn foo(self) -> T; 1539 fn foo(self) -> T;
1554 } 1540}
1555 impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {} 1541impl<T, U> Trait2<T> for U where U: Trait1<Type = T> {}
1556 1542
1557 fn test<T: Trait1<Type = u32>>(x: T) { 1543fn test<T: Trait1<Type = u32>>(x: T) {
1558 x.foo(); 1544 x.foo();
1559 } 1545}"#,
1560 "#,
1561 expect![[r#" 1546 expect![[r#"
1562 61..65 'self': Self 1547 61..65 'self': Self
1563 163..164 'x': T 1548 163..164 'x': T
@@ -1589,19 +1574,18 @@ fn test<T: foo::Trait>(x: T) {
1589fn super_trait_method_resolution() { 1574fn super_trait_method_resolution() {
1590 check_infer( 1575 check_infer(
1591 r#" 1576 r#"
1592 mod foo { 1577mod foo {
1593 trait SuperTrait { 1578 trait SuperTrait {
1594 fn foo(&self) -> u32 {} 1579 fn foo(&self) -> u32 {}
1595 } 1580 }
1596 } 1581}
1597 trait Trait1: foo::SuperTrait {} 1582trait Trait1: foo::SuperTrait {}
1598 trait Trait2 where Self: foo::SuperTrait {} 1583trait Trait2 where Self: foo::SuperTrait {}
1599 1584
1600 fn test<T: Trait1, U: Trait2>(x: T, y: U) { 1585fn test<T: Trait1, U: Trait2>(x: T, y: U) {
1601 x.foo(); 1586 x.foo();
1602 y.foo(); 1587 y.foo();
1603 } 1588}"#,
1604 "#,
1605 expect![[r#" 1589 expect![[r#"
1606 49..53 'self': &Self 1590 49..53 'self': &Self
1607 62..64 '{}': () 1591 62..64 '{}': ()
@@ -1620,17 +1604,16 @@ fn super_trait_method_resolution() {
1620fn super_trait_impl_trait_method_resolution() { 1604fn super_trait_impl_trait_method_resolution() {
1621 check_infer( 1605 check_infer(
1622 r#" 1606 r#"
1623 mod foo { 1607mod foo {
1624 trait SuperTrait { 1608 trait SuperTrait {
1625 fn foo(&self) -> u32 {} 1609 fn foo(&self) -> u32 {}
1626 } 1610 }
1627 } 1611}
1628 trait Trait1: foo::SuperTrait {} 1612trait Trait1: foo::SuperTrait {}
1629 1613
1630 fn test(x: &impl Trait1) { 1614fn test(x: &impl Trait1) {
1631 x.foo(); 1615 x.foo();
1632 } 1616}"#,
1633 "#,
1634 expect![[r#" 1617 expect![[r#"
1635 49..53 'self': &Self 1618 49..53 'self': &Self
1636 62..64 '{}': () 1619 62..64 '{}': ()
@@ -1667,20 +1650,19 @@ fn super_trait_cycle() {
1667fn super_trait_assoc_type_bounds() { 1650fn super_trait_assoc_type_bounds() {
1668 check_infer( 1651 check_infer(
1669 r#" 1652 r#"
1670 trait SuperTrait { type Type; } 1653trait SuperTrait { type Type; }
1671 trait Trait where Self: SuperTrait {} 1654trait Trait where Self: SuperTrait {}
1672 1655
1673 fn get2<U, T: Trait<Type = U>>(t: T) -> U {} 1656fn get2<U, T: Trait<Type = U>>(t: T) -> U {}
1674 fn set<T: Trait<Type = u64>>(t: T) -> T {t} 1657fn set<T: Trait<Type = u64>>(t: T) -> T {t}
1675 1658
1676 struct S<T>; 1659struct S<T>;
1677 impl<T> SuperTrait for S<T> { type Type = T; } 1660impl<T> SuperTrait for S<T> { type Type = T; }
1678 impl<T> Trait for S<T> {} 1661impl<T> Trait for S<T> {}
1679 1662
1680 fn test() { 1663fn test() {
1681 get2(set(S)); 1664 get2(set(S));
1682 } 1665}"#,
1683 "#,
1684 expect![[r#" 1666 expect![[r#"
1685 102..103 't': T 1667 102..103 't': T
1686 113..115 '{}': () 1668 113..115 '{}': ()
@@ -1701,16 +1683,15 @@ fn super_trait_assoc_type_bounds() {
1701fn fn_trait() { 1683fn fn_trait() {
1702 check_infer_with_mismatches( 1684 check_infer_with_mismatches(
1703 r#" 1685 r#"
1704 trait FnOnce<Args> { 1686trait FnOnce<Args> {
1705 type Output; 1687 type Output;
1706 1688
1707 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output; 1689 fn call_once(self, args: Args) -> <Self as FnOnce<Args>>::Output;
1708 } 1690}
1709 1691
1710 fn test<F: FnOnce(u32, u64) -> u128>(f: F) { 1692fn test<F: FnOnce(u32, u64) -> u128>(f: F) {
1711 f.call_once((1, 2)); 1693 f.call_once((1, 2));
1712 } 1694}"#,
1713 "#,
1714 expect![[r#" 1695 expect![[r#"
1715 56..60 'self': Self 1696 56..60 'self': Self
1716 62..66 'args': Args 1697 62..66 'args': Args
@@ -1729,37 +1710,36 @@ fn fn_trait() {
1729fn fn_ptr_and_item() { 1710fn fn_ptr_and_item() {
1730 check_infer_with_mismatches( 1711 check_infer_with_mismatches(
1731 r#" 1712 r#"
1732 #[lang="fn_once"] 1713#[lang="fn_once"]
1733 trait FnOnce<Args> { 1714trait FnOnce<Args> {
1734 type Output; 1715 type Output;
1735 1716
1736 fn call_once(self, args: Args) -> Self::Output; 1717 fn call_once(self, args: Args) -> Self::Output;
1737 } 1718}
1738 1719
1739 trait Foo<T> { 1720trait Foo<T> {
1740 fn foo(&self) -> T; 1721 fn foo(&self) -> T;
1741 } 1722}
1742 1723
1743 struct Bar<T>(T); 1724struct Bar<T>(T);
1744 1725
1745 impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> { 1726impl<A1, R, F: FnOnce(A1) -> R> Foo<(A1, R)> for Bar<F> {
1746 fn foo(&self) -> (A1, R) { loop {} } 1727 fn foo(&self) -> (A1, R) { loop {} }
1747 } 1728}
1748 1729
1749 enum Opt<T> { None, Some(T) } 1730enum Opt<T> { None, Some(T) }
1750 impl<T> Opt<T> { 1731impl<T> Opt<T> {
1751 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} } 1732 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Opt<U> { loop {} }
1752 } 1733}
1753 1734
1754 fn test() { 1735fn test() {
1755 let bar: Bar<fn(u8) -> u32>; 1736 let bar: Bar<fn(u8) -> u32>;
1756 bar.foo(); 1737 bar.foo();
1757 1738
1758 let opt: Opt<u8>; 1739 let opt: Opt<u8>;
1759 let f: fn(u8) -> u32; 1740 let f: fn(u8) -> u32;
1760 opt.map(f); 1741 opt.map(f);
1761 } 1742}"#,
1762 "#,
1763 expect![[r#" 1743 expect![[r#"
1764 74..78 'self': Self 1744 74..78 'self': Self
1765 80..84 'args': Args 1745 80..84 'args': Args
@@ -1790,46 +1770,45 @@ fn fn_ptr_and_item() {
1790fn fn_trait_deref_with_ty_default() { 1770fn fn_trait_deref_with_ty_default() {
1791 check_infer( 1771 check_infer(
1792 r#" 1772 r#"
1793 #[lang = "deref"] 1773#[lang = "deref"]
1794 trait Deref { 1774trait Deref {
1795 type Target; 1775 type Target;
1796 1776
1797 fn deref(&self) -> &Self::Target; 1777 fn deref(&self) -> &Self::Target;
1798 } 1778}
1799 1779
1800 #[lang="fn_once"] 1780#[lang="fn_once"]
1801 trait FnOnce<Args> { 1781trait FnOnce<Args> {
1802 type Output; 1782 type Output;
1803 1783
1804 fn call_once(self, args: Args) -> Self::Output; 1784 fn call_once(self, args: Args) -> Self::Output;
1805 } 1785}
1806 1786
1807 struct Foo; 1787struct Foo;
1808 1788
1809 impl Foo { 1789impl Foo {
1810 fn foo(&self) -> usize {} 1790 fn foo(&self) -> usize {}
1811 } 1791}
1812 1792
1813 struct Lazy<T, F = fn() -> T>(F); 1793struct Lazy<T, F = fn() -> T>(F);
1814 1794
1815 impl<T, F> Lazy<T, F> { 1795impl<T, F> Lazy<T, F> {
1816 pub fn new(f: F) -> Lazy<T, F> {} 1796 pub fn new(f: F) -> Lazy<T, F> {}
1817 } 1797}
1818 1798
1819 impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> { 1799impl<T, F: FnOnce() -> T> Deref for Lazy<T, F> {
1820 type Target = T; 1800 type Target = T;
1821 } 1801}
1822 1802
1823 fn test() { 1803fn test() {
1824 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo); 1804 let lazy1: Lazy<Foo, _> = Lazy::new(|| Foo);
1825 let r1 = lazy1.foo(); 1805 let r1 = lazy1.foo();
1826 1806
1827 fn make_foo_fn() -> Foo {} 1807 fn make_foo_fn() -> Foo {}
1828 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn; 1808 let make_foo_fn_ptr: fn() -> Foo = make_foo_fn;
1829 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr); 1809 let lazy2: Lazy<Foo, _> = Lazy::new(make_foo_fn_ptr);
1830 let r2 = lazy2.foo(); 1810 let r2 = lazy2.foo();
1831 } 1811}"#,
1832 "#,
1833 expect![[r#" 1812 expect![[r#"
1834 64..68 'self': &Self 1813 64..68 'self': &Self
1835 165..169 'self': Self 1814 165..169 'self': Self
@@ -1865,23 +1844,22 @@ fn fn_trait_deref_with_ty_default() {
1865fn closure_1() { 1844fn closure_1() {
1866 check_infer_with_mismatches( 1845 check_infer_with_mismatches(
1867 r#" 1846 r#"
1868 #[lang = "fn_once"] 1847#[lang = "fn_once"]
1869 trait FnOnce<Args> { 1848trait FnOnce<Args> {
1870 type Output; 1849 type Output;
1871 } 1850}
1872 1851
1873 enum Option<T> { Some(T), None } 1852enum Option<T> { Some(T), None }
1874 impl<T> Option<T> { 1853impl<T> Option<T> {
1875 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} } 1854 fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Option<U> { loop {} }
1876 } 1855}
1877 1856
1878 fn test() { 1857fn test() {
1879 let x = Option::Some(1u32); 1858 let x = Option::Some(1u32);
1880 x.map(|v| v + 1); 1859 x.map(|v| v + 1);
1881 x.map(|_v| 1u64); 1860 x.map(|_v| 1u64);
1882 let y: Option<i64> = x.map(|_v| 1); 1861 let y: Option<i64> = x.map(|_v| 1);
1883 } 1862}"#,
1884 "#,
1885 expect![[r#" 1863 expect![[r#"
1886 147..151 'self': Option<T> 1864 147..151 'self': Option<T>
1887 153..154 'f': F 1865 153..154 'f': F
@@ -1919,38 +1897,63 @@ fn closure_1() {
1919fn closure_2() { 1897fn closure_2() {
1920 check_infer_with_mismatches( 1898 check_infer_with_mismatches(
1921 r#" 1899 r#"
1922 trait FnOnce<Args> { 1900#[lang = "add"]
1923 type Output; 1901pub trait Add<Rhs = Self> {
1924 } 1902 type Output;
1903 fn add(self, rhs: Rhs) -> Self::Output;
1904}
1925 1905
1926 fn test<F: FnOnce(u32) -> u64>(f: F) { 1906trait FnOnce<Args> {
1927 f(1); 1907 type Output;
1928 let g = |v| v + 1; 1908}
1929 g(1u64); 1909
1930 let h = |v| 1u128 + v; 1910impl Add for u64 {
1931 } 1911 type Output = Self;
1932 "#, 1912 fn add(self, rhs: u64) -> Self::Output {0}
1913}
1914
1915impl Add for u128 {
1916 type Output = Self;
1917 fn add(self, rhs: u128) -> Self::Output {0}
1918}
1919
1920fn test<F: FnOnce(u32) -> u64>(f: F) {
1921 f(1);
1922 let g = |v| v + 1;
1923 g(1u64);
1924 let h = |v| 1u128 + v;
1925}"#,
1933 expect![[r#" 1926 expect![[r#"
1934 72..73 'f': F 1927 72..76 'self': Self
1935 78..154 '{ ...+ v; }': () 1928 78..81 'rhs': Rhs
1936 84..85 'f': F 1929 203..207 'self': u64
1937 84..88 'f(1)': {unknown} 1930 209..212 'rhs': u64
1938 86..87 '1': i32 1931 235..238 '{0}': u64
1939 98..99 'g': |u64| -> i32 1932 236..237 '0': u64
1940 102..111 '|v| v + 1': |u64| -> i32 1933 297..301 'self': u128
1941 103..104 'v': u64 1934 303..306 'rhs': u128
1942 106..107 'v': u64 1935 330..333 '{0}': u128
1943 106..111 'v + 1': i32 1936 331..332 '0': u128
1944 110..111 '1': i32 1937 368..369 'f': F
1945 117..118 'g': |u64| -> i32 1938 374..450 '{ ...+ v; }': ()
1946 117..124 'g(1u64)': i32 1939 380..381 'f': F
1947 119..123 '1u64': u64 1940 380..384 'f(1)': {unknown}
1948 134..135 'h': |u128| -> u128 1941 382..383 '1': i32
1949 138..151 '|v| 1u128 + v': |u128| -> u128 1942 394..395 'g': |u64| -> u64
1950 139..140 'v': u128 1943 398..407 '|v| v + 1': |u64| -> u64
1951 142..147 '1u128': u128 1944 399..400 'v': u64
1952 142..151 '1u128 + v': u128 1945 402..403 'v': u64
1953 150..151 'v': u128 1946 402..407 'v + 1': u64
1947 406..407 '1': u64
1948 413..414 'g': |u64| -> u64
1949 413..420 'g(1u64)': u64
1950 415..419 '1u64': u64
1951 430..431 'h': |u128| -> u128
1952 434..447 '|v| 1u128 + v': |u128| -> u128
1953 435..436 'v': u128
1954 438..443 '1u128': u128
1955 438..447 '1u128 + v': u128
1956 446..447 'v': u128
1954 "#]], 1957 "#]],
1955 ); 1958 );
1956} 1959}
@@ -1959,29 +1962,28 @@ fn closure_2() {
1959fn closure_as_argument_inference_order() { 1962fn closure_as_argument_inference_order() {
1960 check_infer_with_mismatches( 1963 check_infer_with_mismatches(
1961 r#" 1964 r#"
1962 #[lang = "fn_once"] 1965#[lang = "fn_once"]
1963 trait FnOnce<Args> { 1966trait FnOnce<Args> {
1964 type Output; 1967 type Output;
1965 } 1968}
1966 1969
1967 fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} } 1970fn foo1<T, U, F: FnOnce(T) -> U>(x: T, f: F) -> U { loop {} }
1968 fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} } 1971fn foo2<T, U, F: FnOnce(T) -> U>(f: F, x: T) -> U { loop {} }
1969 1972
1970 struct S; 1973struct S;
1971 impl S { 1974impl S {
1972 fn method(self) -> u64; 1975 fn method(self) -> u64;
1973 1976
1974 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} } 1977 fn foo1<T, U, F: FnOnce(T) -> U>(self, x: T, f: F) -> U { loop {} }
1975 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} } 1978 fn foo2<T, U, F: FnOnce(T) -> U>(self, f: F, x: T) -> U { loop {} }
1976 } 1979}
1977 1980
1978 fn test() { 1981fn test() {
1979 let x1 = foo1(S, |s| s.method()); 1982 let x1 = foo1(S, |s| s.method());
1980 let x2 = foo2(|s| s.method(), S); 1983 let x2 = foo2(|s| s.method(), S);
1981 let x3 = S.foo1(S, |s| s.method()); 1984 let x3 = S.foo1(S, |s| s.method());
1982 let x4 = S.foo2(|s| s.method(), S); 1985 let x4 = S.foo2(|s| s.method(), S);
1983 } 1986}"#,
1984 "#,
1985 expect![[r#" 1987 expect![[r#"
1986 94..95 'x': T 1988 94..95 'x': T
1987 100..101 'f': F 1989 100..101 'f': F
@@ -2110,27 +2112,26 @@ fn test<T, U>() where T::Item: Trait2, T: Trait<U::Item>, U: Trait<()> {
2110fn unselected_projection_on_impl_self() { 2112fn unselected_projection_on_impl_self() {
2111 check_infer( 2113 check_infer(
2112 r#" 2114 r#"
2113 //- /main.rs 2115//- /main.rs
2114 trait Trait { 2116trait Trait {
2115 type Item; 2117 type Item;
2116 2118
2117 fn f(&self, x: Self::Item); 2119 fn f(&self, x: Self::Item);
2118 } 2120}
2119 2121
2120 struct S; 2122struct S;
2121 2123
2122 impl Trait for S { 2124impl Trait for S {
2123 type Item = u32; 2125 type Item = u32;
2124 fn f(&self, x: Self::Item) { let y = x; } 2126 fn f(&self, x: Self::Item) { let y = x; }
2125 } 2127}
2126 2128
2127 struct S2; 2129struct S2;
2128 2130
2129 impl Trait for S2 { 2131impl Trait for S2 {
2130 type Item = i32; 2132 type Item = i32;
2131 fn f(&self, x: <Self>::Item) { let y = x; } 2133 fn f(&self, x: <Self>::Item) { let y = x; }
2132 } 2134}"#,
2133 "#,
2134 expect![[r#" 2135 expect![[r#"
2135 40..44 'self': &Self 2136 40..44 'self': &Self
2136 46..47 'x': Trait::Item<Self> 2137 46..47 'x': Trait::Item<Self>
@@ -2366,58 +2367,57 @@ fn test<I: Iterator<Item: Iterator<Item = u32>>>() {
2366fn proc_macro_server_types() { 2367fn proc_macro_server_types() {
2367 check_infer( 2368 check_infer(
2368 r#" 2369 r#"
2369 macro_rules! with_api { 2370macro_rules! with_api {
2370 ($S:ident, $self:ident, $m:ident) => { 2371 ($S:ident, $self:ident, $m:ident) => {
2371 $m! { 2372 $m! {
2372 TokenStream { 2373 TokenStream {
2373 fn new() -> $S::TokenStream; 2374 fn new() -> $S::TokenStream;
2374 }, 2375 },
2375 Group { 2376 Group {
2376 }, 2377 },
2377 }
2378 };
2379 } 2378 }
2380 macro_rules! associated_item { 2379 };
2381 (type TokenStream) => 2380}
2382 (type TokenStream: 'static;); 2381macro_rules! associated_item {
2383 (type Group) => 2382 (type TokenStream) =>
2384 (type Group: 'static;); 2383 (type TokenStream: 'static;);
2385 ($($item:tt)*) => ($($item)*;) 2384 (type Group) =>
2386 } 2385 (type Group: 'static;);
2387 macro_rules! declare_server_traits { 2386 ($($item:tt)*) => ($($item)*;)
2388 ($($name:ident { 2387}
2389 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)* 2388macro_rules! declare_server_traits {
2390 }),* $(,)?) => { 2389 ($($name:ident {
2391 pub trait Types { 2390 $(fn $method:ident($($arg:ident: $arg_ty:ty),* $(,)?) $(-> $ret_ty:ty)?;)*
2392 $(associated_item!(type $name);)* 2391 }),* $(,)?) => {
2393 } 2392 pub trait Types {
2394 2393 $(associated_item!(type $name);)*
2395 $(pub trait $name: Types {
2396 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2397 })*
2398
2399 pub trait Server: Types $(+ $name)* {}
2400 impl<S: Types $(+ $name)*> Server for S {}
2401 }
2402 } 2394 }
2403 2395
2404 with_api!(Self, self_, declare_server_traits); 2396 $(pub trait $name: Types {
2405 struct G {} 2397 $(associated_item!(fn $method($($arg: $arg_ty),*) $(-> $ret_ty)?);)*
2406 struct T {} 2398 })*
2407 struct Rustc;
2408 impl Types for Rustc {
2409 type TokenStream = T;
2410 type Group = G;
2411 }
2412 2399
2413 fn make<T>() -> T { loop {} } 2400 pub trait Server: Types $(+ $name)* {}
2414 impl TokenStream for Rustc { 2401 impl<S: Types $(+ $name)*> Server for S {}
2415 fn new() -> Self::TokenStream { 2402 }
2416 let group: Self::Group = make(); 2403}
2417 make() 2404
2418 } 2405with_api!(Self, self_, declare_server_traits);
2419 } 2406struct G {}
2420 "#, 2407struct T {}
2408struct Rustc;
2409impl Types for Rustc {
2410 type TokenStream = T;
2411 type Group = G;
2412}
2413
2414fn make<T>() -> T { loop {} }
2415impl TokenStream for Rustc {
2416 fn new() -> Self::TokenStream {
2417 let group: Self::Group = make();
2418 make()
2419 }
2420}"#,
2421 expect![[r#" 2421 expect![[r#"
2422 1061..1072 '{ loop {} }': T 2422 1061..1072 '{ loop {} }': T
2423 1063..1070 'loop {}': ! 2423 1063..1070 'loop {}': !
@@ -2436,23 +2436,22 @@ fn proc_macro_server_types() {
2436fn unify_impl_trait() { 2436fn unify_impl_trait() {
2437 check_infer_with_mismatches( 2437 check_infer_with_mismatches(
2438 r#" 2438 r#"
2439 trait Trait<T> {} 2439trait Trait<T> {}
2440 2440
2441 fn foo(x: impl Trait<u32>) { loop {} } 2441fn foo(x: impl Trait<u32>) { loop {} }
2442 fn bar<T>(x: impl Trait<T>) -> T { loop {} } 2442fn bar<T>(x: impl Trait<T>) -> T { loop {} }
2443 2443
2444 struct S<T>(T); 2444struct S<T>(T);
2445 impl<T> Trait<T> for S<T> {} 2445impl<T> Trait<T> for S<T> {}
2446 2446
2447 fn default<T>() -> T { loop {} } 2447fn default<T>() -> T { loop {} }
2448 2448
2449 fn test() -> impl Trait<i32> { 2449fn test() -> impl Trait<i32> {
2450 let s1 = S(default()); 2450 let s1 = S(default());
2451 foo(s1); 2451 foo(s1);
2452 let x: i32 = bar(S(default())); 2452 let x: i32 = bar(S(default()));
2453 S(default()) 2453 S(default())
2454 } 2454}"#,
2455 "#,
2456 expect![[r#" 2455 expect![[r#"
2457 26..27 'x': impl Trait<u32> 2456 26..27 'x': impl Trait<u32>
2458 46..57 '{ loop {} }': () 2457 46..57 '{ loop {} }': ()
@@ -2493,30 +2492,29 @@ fn unify_impl_trait() {
2493fn assoc_types_from_bounds() { 2492fn assoc_types_from_bounds() {
2494 check_infer( 2493 check_infer(
2495 r#" 2494 r#"
2496 //- /main.rs 2495//- /main.rs
2497 #[lang = "fn_once"] 2496#[lang = "fn_once"]
2498 trait FnOnce<Args> { 2497trait FnOnce<Args> {
2499 type Output; 2498 type Output;
2500 } 2499}
2501 2500
2502 trait T { 2501trait T {
2503 type O; 2502 type O;
2504 } 2503}
2505 2504
2506 impl T for () { 2505impl T for () {
2507 type O = (); 2506 type O = ();
2508 } 2507}
2509 2508
2510 fn f<X, F>(_v: F) 2509fn f<X, F>(_v: F)
2511 where 2510where
2512 X: T, 2511 X: T,
2513 F: FnOnce(&X::O), 2512 F: FnOnce(&X::O),
2514 { } 2513{ }
2515 2514
2516 fn main() { 2515fn main() {
2517 f::<(), _>(|z| { z; }); 2516 f::<(), _>(|z| { z; });
2518 } 2517}"#,
2519 "#,
2520 expect![[r#" 2518 expect![[r#"
2521 133..135 '_v': F 2519 133..135 '_v': F
2522 178..181 '{ }': () 2520 178..181 '{ }': ()
@@ -2602,76 +2600,75 @@ fn test() {
2602fn iterator_chain() { 2600fn iterator_chain() {
2603 check_infer_with_mismatches( 2601 check_infer_with_mismatches(
2604 r#" 2602 r#"
2605 //- /main.rs 2603//- /main.rs
2606 #[lang = "fn_once"] 2604#[lang = "fn_once"]
2607 trait FnOnce<Args> { 2605trait FnOnce<Args> {
2608 type Output; 2606 type Output;
2609 } 2607}
2610 #[lang = "fn_mut"] 2608#[lang = "fn_mut"]
2611 trait FnMut<Args>: FnOnce<Args> { } 2609trait FnMut<Args>: FnOnce<Args> { }
2612 2610
2613 enum Option<T> { Some(T), None } 2611enum Option<T> { Some(T), None }
2614 use Option::*; 2612use Option::*;
2615 2613
2616 pub trait Iterator { 2614pub trait Iterator {
2617 type Item; 2615 type Item;
2618 2616
2619 fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F> 2617 fn filter_map<B, F>(self, f: F) -> FilterMap<Self, F>
2620 where 2618 where
2621 F: FnMut(Self::Item) -> Option<B>, 2619 F: FnMut(Self::Item) -> Option<B>,
2622 { loop {} } 2620 { loop {} }
2623 2621
2624 fn for_each<F>(self, f: F) 2622 fn for_each<F>(self, f: F)
2625 where 2623 where
2626 F: FnMut(Self::Item), 2624 F: FnMut(Self::Item),
2627 { loop {} } 2625 { loop {} }
2628 } 2626}
2629 2627
2630 pub trait IntoIterator { 2628pub trait IntoIterator {
2631 type Item; 2629 type Item;
2632 type IntoIter: Iterator<Item = Self::Item>; 2630 type IntoIter: Iterator<Item = Self::Item>;
2633 fn into_iter(self) -> Self::IntoIter; 2631 fn into_iter(self) -> Self::IntoIter;
2634 } 2632}
2635 2633
2636 pub struct FilterMap<I, F> { } 2634pub struct FilterMap<I, F> { }
2637 impl<B, I: Iterator, F> Iterator for FilterMap<I, F> 2635impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
2638 where 2636where
2639 F: FnMut(I::Item) -> Option<B>, 2637 F: FnMut(I::Item) -> Option<B>,
2640 { 2638{
2641 type Item = B; 2639 type Item = B;
2642 } 2640}
2643 2641
2644 #[stable(feature = "rust1", since = "1.0.0")] 2642#[stable(feature = "rust1", since = "1.0.0")]
2645 impl<I: Iterator> IntoIterator for I { 2643impl<I: Iterator> IntoIterator for I {
2646 type Item = I::Item; 2644 type Item = I::Item;
2647 type IntoIter = I; 2645 type IntoIter = I;
2648 2646
2649 fn into_iter(self) -> I { 2647 fn into_iter(self) -> I {
2650 self 2648 self
2651 } 2649 }
2652 } 2650}
2653 2651
2654 struct Vec<T> {} 2652struct Vec<T> {}
2655 impl<T> Vec<T> { 2653impl<T> Vec<T> {
2656 fn new() -> Self { loop {} } 2654 fn new() -> Self { loop {} }
2657 } 2655}
2658 2656
2659 impl<T> IntoIterator for Vec<T> { 2657impl<T> IntoIterator for Vec<T> {
2660 type Item = T; 2658 type Item = T;
2661 type IntoIter = IntoIter<T>; 2659 type IntoIter = IntoIter<T>;
2662 } 2660}
2663 2661
2664 pub struct IntoIter<T> { } 2662pub struct IntoIter<T> { }
2665 impl<T> Iterator for IntoIter<T> { 2663impl<T> Iterator for IntoIter<T> {
2666 type Item = T; 2664 type Item = T;
2667 } 2665}
2668 2666
2669 fn main() { 2667fn main() {
2670 Vec::<i32>::new().into_iter() 2668 Vec::<i32>::new().into_iter()
2671 .filter_map(|x| if x > 0 { Some(x as u32) } else { None }) 2669 .filter_map(|x| if x > 0 { Some(x as u32) } else { None })
2672 .for_each(|y| { y; }); 2670 .for_each(|y| { y; });
2673 } 2671}"#,
2674 "#,
2675 expect![[r#" 2672 expect![[r#"
2676 226..230 'self': Self 2673 226..230 'self': Self
2677 232..233 'f': F 2674 232..233 'f': F
@@ -2753,14 +2750,13 @@ fn main() {
2753fn trait_object_no_coercion() { 2750fn trait_object_no_coercion() {
2754 check_infer_with_mismatches( 2751 check_infer_with_mismatches(
2755 r#" 2752 r#"
2756 trait Foo {} 2753trait Foo {}
2757 2754
2758 fn foo(x: &dyn Foo) {} 2755fn foo(x: &dyn Foo) {}
2759 2756
2760 fn test(x: &dyn Foo) { 2757fn test(x: &dyn Foo) {
2761 foo(x); 2758 foo(x);
2762 } 2759}"#,
2763 "#,
2764 expect![[r#" 2760 expect![[r#"
2765 21..22 'x': &dyn Foo 2761 21..22 'x': &dyn Foo
2766 34..36 '{}': () 2762 34..36 '{}': ()
@@ -2777,23 +2773,22 @@ fn trait_object_no_coercion() {
2777fn builtin_copy() { 2773fn builtin_copy() {
2778 check_infer_with_mismatches( 2774 check_infer_with_mismatches(
2779 r#" 2775 r#"
2780 #[lang = "copy"] 2776#[lang = "copy"]
2781 trait Copy {} 2777trait Copy {}
2782 2778
2783 struct IsCopy; 2779struct IsCopy;
2784 impl Copy for IsCopy {} 2780impl Copy for IsCopy {}
2785 struct NotCopy; 2781struct NotCopy;
2786 2782
2787 trait Test { fn test(&self) -> bool; } 2783trait Test { fn test(&self) -> bool; }
2788 impl<T: Copy> Test for T {} 2784impl<T: Copy> Test for T {}
2789 2785
2790 fn test() { 2786fn test() {
2791 IsCopy.test(); 2787 IsCopy.test();
2792 NotCopy.test(); 2788 NotCopy.test();
2793 (IsCopy, IsCopy).test(); 2789 (IsCopy, IsCopy).test();
2794 (IsCopy, NotCopy).test(); 2790 (IsCopy, NotCopy).test();
2795 } 2791}"#,
2796 "#,
2797 expect![[r#" 2792 expect![[r#"
2798 110..114 'self': &Self 2793 110..114 'self': &Self
2799 166..267 '{ ...t(); }': () 2794 166..267 '{ ...t(); }': ()
@@ -2817,24 +2812,23 @@ fn builtin_copy() {
2817fn builtin_fn_def_copy() { 2812fn builtin_fn_def_copy() {
2818 check_infer_with_mismatches( 2813 check_infer_with_mismatches(
2819 r#" 2814 r#"
2820 #[lang = "copy"] 2815#[lang = "copy"]
2821 trait Copy {} 2816trait Copy {}
2822 2817
2823 fn foo() {} 2818fn foo() {}
2824 fn bar<T: Copy>(T) -> T {} 2819fn bar<T: Copy>(T) -> T {}
2825 struct Struct(usize); 2820struct Struct(usize);
2826 enum Enum { Variant(usize) } 2821enum Enum { Variant(usize) }
2827 2822
2828 trait Test { fn test(&self) -> bool; } 2823trait Test { fn test(&self) -> bool; }
2829 impl<T: Copy> Test for T {} 2824impl<T: Copy> Test for T {}
2830 2825
2831 fn test() { 2826fn test() {
2832 foo.test(); 2827 foo.test();
2833 bar.test(); 2828 bar.test();
2834 Struct.test(); 2829 Struct.test();
2835 Enum::Variant.test(); 2830 Enum::Variant.test();
2836 } 2831}"#,
2837 "#,
2838 expect![[r#" 2832 expect![[r#"
2839 41..43 '{}': () 2833 41..43 '{}': ()
2840 60..61 'T': {unknown} 2834 60..61 'T': {unknown}
@@ -2858,18 +2852,17 @@ fn builtin_fn_def_copy() {
2858fn builtin_fn_ptr_copy() { 2852fn builtin_fn_ptr_copy() {
2859 check_infer_with_mismatches( 2853 check_infer_with_mismatches(
2860 r#" 2854 r#"
2861 #[lang = "copy"] 2855#[lang = "copy"]
2862 trait Copy {} 2856trait Copy {}
2863 2857
2864 trait Test { fn test(&self) -> bool; } 2858trait Test { fn test(&self) -> bool; }
2865 impl<T: Copy> Test for T {} 2859impl<T: Copy> Test for T {}
2866 2860
2867 fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) { 2861fn test(f1: fn(), f2: fn(usize) -> u8, f3: fn(u8, u8) -> &u8) {
2868 f1.test(); 2862 f1.test();
2869 f2.test(); 2863 f2.test();
2870 f3.test(); 2864 f3.test();
2871 } 2865}"#,
2872 "#,
2873 expect![[r#" 2866 expect![[r#"
2874 54..58 'self': &Self 2867 54..58 'self': &Self
2875 108..110 'f1': fn() 2868 108..110 'f1': fn()
@@ -2890,19 +2883,18 @@ fn builtin_fn_ptr_copy() {
2890fn builtin_sized() { 2883fn builtin_sized() {
2891 check_infer_with_mismatches( 2884 check_infer_with_mismatches(
2892 r#" 2885 r#"
2893 #[lang = "sized"] 2886#[lang = "sized"]
2894 trait Sized {} 2887trait Sized {}
2895 2888
2896 trait Test { fn test(&self) -> bool; } 2889trait Test { fn test(&self) -> bool; }
2897 impl<T: Sized> Test for T {} 2890impl<T: Sized> Test for T {}
2898 2891
2899 fn test() { 2892fn test() {
2900 1u8.test(); 2893 1u8.test();
2901 (*"foo").test(); // not Sized 2894 (*"foo").test(); // not Sized
2902 (1u8, 1u8).test(); 2895 (1u8, 1u8).test();
2903 (1u8, *"foo").test(); // not Sized 2896 (1u8, *"foo").test(); // not Sized
2904 } 2897}"#,
2905 "#,
2906 expect![[r#" 2898 expect![[r#"
2907 56..60 'self': &Self 2899 56..60 'self': &Self
2908 113..228 '{ ...ized }': () 2900 113..228 '{ ...ized }': ()
@@ -2972,19 +2964,18 @@ impl<A: Step> iter::Iterator for ops::Range<A> {
2972fn infer_closure_arg() { 2964fn infer_closure_arg() {
2973 check_infer( 2965 check_infer(
2974 r#" 2966 r#"
2975 //- /lib.rs 2967//- /lib.rs
2976 2968
2977 enum Option<T> { 2969enum Option<T> {
2978 None, 2970 None,
2979 Some(T) 2971 Some(T)
2980 } 2972}
2981 2973
2982 fn foo() { 2974fn foo() {
2983 let s = Option::None; 2975 let s = Option::None;
2984 let f = |x: Option<i32>| {}; 2976 let f = |x: Option<i32>| {};
2985 (&f)(s) 2977 (&f)(s)
2986 } 2978}"#,
2987 "#,
2988 expect![[r#" 2979 expect![[r#"
2989 52..126 '{ ...)(s) }': () 2980 52..126 '{ ...)(s) }': ()
2990 62..63 's': Option<i32> 2981 62..63 's': Option<i32>
@@ -3053,46 +3044,45 @@ fn infer_box_fn_arg() {
3053 // The type mismatch is a bug 3044 // The type mismatch is a bug
3054 check_infer_with_mismatches( 3045 check_infer_with_mismatches(
3055 r#" 3046 r#"
3056 //- /lib.rs deps:std 3047//- /lib.rs deps:std
3057 3048
3058 #[lang = "fn_once"] 3049#[lang = "fn_once"]
3059 pub trait FnOnce<Args> { 3050pub trait FnOnce<Args> {
3060 type Output; 3051 type Output;
3061 3052
3062 extern "rust-call" fn call_once(self, args: Args) -> Self::Output; 3053 extern "rust-call" fn call_once(self, args: Args) -> Self::Output;
3063 } 3054}
3064 3055
3065 #[lang = "deref"] 3056#[lang = "deref"]
3066 pub trait Deref { 3057pub trait Deref {
3067 type Target: ?Sized; 3058 type Target: ?Sized;
3068 3059
3069 fn deref(&self) -> &Self::Target; 3060 fn deref(&self) -> &Self::Target;
3070 } 3061}
3071 3062
3072 #[lang = "owned_box"] 3063#[lang = "owned_box"]
3073 pub struct Box<T: ?Sized> { 3064pub struct Box<T: ?Sized> {
3074 inner: *mut T, 3065 inner: *mut T,
3075 } 3066}
3076 3067
3077 impl<T: ?Sized> Deref for Box<T> { 3068impl<T: ?Sized> Deref for Box<T> {
3078 type Target = T; 3069 type Target = T;
3079 3070
3080 fn deref(&self) -> &T { 3071 fn deref(&self) -> &T {
3081 &self.inner 3072 &self.inner
3082 } 3073 }
3083 } 3074}
3084 3075
3085 enum Option<T> { 3076enum Option<T> {
3086 None, 3077 None,
3087 Some(T) 3078 Some(T)
3088 } 3079}
3089 3080
3090 fn foo() { 3081fn foo() {
3091 let s = Option::None; 3082 let s = Option::None;
3092 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {}); 3083 let f: Box<dyn FnOnce(&Option<i32>)> = box (|ps| {});
3093 f(&s); 3084 f(&s);
3094 } 3085}"#,
3095 "#,
3096 expect![[r#" 3086 expect![[r#"
3097 100..104 'self': Self 3087 100..104 'self': Self
3098 106..110 'args': Args 3088 106..110 'args': Args
@@ -3258,8 +3248,7 @@ fn f() {
3258 ().method(); 3248 ().method();
3259 //^^^^^^^^^^^ u8 3249 //^^^^^^^^^^^ u8
3260 } 3250 }
3261} 3251}"#,
3262 "#,
3263 expect![[r#" 3252 expect![[r#"
3264 46..50 'self': &Self 3253 46..50 'self': &Self
3265 58..63 '{ 0 }': u8 3254 58..63 '{ 0 }': u8
@@ -3313,8 +3302,7 @@ fn f() {
3313 fn inner() -> S { 3302 fn inner() -> S {
3314 let s = inner(); 3303 let s = inner();
3315 } 3304 }
3316} 3305}"#,
3317 "#,
3318 expect![[r#" 3306 expect![[r#"
3319 17..73 '{ ... } }': () 3307 17..73 '{ ... } }': ()
3320 39..71 '{ ... }': () 3308 39..71 '{ ... }': ()
@@ -3349,8 +3337,7 @@ fn test() {
3349 let x = A; 3337 let x = A;
3350 let y = A; 3338 let y = A;
3351 let r = x.do_op(y); 3339 let r = x.do_op(y);
3352} 3340}"#,
3353 "#,
3354 expect![[r#" 3341 expect![[r#"
3355 63..67 'self': Self 3342 63..67 'self': Self
3356 69..72 'rhs': RHS 3343 69..72 'rhs': RHS
@@ -3399,9 +3386,7 @@ impl foo::Bar for F {
3399fn foo() { 3386fn foo() {
3400 use foo::Bar; 3387 use foo::Bar;
3401 let x = <F as Bar>::boo(); 3388 let x = <F as Bar>::boo();
3402} 3389}"#,
3403
3404 "#,
3405 expect![[r#" 3390 expect![[r#"
3406 132..163 '{ ... }': Bar::Output<Self> 3391 132..163 '{ ... }': Bar::Output<Self>
3407 146..153 'loop {}': ! 3392 146..153 'loop {}': !
@@ -3413,3 +3398,79 @@ fn foo() {
3413 "#]], 3398 "#]],
3414 ); 3399 );
3415} 3400}
3401
3402#[test]
3403fn renamed_extern_crate_in_block() {
3404 check_types(
3405 r#"
3406//- /lib.rs crate:lib deps:serde
3407use serde::Deserialize;
3408
3409struct Foo {}
3410
3411const _ : () = {
3412 extern crate serde as _serde;
3413 impl _serde::Deserialize for Foo {
3414 fn deserialize() -> u8 { 0 }
3415 }
3416};
3417
3418fn foo() {
3419 Foo::deserialize();
3420 //^^^^^^^^^^^^^^^^^^ u8
3421}
3422
3423//- /serde.rs crate:serde
3424
3425pub trait Deserialize {
3426 fn deserialize() -> u8;
3427}"#,
3428 );
3429}
3430
3431#[test]
3432fn bin_op_adt_with_rhs_primitive() {
3433 check_infer_with_mismatches(
3434 r#"
3435#[lang = "add"]
3436pub trait Add<Rhs = Self> {
3437 type Output;
3438 fn add(self, rhs: Rhs) -> Self::Output;
3439}
3440
3441struct Wrapper(u32);
3442impl Add<u32> for Wrapper {
3443 type Output = Self;
3444 fn add(self, rhs: u32) -> Wrapper {
3445 Wrapper(rhs)
3446 }
3447}
3448fn main(){
3449 let wrapped = Wrapper(10);
3450 let num: u32 = 2;
3451 let res = wrapped + num;
3452
3453}"#,
3454 expect![[r#"
3455 72..76 'self': Self
3456 78..81 'rhs': Rhs
3457 192..196 'self': Wrapper
3458 198..201 'rhs': u32
3459 219..247 '{ ... }': Wrapper
3460 229..236 'Wrapper': Wrapper(u32) -> Wrapper
3461 229..241 'Wrapper(rhs)': Wrapper
3462 237..240 'rhs': u32
3463 259..345 '{ ...um; }': ()
3464 269..276 'wrapped': Wrapper
3465 279..286 'Wrapper': Wrapper(u32) -> Wrapper
3466 279..290 'Wrapper(10)': Wrapper
3467 287..289 '10': u32
3468 300..303 'num': u32
3469 311..312 '2': u32
3470 322..325 'res': Wrapper
3471 328..335 'wrapped': Wrapper
3472 328..341 'wrapped + num': Wrapper
3473 338..341 'num': u32
3474 "#]],
3475 )
3476}
diff --git a/crates/hir_ty/src/traits/chalk/tls.rs b/crates/hir_ty/src/tls.rs
index 8892a63a9..87c671a42 100644
--- a/crates/hir_ty/src/traits/chalk/tls.rs
+++ b/crates/hir_ty/src/tls.rs
@@ -4,8 +4,10 @@ use std::fmt;
4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication}; 4use chalk_ir::{AliasTy, GenericArg, Goal, Goals, Lifetime, ProgramClauseImplication};
5use itertools::Itertools; 5use itertools::Itertools;
6 6
7use super::{from_chalk, Interner}; 7use crate::{
8use crate::{db::HirDatabase, from_assoc_type_id, CallableDefId}; 8 chalk_db, db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, mapping::from_chalk,
9 CallableDefId, Interner,
10};
9use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId}; 11use hir_def::{AdtId, AssocContainerId, Lookup, TypeAliasId};
10 12
11pub(crate) use unsafe_tls::{set_current_program, with_current_program}; 13pub(crate) use unsafe_tls::{set_current_program, with_current_program};
@@ -15,7 +17,7 @@ pub(crate) struct DebugContext<'a>(&'a dyn HirDatabase);
15impl DebugContext<'_> { 17impl DebugContext<'_> {
16 pub(crate) fn debug_struct_id( 18 pub(crate) fn debug_struct_id(
17 &self, 19 &self,
18 id: super::AdtId, 20 id: chalk_db::AdtId,
19 f: &mut fmt::Formatter<'_>, 21 f: &mut fmt::Formatter<'_>,
20 ) -> Result<(), fmt::Error> { 22 ) -> Result<(), fmt::Error> {
21 let name = match id.0 { 23 let name = match id.0 {
@@ -28,17 +30,17 @@ impl DebugContext<'_> {
28 30
29 pub(crate) fn debug_trait_id( 31 pub(crate) fn debug_trait_id(
30 &self, 32 &self,
31 id: super::TraitId, 33 id: chalk_db::TraitId,
32 fmt: &mut fmt::Formatter<'_>, 34 fmt: &mut fmt::Formatter<'_>,
33 ) -> Result<(), fmt::Error> { 35 ) -> Result<(), fmt::Error> {
34 let trait_: hir_def::TraitId = from_chalk(self.0, id); 36 let trait_: hir_def::TraitId = from_chalk_trait_id(id);
35 let trait_data = self.0.trait_data(trait_); 37 let trait_data = self.0.trait_data(trait_);
36 write!(fmt, "{}", trait_data.name) 38 write!(fmt, "{}", trait_data.name)
37 } 39 }
38 40
39 pub(crate) fn debug_assoc_type_id( 41 pub(crate) fn debug_assoc_type_id(
40 &self, 42 &self,
41 id: super::AssocTypeId, 43 id: chalk_db::AssocTypeId,
42 fmt: &mut fmt::Formatter<'_>, 44 fmt: &mut fmt::Formatter<'_>,
43 ) -> Result<(), fmt::Error> { 45 ) -> Result<(), fmt::Error> {
44 let type_alias: TypeAliasId = from_assoc_type_id(id); 46 let type_alias: TypeAliasId = from_assoc_type_id(id);
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index c8883485c..9936d0803 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -1,28 +1,26 @@
1//! Trait solving using Chalk. 1//! Trait solving using Chalk.
2
2use std::env::var; 3use std::env::var;
3 4
4use base_db::CrateId;
5use chalk_ir::cast::Cast; 5use chalk_ir::cast::Cast;
6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver}; 6use chalk_solve::{logging_db::LoggingRustIrDatabase, Solver};
7
8use base_db::CrateId;
7use hir_def::{lang_item::LangItemTarget, TraitId}; 9use hir_def::{lang_item::LangItemTarget, TraitId};
8use stdx::panic_context; 10use stdx::panic_context;
9 11
10use crate::{ 12use crate::{
11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, 13 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 Solution, SolutionVariables, Ty, TyKind, WhereClause, 14 Interner, Solution, TraitRefExt, Ty, TyKind, WhereClause,
13}; 15};
14 16
15use self::chalk::{from_chalk, Interner, ToChalk};
16
17pub(crate) mod chalk;
18
19/// This controls how much 'time' we give the Chalk solver before giving up. 17/// This controls how much 'time' we give the Chalk solver before giving up.
20const CHALK_SOLVER_FUEL: i32 = 100; 18const CHALK_SOLVER_FUEL: i32 = 100;
21 19
22#[derive(Debug, Copy, Clone)] 20#[derive(Debug, Copy, Clone)]
23struct ChalkContext<'a> { 21pub(crate) struct ChalkContext<'a> {
24 db: &'a dyn HirDatabase, 22 pub(crate) db: &'a dyn HirDatabase,
25 krate: CrateId, 23 pub(crate) krate: CrateId,
26} 24}
27 25
28fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> { 26fn create_chalk_solver() -> chalk_recursive::RecursiveSolver<Interner> {
@@ -81,6 +79,7 @@ pub(crate) fn trait_solve_query(
81 db.trait_data(it.hir_trait_id()).name.to_string() 79 db.trait_data(it.hir_trait_id()).name.to_string()
82 } 80 }
83 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(), 81 DomainGoal::Holds(WhereClause::AliasEq(_)) => "alias_eq".to_string(),
82 _ => "??".to_string(),
84 }); 83 });
85 log::info!("trait_solve_query({})", goal.value.goal.display(db)); 84 log::info!("trait_solve_query({})", goal.value.goal.display(db));
86 85
@@ -95,13 +94,12 @@ pub(crate) fn trait_solve_query(
95 } 94 }
96 } 95 }
97 96
98 let canonical = goal.to_chalk(db).cast(&Interner); 97 let canonical = goal.cast(&Interner);
99 98
100 // We currently don't deal with universes (I think / hope they're not yet 99 // We currently don't deal with universes (I think / hope they're not yet
101 // relevant for our use cases?) 100 // relevant for our use cases?)
102 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 }; 101 let u_canonical = chalk_ir::UCanonical { canonical, universes: 1 };
103 let solution = solve(db, krate, &u_canonical); 102 solve(db, krate, &u_canonical)
104 solution.map(|solution| solution_from_chalk(db, solution))
105} 103}
106 104
107fn solve( 105fn solve(
@@ -148,7 +146,7 @@ fn solve(
148 // don't set the TLS for Chalk unless Chalk debugging is active, to make 146 // don't set the TLS for Chalk unless Chalk debugging is active, to make
149 // extra sure we only use it for debugging 147 // extra sure we only use it for debugging
150 let solution = 148 let solution =
151 if is_chalk_debug() { chalk::tls::set_current_program(db, solve) } else { solve() }; 149 if is_chalk_debug() { crate::tls::set_current_program(db, solve) } else { solve() };
152 150
153 solution 151 solution
154} 152}
@@ -169,34 +167,6 @@ fn is_chalk_print() -> bool {
169 std::env::var("CHALK_PRINT").is_ok() 167 std::env::var("CHALK_PRINT").is_ok()
170} 168}
171 169
172fn solution_from_chalk(
173 db: &dyn HirDatabase,
174 solution: chalk_solve::Solution<Interner>,
175) -> Solution {
176 let convert_subst = |subst: chalk_ir::Canonical<chalk_ir::Substitution<Interner>>| {
177 let result = from_chalk(db, subst);
178 SolutionVariables(result)
179 };
180 match solution {
181 chalk_solve::Solution::Unique(constr_subst) => {
182 let subst = chalk_ir::Canonical {
183 value: constr_subst.value.subst,
184 binders: constr_subst.binders,
185 };
186 Solution::Unique(convert_subst(subst))
187 }
188 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Definite(subst)) => {
189 Solution::Ambig(Guidance::Definite(convert_subst(subst)))
190 }
191 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Suggested(subst)) => {
192 Solution::Ambig(Guidance::Suggested(convert_subst(subst)))
193 }
194 chalk_solve::Solution::Ambig(chalk_solve::Guidance::Unknown) => {
195 Solution::Ambig(Guidance::Unknown)
196 }
197 }
198}
199
200#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 170#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
201pub enum FnTrait { 171pub enum FnTrait {
202 FnOnce, 172 FnOnce,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
deleted file mode 100644
index c3b148cab..000000000
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ /dev/null
@@ -1,572 +0,0 @@
1//! This module contains the implementations of the `ToChalk` trait, which
2//! handles conversion between our data types and their corresponding types in
3//! Chalk (in both directions); plus some helper functions for more specialized
4//! conversions.
5
6use chalk_ir::{cast::Cast, fold::shift::Shift, interner::HasInterner, LifetimeData};
7use chalk_solve::rust_ir;
8
9use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId};
11
12use crate::{
13 db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer,
14 GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution,
15 TraitRef, Ty, TypeWalk, WhereClause,
16};
17
18use super::interner::*;
19use super::*;
20
21impl ToChalk for Ty {
22 type Chalk = chalk_ir::Ty<Interner>;
23 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
24 match self.into_inner() {
25 TyKind::Ref(m, ty) => ref_to_chalk(db, m, ty),
26 TyKind::Array(ty) => array_to_chalk(db, ty),
27 TyKind::Function(FnPointer { sig, substs, .. }) => {
28 let substitution = chalk_ir::FnSubst(substs.to_chalk(db).shifted_in(&Interner));
29 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
30 num_binders: 0,
31 sig,
32 substitution,
33 })
34 .intern(&Interner)
35 }
36 TyKind::AssociatedType(assoc_type_id, substs) => {
37 let substitution = substs.to_chalk(db);
38 chalk_ir::TyKind::AssociatedType(assoc_type_id, substitution).intern(&Interner)
39 }
40
41 TyKind::OpaqueType(id, substs) => {
42 let substitution = substs.to_chalk(db);
43 chalk_ir::TyKind::OpaqueType(id, substitution).intern(&Interner)
44 }
45
46 TyKind::Foreign(id) => chalk_ir::TyKind::Foreign(id).intern(&Interner),
47
48 TyKind::Scalar(scalar) => chalk_ir::TyKind::Scalar(scalar).intern(&Interner),
49
50 TyKind::Tuple(cardinality, substs) => {
51 let substitution = substs.to_chalk(db);
52 chalk_ir::TyKind::Tuple(cardinality, substitution).intern(&Interner)
53 }
54 TyKind::Raw(mutability, ty) => {
55 let ty = ty.to_chalk(db);
56 chalk_ir::TyKind::Raw(mutability, ty).intern(&Interner)
57 }
58 TyKind::Slice(ty) => chalk_ir::TyKind::Slice(ty.to_chalk(db)).intern(&Interner),
59 TyKind::Str => chalk_ir::TyKind::Str.intern(&Interner),
60 TyKind::FnDef(id, substs) => {
61 let substitution = substs.to_chalk(db);
62 chalk_ir::TyKind::FnDef(id, substitution).intern(&Interner)
63 }
64 TyKind::Never => chalk_ir::TyKind::Never.intern(&Interner),
65
66 TyKind::Closure(closure_id, substs) => {
67 let substitution = substs.to_chalk(db);
68 chalk_ir::TyKind::Closure(closure_id, substitution).intern(&Interner)
69 }
70
71 TyKind::Adt(adt_id, substs) => {
72 let substitution = substs.to_chalk(db);
73 chalk_ir::TyKind::Adt(adt_id, substitution).intern(&Interner)
74 }
75 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
76 let associated_ty_id = proj_ty.associated_ty_id;
77 let substitution = proj_ty.substitution.to_chalk(db);
78 chalk_ir::AliasTy::Projection(chalk_ir::ProjectionTy {
79 associated_ty_id,
80 substitution,
81 })
82 .cast(&Interner)
83 .intern(&Interner)
84 }
85 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
86 let opaque_ty_id = opaque_ty.opaque_ty_id;
87 let substitution = opaque_ty.substitution.to_chalk(db);
88 chalk_ir::AliasTy::Opaque(chalk_ir::OpaqueTy { opaque_ty_id, substitution })
89 .cast(&Interner)
90 .intern(&Interner)
91 }
92 TyKind::Placeholder(idx) => idx.to_ty::<Interner>(&Interner),
93 TyKind::BoundVar(idx) => chalk_ir::TyKind::BoundVar(idx).intern(&Interner),
94 TyKind::InferenceVar(..) => panic!("uncanonicalized infer ty"),
95 TyKind::Dyn(dyn_ty) => {
96 let (bounds, binders) = dyn_ty.bounds.into_value_and_skipped_binders();
97 let where_clauses = chalk_ir::QuantifiedWhereClauses::from_iter(
98 &Interner,
99 bounds.interned().iter().cloned().map(|p| p.to_chalk(db)),
100 );
101 let bounded_ty = chalk_ir::DynTy {
102 bounds: chalk_ir::Binders::new(binders, where_clauses),
103 lifetime: LifetimeData::Static.intern(&Interner),
104 };
105 chalk_ir::TyKind::Dyn(bounded_ty).intern(&Interner)
106 }
107 TyKind::Error => chalk_ir::TyKind::Error.intern(&Interner),
108 }
109 }
110 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
111 match chalk.data(&Interner).kind.clone() {
112 chalk_ir::TyKind::Error => TyKind::Error,
113 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)),
114 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
115 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
116 let associated_ty = proj.associated_ty_id;
117 let parameters = from_chalk(db, proj.substitution);
118 TyKind::Alias(AliasTy::Projection(ProjectionTy {
119 associated_ty_id: associated_ty,
120 substitution: parameters,
121 }))
122 }
123 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Opaque(opaque_ty)) => {
124 let opaque_ty_id = opaque_ty.opaque_ty_id;
125 let parameters = from_chalk(db, opaque_ty.substitution);
126 TyKind::Alias(AliasTy::Opaque(OpaqueTy { opaque_ty_id, substitution: parameters }))
127 }
128 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
129 num_binders,
130 sig,
131 substitution,
132 ..
133 }) => {
134 assert_eq!(num_binders, 0);
135 let substs: Substitution = from_chalk(
136 db,
137 substitution.0.shifted_out(&Interner).expect("fn ptr should have no binders"),
138 );
139 TyKind::Function(FnPointer { num_args: (substs.len(&Interner) - 1), sig, substs })
140 }
141 chalk_ir::TyKind::BoundVar(idx) => TyKind::BoundVar(idx),
142 chalk_ir::TyKind::InferenceVar(_iv, _kind) => TyKind::Error,
143 chalk_ir::TyKind::Dyn(where_clauses) => {
144 assert_eq!(where_clauses.bounds.binders.len(&Interner), 1);
145 let bounds = where_clauses
146 .bounds
147 .skip_binders()
148 .iter(&Interner)
149 .map(|c| from_chalk(db, c.clone()));
150 TyKind::Dyn(crate::DynTy {
151 bounds: crate::Binders::new(
152 where_clauses.bounds.binders.clone(),
153 crate::QuantifiedWhereClauses::from_iter(&Interner, bounds),
154 ),
155 })
156 }
157
158 chalk_ir::TyKind::Adt(adt_id, subst) => TyKind::Adt(adt_id, from_chalk(db, subst)),
159 chalk_ir::TyKind::AssociatedType(type_id, subst) => {
160 TyKind::AssociatedType(type_id, from_chalk(db, subst))
161 }
162
163 chalk_ir::TyKind::OpaqueType(opaque_type_id, subst) => {
164 TyKind::OpaqueType(opaque_type_id, from_chalk(db, subst))
165 }
166
167 chalk_ir::TyKind::Scalar(scalar) => TyKind::Scalar(scalar),
168 chalk_ir::TyKind::Tuple(cardinality, subst) => {
169 TyKind::Tuple(cardinality, from_chalk(db, subst))
170 }
171 chalk_ir::TyKind::Raw(mutability, ty) => TyKind::Raw(mutability, from_chalk(db, ty)),
172 chalk_ir::TyKind::Slice(ty) => TyKind::Slice(from_chalk(db, ty)),
173 chalk_ir::TyKind::Ref(mutability, _lifetime, ty) => {
174 TyKind::Ref(mutability, from_chalk(db, ty))
175 }
176 chalk_ir::TyKind::Str => TyKind::Str,
177 chalk_ir::TyKind::Never => TyKind::Never,
178
179 chalk_ir::TyKind::FnDef(fn_def_id, subst) => {
180 TyKind::FnDef(fn_def_id, from_chalk(db, subst))
181 }
182
183 chalk_ir::TyKind::Closure(id, subst) => TyKind::Closure(id, from_chalk(db, subst)),
184
185 chalk_ir::TyKind::Foreign(foreign_def_id) => TyKind::Foreign(foreign_def_id),
186 chalk_ir::TyKind::Generator(_, _) => unimplemented!(), // FIXME
187 chalk_ir::TyKind::GeneratorWitness(_, _) => unimplemented!(), // FIXME
188 }
189 .intern(&Interner)
190 }
191}
192
193/// We currently don't model lifetimes, but Chalk does. So, we have to insert a
194/// fake lifetime here, because Chalks built-in logic may expect it to be there.
195fn ref_to_chalk(
196 db: &dyn HirDatabase,
197 mutability: chalk_ir::Mutability,
198 ty: Ty,
199) -> chalk_ir::Ty<Interner> {
200 let arg = ty.to_chalk(db);
201 let lifetime = LifetimeData::Static.intern(&Interner);
202 chalk_ir::TyKind::Ref(mutability, lifetime, arg).intern(&Interner)
203}
204
205/// We currently don't model constants, but Chalk does. So, we have to insert a
206/// fake constant here, because Chalks built-in logic may expect it to be there.
207fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> {
208 let arg = ty.to_chalk(db);
209 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
210 let const_ = chalk_ir::ConstData {
211 ty: usize_ty,
212 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
213 }
214 .intern(&Interner);
215 chalk_ir::TyKind::Array(arg, const_).intern(&Interner)
216}
217
218impl ToChalk for GenericArg {
219 type Chalk = chalk_ir::GenericArg<Interner>;
220
221 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
222 match self.interned() {
223 crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner),
224 }
225 }
226
227 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
228 match chalk.interned() {
229 chalk_ir::GenericArgData::Ty(ty) => Ty::from_chalk(db, ty.clone()).cast(&Interner),
230 chalk_ir::GenericArgData::Lifetime(_) => unimplemented!(),
231 chalk_ir::GenericArgData::Const(_) => unimplemented!(),
232 }
233 }
234}
235
236impl ToChalk for Substitution {
237 type Chalk = chalk_ir::Substitution<Interner>;
238
239 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Substitution<Interner> {
240 chalk_ir::Substitution::from_iter(
241 &Interner,
242 self.iter(&Interner).map(|ty| ty.clone().to_chalk(db)),
243 )
244 }
245
246 fn from_chalk(
247 db: &dyn HirDatabase,
248 parameters: chalk_ir::Substitution<Interner>,
249 ) -> Substitution {
250 let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect();
251 Substitution::intern(tys)
252 }
253}
254
255impl ToChalk for TraitRef {
256 type Chalk = chalk_ir::TraitRef<Interner>;
257
258 fn to_chalk(self: TraitRef, db: &dyn HirDatabase) -> chalk_ir::TraitRef<Interner> {
259 let trait_id = self.trait_id;
260 let substitution = self.substitution.to_chalk(db);
261 chalk_ir::TraitRef { trait_id, substitution }
262 }
263
264 fn from_chalk(db: &dyn HirDatabase, trait_ref: chalk_ir::TraitRef<Interner>) -> Self {
265 let trait_id = trait_ref.trait_id;
266 let substs = from_chalk(db, trait_ref.substitution);
267 TraitRef { trait_id, substitution: substs }
268 }
269}
270
271impl ToChalk for hir_def::TraitId {
272 type Chalk = TraitId;
273
274 fn to_chalk(self, _db: &dyn HirDatabase) -> TraitId {
275 chalk_ir::TraitId(self.as_intern_id())
276 }
277
278 fn from_chalk(_db: &dyn HirDatabase, trait_id: TraitId) -> hir_def::TraitId {
279 InternKey::from_intern_id(trait_id.0)
280 }
281}
282
283impl ToChalk for hir_def::ImplId {
284 type Chalk = ImplId;
285
286 fn to_chalk(self, _db: &dyn HirDatabase) -> ImplId {
287 chalk_ir::ImplId(self.as_intern_id())
288 }
289
290 fn from_chalk(_db: &dyn HirDatabase, impl_id: ImplId) -> hir_def::ImplId {
291 InternKey::from_intern_id(impl_id.0)
292 }
293}
294
295impl ToChalk for CallableDefId {
296 type Chalk = FnDefId;
297
298 fn to_chalk(self, db: &dyn HirDatabase) -> FnDefId {
299 db.intern_callable_def(self).into()
300 }
301
302 fn from_chalk(db: &dyn HirDatabase, fn_def_id: FnDefId) -> CallableDefId {
303 db.lookup_intern_callable_def(fn_def_id.into())
304 }
305}
306
307pub(crate) struct TypeAliasAsValue(pub(crate) TypeAliasId);
308
309impl ToChalk for TypeAliasAsValue {
310 type Chalk = AssociatedTyValueId;
311
312 fn to_chalk(self, _db: &dyn HirDatabase) -> AssociatedTyValueId {
313 rust_ir::AssociatedTyValueId(self.0.as_intern_id())
314 }
315
316 fn from_chalk(
317 _db: &dyn HirDatabase,
318 assoc_ty_value_id: AssociatedTyValueId,
319 ) -> TypeAliasAsValue {
320 TypeAliasAsValue(TypeAliasId::from_intern_id(assoc_ty_value_id.0))
321 }
322}
323
324impl ToChalk for WhereClause {
325 type Chalk = chalk_ir::WhereClause<Interner>;
326
327 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::WhereClause<Interner> {
328 match self {
329 WhereClause::Implemented(trait_ref) => {
330 chalk_ir::WhereClause::Implemented(trait_ref.to_chalk(db))
331 }
332 WhereClause::AliasEq(alias_eq) => chalk_ir::WhereClause::AliasEq(alias_eq.to_chalk(db)),
333 }
334 }
335
336 fn from_chalk(
337 db: &dyn HirDatabase,
338 where_clause: chalk_ir::WhereClause<Interner>,
339 ) -> WhereClause {
340 match where_clause {
341 chalk_ir::WhereClause::Implemented(tr) => WhereClause::Implemented(from_chalk(db, tr)),
342 chalk_ir::WhereClause::AliasEq(alias_eq) => {
343 WhereClause::AliasEq(from_chalk(db, alias_eq))
344 }
345
346 chalk_ir::WhereClause::LifetimeOutlives(_) => {
347 // we shouldn't get these from Chalk
348 panic!("encountered LifetimeOutlives from Chalk")
349 }
350
351 chalk_ir::WhereClause::TypeOutlives(_) => {
352 // we shouldn't get these from Chalk
353 panic!("encountered TypeOutlives from Chalk")
354 }
355 }
356 }
357}
358
359impl ToChalk for ProjectionTy {
360 type Chalk = chalk_ir::ProjectionTy<Interner>;
361
362 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::ProjectionTy<Interner> {
363 chalk_ir::ProjectionTy {
364 associated_ty_id: self.associated_ty_id,
365 substitution: self.substitution.to_chalk(db),
366 }
367 }
368
369 fn from_chalk(
370 db: &dyn HirDatabase,
371 projection_ty: chalk_ir::ProjectionTy<Interner>,
372 ) -> ProjectionTy {
373 ProjectionTy {
374 associated_ty_id: projection_ty.associated_ty_id,
375 substitution: from_chalk(db, projection_ty.substitution),
376 }
377 }
378}
379impl ToChalk for OpaqueTy {
380 type Chalk = chalk_ir::OpaqueTy<Interner>;
381
382 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
383 chalk_ir::OpaqueTy {
384 opaque_ty_id: self.opaque_ty_id,
385 substitution: self.substitution.to_chalk(db),
386 }
387 }
388
389 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
390 OpaqueTy {
391 opaque_ty_id: chalk.opaque_ty_id,
392 substitution: from_chalk(db, chalk.substitution),
393 }
394 }
395}
396
397impl ToChalk for AliasTy {
398 type Chalk = chalk_ir::AliasTy<Interner>;
399
400 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
401 match self {
402 AliasTy::Projection(projection_ty) => {
403 chalk_ir::AliasTy::Projection(projection_ty.to_chalk(db))
404 }
405 AliasTy::Opaque(opaque_ty) => chalk_ir::AliasTy::Opaque(opaque_ty.to_chalk(db)),
406 }
407 }
408
409 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self {
410 match chalk {
411 chalk_ir::AliasTy::Projection(projection_ty) => {
412 AliasTy::Projection(from_chalk(db, projection_ty))
413 }
414 chalk_ir::AliasTy::Opaque(opaque_ty) => AliasTy::Opaque(from_chalk(db, opaque_ty)),
415 }
416 }
417}
418
419impl ToChalk for AliasEq {
420 type Chalk = chalk_ir::AliasEq<Interner>;
421
422 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::AliasEq<Interner> {
423 chalk_ir::AliasEq { alias: self.alias.to_chalk(db), ty: self.ty.to_chalk(db) }
424 }
425
426 fn from_chalk(db: &dyn HirDatabase, alias_eq: chalk_ir::AliasEq<Interner>) -> Self {
427 AliasEq { alias: from_chalk(db, alias_eq.alias), ty: from_chalk(db, alias_eq.ty) }
428 }
429}
430
431impl ToChalk for DomainGoal {
432 type Chalk = chalk_ir::DomainGoal<Interner>;
433
434 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::DomainGoal<Interner> {
435 match self {
436 DomainGoal::Holds(WhereClause::Implemented(tr)) => tr.to_chalk(db).cast(&Interner),
437 DomainGoal::Holds(WhereClause::AliasEq(alias_eq)) => {
438 alias_eq.to_chalk(db).cast(&Interner)
439 }
440 }
441 }
442
443 fn from_chalk(_db: &dyn HirDatabase, _goal: chalk_ir::DomainGoal<Interner>) -> Self {
444 unimplemented!()
445 }
446}
447
448impl<T> ToChalk for Canonical<T>
449where
450 T: ToChalk,
451 T::Chalk: HasInterner<Interner = Interner>,
452{
453 type Chalk = chalk_ir::Canonical<T::Chalk>;
454
455 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Canonical<T::Chalk> {
456 let value = self.value.to_chalk(db);
457 chalk_ir::Canonical { value, binders: self.binders }
458 }
459
460 fn from_chalk(db: &dyn HirDatabase, canonical: chalk_ir::Canonical<T::Chalk>) -> Canonical<T> {
461 Canonical { binders: canonical.binders, value: from_chalk(db, canonical.value) }
462 }
463}
464
465impl<T: ToChalk> ToChalk for InEnvironment<T>
466where
467 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
468{
469 type Chalk = chalk_ir::InEnvironment<T::Chalk>;
470
471 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::InEnvironment<T::Chalk> {
472 chalk_ir::InEnvironment { environment: self.environment, goal: self.goal.to_chalk(db) }
473 }
474
475 fn from_chalk(
476 _db: &dyn HirDatabase,
477 _in_env: chalk_ir::InEnvironment<T::Chalk>,
478 ) -> InEnvironment<T> {
479 unimplemented!()
480 }
481}
482
483impl<T: ToChalk> ToChalk for crate::Binders<T>
484where
485 T::Chalk: chalk_ir::interner::HasInterner<Interner = Interner>,
486{
487 type Chalk = chalk_ir::Binders<T::Chalk>;
488
489 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Binders<T::Chalk> {
490 let (value, binders) = self.into_value_and_skipped_binders();
491 chalk_ir::Binders::new(binders, value.to_chalk(db))
492 }
493
494 fn from_chalk(db: &dyn HirDatabase, binders: chalk_ir::Binders<T::Chalk>) -> crate::Binders<T> {
495 let (v, b) = binders.into_value_and_skipped_binders();
496 crate::Binders::new(b, from_chalk(db, v))
497 }
498}
499
500pub(super) fn make_binders<T>(value: T, num_vars: usize) -> chalk_ir::Binders<T>
501where
502 T: HasInterner<Interner = Interner>,
503{
504 chalk_ir::Binders::new(
505 chalk_ir::VariableKinds::from_iter(
506 &Interner,
507 std::iter::repeat(chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General))
508 .take(num_vars),
509 ),
510 value,
511 )
512}
513
514pub(super) fn convert_where_clauses(
515 db: &dyn HirDatabase,
516 def: GenericDefId,
517 substs: &Substitution,
518) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
519 let generic_predicates = db.generic_predicates(def);
520 let mut result = Vec::with_capacity(generic_predicates.len());
521 for pred in generic_predicates.iter() {
522 result.push(pred.clone().substitute(&Interner, substs).to_chalk(db));
523 }
524 result
525}
526
527pub(super) fn generic_predicate_to_inline_bound(
528 db: &dyn HirDatabase,
529 pred: &QuantifiedWhereClause,
530 self_ty: &Ty,
531) -> Option<chalk_ir::Binders<rust_ir::InlineBound<Interner>>> {
532 // An InlineBound is like a GenericPredicate, except the self type is left out.
533 // We don't have a special type for this, but Chalk does.
534 let self_ty_shifted_in = self_ty.clone().shifted_in_from(DebruijnIndex::ONE);
535 let (pred, binders) = pred.as_ref().into_value_and_skipped_binders();
536 match pred {
537 WhereClause::Implemented(trait_ref) => {
538 if trait_ref.self_type_parameter(&Interner) != &self_ty_shifted_in {
539 // we can only convert predicates back to type bounds if they
540 // have the expected self type
541 return None;
542 }
543 let args_no_self = trait_ref.substitution.interned()[1..]
544 .iter()
545 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
546 .collect();
547 let trait_bound = rust_ir::TraitBound { trait_id: trait_ref.trait_id, args_no_self };
548 Some(chalk_ir::Binders::new(binders, rust_ir::InlineBound::TraitBound(trait_bound)))
549 }
550 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
551 if projection_ty.self_type_parameter(&Interner) != &self_ty_shifted_in {
552 return None;
553 }
554 let trait_ = projection_ty.trait_(db);
555 let args_no_self = projection_ty.substitution.interned()[1..]
556 .iter()
557 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
558 .collect();
559 let alias_eq_bound = rust_ir::AliasEqBound {
560 value: ty.clone().to_chalk(db),
561 trait_bound: rust_ir::TraitBound { trait_id: trait_.to_chalk(db), args_no_self },
562 associated_ty_id: projection_ty.associated_ty_id,
563 parameters: Vec::new(), // FIXME we don't support generic associated types yet
564 };
565 Some(chalk_ir::Binders::new(
566 binders,
567 rust_ir::InlineBound::AliasEqBound(alias_eq_bound),
568 ))
569 }
570 _ => None,
571 }
572}
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
deleted file mode 100644
index 46c705a76..000000000
--- a/crates/hir_ty/src/types.rs
+++ /dev/null
@@ -1,475 +0,0 @@
1//! This is the home of `Ty` etc. until they get replaced by their chalk_ir
2//! equivalents.
3
4use std::sync::Arc;
5
6use chalk_ir::{
7 cast::{CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind,
9};
10use hir_def::LifetimeParamId;
11use smallvec::SmallVec;
12
13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKinds,
16};
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
19pub enum Lifetime {
20 Parameter(LifetimeParamId),
21 Static,
22}
23
24#[derive(Clone, PartialEq, Eq, Debug, Hash)]
25pub struct OpaqueTy {
26 pub opaque_ty_id: OpaqueTyId,
27 pub substitution: Substitution,
28}
29
30/// A "projection" type corresponds to an (unnormalized)
31/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
32/// trait and all its parameters are fully known.
33#[derive(Clone, PartialEq, Eq, Debug, Hash)]
34pub struct ProjectionTy {
35 pub associated_ty_id: AssocTypeId,
36 pub substitution: Substitution,
37}
38
39#[derive(Clone, PartialEq, Eq, Debug, Hash)]
40pub struct DynTy {
41 /// The unknown self type.
42 pub bounds: Binders<QuantifiedWhereClauses>,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug, Hash)]
46pub struct FnPointer {
47 pub num_args: usize,
48 pub sig: FnSig,
49 pub substs: Substitution,
50}
51
52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
53pub enum AliasTy {
54 /// A "projection" type corresponds to an (unnormalized)
55 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
56 /// trait and all its parameters are fully known.
57 Projection(ProjectionTy),
58 /// An opaque type (`impl Trait`).
59 ///
60 /// This is currently only used for return type impl trait; each instance of
61 /// `impl Trait` in a return type gets its own ID.
62 Opaque(OpaqueTy),
63}
64
65/// A type.
66///
67/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
68/// the same thing (but in a different way).
69///
70/// This should be cheap to clone.
71#[derive(Clone, PartialEq, Eq, Debug, Hash)]
72pub enum TyKind {
73 /// Structures, enumerations and unions.
74 Adt(chalk_ir::AdtId<Interner>, Substitution),
75
76 /// Represents an associated item like `Iterator::Item`. This is used
77 /// when we have tried to normalize a projection like `T::Item` but
78 /// couldn't find a better representation. In that case, we generate
79 /// an **application type** like `(Iterator::Item)<T>`.
80 AssociatedType(AssocTypeId, Substitution),
81
82 /// a scalar type like `bool` or `u32`
83 Scalar(Scalar),
84
85 /// A tuple type. For example, `(i32, bool)`.
86 Tuple(usize, Substitution),
87
88 /// An array with the given length. Written as `[T; n]`.
89 Array(Ty),
90
91 /// The pointee of an array slice. Written as `[T]`.
92 Slice(Ty),
93
94 /// A raw pointer. Written as `*mut T` or `*const T`
95 Raw(Mutability, Ty),
96
97 /// A reference; a pointer with an associated lifetime. Written as
98 /// `&'a mut T` or `&'a T`.
99 Ref(Mutability, Ty),
100
101 /// This represents a placeholder for an opaque type in situations where we
102 /// don't know the hidden type (i.e. currently almost always). This is
103 /// analogous to the `AssociatedType` type constructor.
104 /// It is also used as the type of async block, with one type parameter
105 /// representing the Future::Output type.
106 OpaqueType(OpaqueTyId, Substitution),
107
108 /// The anonymous type of a function declaration/definition. Each
109 /// function has a unique type, which is output (for a function
110 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
111 ///
112 /// This includes tuple struct / enum variant constructors as well.
113 ///
114 /// For example the type of `bar` here:
115 ///
116 /// ```
117 /// fn foo() -> i32 { 1 }
118 /// let bar = foo; // bar: fn() -> i32 {foo}
119 /// ```
120 FnDef(FnDefId, Substitution),
121
122 /// The pointee of a string slice. Written as `str`.
123 Str,
124
125 /// The never type `!`.
126 Never,
127
128 /// The type of a specific closure.
129 ///
130 /// The closure signature is stored in a `FnPtr` type in the first type
131 /// parameter.
132 Closure(ClosureId, Substitution),
133
134 /// Represents a foreign type declared in external blocks.
135 Foreign(ForeignDefId),
136
137 /// A pointer to a function. Written as `fn() -> i32`.
138 ///
139 /// For example the type of `bar` here:
140 ///
141 /// ```
142 /// fn foo() -> i32 { 1 }
143 /// let bar: fn() -> i32 = foo;
144 /// ```
145 Function(FnPointer),
146
147 /// An "alias" type represents some form of type alias, such as:
148 /// - An associated type projection like `<T as Iterator>::Item`
149 /// - `impl Trait` types
150 /// - Named type aliases like `type Foo<X> = Vec<X>`
151 Alias(AliasTy),
152
153 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
154 /// {}` when we're type-checking the body of that function. In this
155 /// situation, we know this stands for *some* type, but don't know the exact
156 /// type.
157 Placeholder(PlaceholderIndex),
158
159 /// A bound type variable. This is used in various places: when representing
160 /// some polymorphic type like the type of function `fn f<T>`, the type
161 /// parameters get turned into variables; during trait resolution, inference
162 /// variables get turned into bound variables and back; and in `Dyn` the
163 /// `Self` type is represented with a bound variable as well.
164 BoundVar(BoundVar),
165
166 /// A type variable used during type checking.
167 InferenceVar(InferenceVar, TyVariableKind),
168
169 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
170 ///
171 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
172 /// represents the `Self` type inside the bounds. This is currently
173 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
174 /// didn't seem worth the overhead yet.
175 Dyn(DynTy),
176
177 /// A placeholder for a type which could not be computed; this is propagated
178 /// to avoid useless error messages. Doubles as a placeholder where type
179 /// variables are inserted before type checking, since we want to try to
180 /// infer a better type here anyway -- for the IDE use case, we want to try
181 /// to infer as much as possible even in the presence of type errors.
182 Error,
183}
184
185#[derive(Clone, PartialEq, Eq, Debug, Hash)]
186pub struct Ty(Arc<TyKind>);
187
188impl TyKind {
189 pub fn intern(self, _interner: &Interner) -> Ty {
190 Ty(Arc::new(self))
191 }
192}
193
194impl Ty {
195 pub fn kind(&self, _interner: &Interner) -> &TyKind {
196 &self.0
197 }
198
199 pub fn interned_mut(&mut self) -> &mut TyKind {
200 Arc::make_mut(&mut self.0)
201 }
202
203 pub fn into_inner(self) -> TyKind {
204 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
205 }
206}
207
208#[derive(Clone, PartialEq, Eq, Debug, Hash)]
209pub struct GenericArg {
210 interned: GenericArgData,
211}
212
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub enum GenericArgData {
215 Ty(Ty),
216}
217
218impl GenericArg {
219 /// Constructs a generic argument using `GenericArgData`.
220 pub fn new(_interner: &Interner, data: GenericArgData) -> Self {
221 GenericArg { interned: data }
222 }
223
224 /// Gets the interned value.
225 pub fn interned(&self) -> &GenericArgData {
226 &self.interned
227 }
228
229 /// Asserts that this is a type argument.
230 pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty {
231 self.ty(interner).unwrap()
232 }
233
234 /// Checks whether the generic argument is a type.
235 pub fn is_ty(&self, _interner: &Interner) -> bool {
236 match self.interned() {
237 GenericArgData::Ty(_) => true,
238 }
239 }
240
241 /// Returns the type if it is one, `None` otherwise.
242 pub fn ty(&self, _interner: &Interner) -> Option<&Ty> {
243 match self.interned() {
244 GenericArgData::Ty(t) => Some(t),
245 }
246 }
247
248 pub fn interned_mut(&mut self) -> &mut GenericArgData {
249 &mut self.interned
250 }
251}
252
253/// A list of substitutions for generic parameters.
254#[derive(Clone, PartialEq, Eq, Debug, Hash)]
255pub struct Substitution(SmallVec<[GenericArg; 2]>);
256
257impl Substitution {
258 pub fn interned(&self) -> &[GenericArg] {
259 &self.0
260 }
261
262 pub fn len(&self, _: &Interner) -> usize {
263 self.0.len()
264 }
265
266 pub fn is_empty(&self, _: &Interner) -> bool {
267 self.0.is_empty()
268 }
269
270 pub fn at(&self, _: &Interner, i: usize) -> &GenericArg {
271 &self.0[i]
272 }
273
274 pub fn empty(_: &Interner) -> Substitution {
275 Substitution(SmallVec::new())
276 }
277
278 pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> {
279 self.0.iter()
280 }
281
282 pub fn from_iter(
283 interner: &Interner,
284 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
285 ) -> Self {
286 Substitution(elements.into_iter().casted(interner).collect())
287 }
288
289 pub fn apply<T: TypeWalk>(&self, value: T, _interner: &Interner) -> T {
290 value.subst_bound_vars(self)
291 }
292
293 // Temporary helper functions, to be removed
294 pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution {
295 Substitution(interned)
296 }
297
298 pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> {
299 &mut self.0
300 }
301}
302
303#[derive(Clone, PartialEq, Eq, Hash)]
304pub struct Binders<T> {
305 /// The binders that quantify over the value.
306 pub binders: VariableKinds,
307 value: T,
308}
309
310impl<T> Binders<T> {
311 pub fn new(binders: VariableKinds, value: T) -> Self {
312 Self { binders, value }
313 }
314
315 pub fn empty(_interner: &Interner, value: T) -> Self {
316 crate::make_only_type_binders(0, value)
317 }
318
319 pub fn as_ref(&self) -> Binders<&T> {
320 Binders { binders: self.binders.clone(), value: &self.value }
321 }
322
323 pub fn map<U>(self, f: impl FnOnce(T) -> U) -> Binders<U> {
324 Binders { binders: self.binders, value: f(self.value) }
325 }
326
327 pub fn filter_map<U>(self, f: impl FnOnce(T) -> Option<U>) -> Option<Binders<U>> {
328 Some(Binders { binders: self.binders, value: f(self.value)? })
329 }
330
331 pub fn skip_binders(&self) -> &T {
332 &self.value
333 }
334
335 pub fn into_value_and_skipped_binders(self) -> (T, VariableKinds) {
336 (self.value, self.binders)
337 }
338
339 /// Returns the number of binders.
340 pub fn len(&self, interner: &Interner) -> usize {
341 self.binders.len(interner)
342 }
343
344 // Temporary helper function, to be removed
345 pub fn skip_binders_mut(&mut self) -> &mut T {
346 &mut self.value
347 }
348}
349
350impl<T: Clone> Binders<&T> {
351 pub fn cloned(&self) -> Binders<T> {
352 Binders::new(self.binders.clone(), self.value.clone())
353 }
354}
355
356impl<T: std::fmt::Debug> std::fmt::Debug for Binders<T> {
357 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
358 let Binders { ref binders, ref value } = *self;
359 write!(fmt, "for{:?} ", binders.inner_debug(&Interner))?;
360 std::fmt::Debug::fmt(value, fmt)
361 }
362}
363
364/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
365#[derive(Clone, PartialEq, Eq, Debug, Hash)]
366pub struct TraitRef {
367 pub trait_id: ChalkTraitId,
368 pub substitution: Substitution,
369}
370
371/// Like `generics::WherePredicate`, but with resolved types: A condition on the
372/// parameters of a generic item.
373#[derive(Debug, Clone, PartialEq, Eq, Hash)]
374pub enum WhereClause {
375 /// The given trait needs to be implemented for its type parameters.
376 Implemented(TraitRef),
377 /// An associated type bindings like in `Iterator<Item = T>`.
378 AliasEq(AliasEq),
379}
380
381pub type QuantifiedWhereClause = Binders<WhereClause>;
382
383#[derive(Debug, Clone, PartialEq, Eq, Hash)]
384pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
385
386impl QuantifiedWhereClauses {
387 pub fn from_iter(
388 _interner: &Interner,
389 elements: impl IntoIterator<Item = QuantifiedWhereClause>,
390 ) -> Self {
391 QuantifiedWhereClauses(elements.into_iter().collect())
392 }
393
394 pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
395 &self.0
396 }
397
398 pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> {
399 &mut self.0
400 }
401}
402
403/// Basically a claim (currently not validated / checked) that the contained
404/// type / trait ref contains no inference variables; any inference variables it
405/// contained have been replaced by bound variables, and `kinds` tells us how
406/// many there are and whether they were normal or float/int variables. This is
407/// used to erase irrelevant differences between types before using them in
408/// queries.
409#[derive(Debug, Clone, PartialEq, Eq, Hash)]
410pub struct Canonical<T> {
411 pub value: T,
412 pub binders: CanonicalVarKinds,
413}
414
415/// Something (usually a goal), along with an environment.
416#[derive(Clone, Debug, PartialEq, Eq, Hash)]
417pub struct InEnvironment<T> {
418 pub environment: chalk_ir::Environment<Interner>,
419 pub goal: T,
420}
421
422impl<T> InEnvironment<T> {
423 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
424 InEnvironment { environment, goal: value }
425 }
426}
427
428/// Something that needs to be proven (by Chalk) during type checking, e.g. that
429/// a certain type implements a certain trait. Proving the Obligation might
430/// result in additional information about inference variables.
431#[derive(Clone, Debug, PartialEq, Eq, Hash)]
432pub enum DomainGoal {
433 Holds(WhereClause),
434}
435
436#[derive(Clone, Debug, PartialEq, Eq, Hash)]
437pub struct AliasEq {
438 pub alias: AliasTy,
439 pub ty: Ty,
440}
441
442#[derive(Clone, Debug, PartialEq, Eq)]
443pub struct SolutionVariables(pub Canonical<Substitution>);
444
445#[derive(Clone, Debug, PartialEq, Eq)]
446/// A (possible) solution for a proposed goal.
447pub enum Solution {
448 /// The goal indeed holds, and there is a unique value for all existential
449 /// variables.
450 Unique(SolutionVariables),
451
452 /// The goal may be provable in multiple ways, but regardless we may have some guidance
453 /// for type inference. In this case, we don't return any lifetime
454 /// constraints, since we have not "committed" to any particular solution
455 /// yet.
456 Ambig(Guidance),
457}
458
459#[derive(Clone, Debug, PartialEq, Eq)]
460/// When a goal holds ambiguously (e.g., because there are multiple possible
461/// solutions), we issue a set of *guidance* back to type inference.
462pub enum Guidance {
463 /// The existential variables *must* have the given values if the goal is
464 /// ever to hold, but that alone isn't enough to guarantee the goal will
465 /// actually hold.
466 Definite(SolutionVariables),
467
468 /// There are multiple plausible values for the existentials, but the ones
469 /// here are suggested as the preferred choice heuristically. These should
470 /// be used for inference fallback only.
471 Suggested(SolutionVariables),
472
473 /// There's no useful information to feed back to type inference
474 Unknown,
475}
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index d11708299..5f6cb052a 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -1,10 +1,8 @@
1//! Helper functions for working with def, which don't need to be a separate 1//! Helper functions for working with def, which don't need to be a separate
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3use std::sync::Arc;
4 3
5use chalk_ir::{BoundVar, DebruijnIndex}; 4use chalk_ir::{fold::Shift, BoundVar, DebruijnIndex};
6use hir_def::{ 5use hir_def::{
7 adt::VariantData,
8 db::DefDatabase, 6 db::DefDatabase,
9 generics::{ 7 generics::{
10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, 8 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
@@ -13,11 +11,11 @@ use hir_def::{
13 path::Path, 11 path::Path,
14 resolver::{HasResolver, TypeNs}, 12 resolver::{HasResolver, TypeNs},
15 type_ref::TypeRef, 13 type_ref::TypeRef,
16 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId, VariantId, 14 AssocContainerId, GenericDefId, Lookup, TraitId, TypeAliasId, TypeParamId,
17}; 15};
18use hir_expand::name::{name, Name}; 16use hir_expand::name::{name, Name};
19 17
20use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause}; 18use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TraitRefExt, TyKind, WhereClause};
21 19
22fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 20fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
23 let resolver = trait_.resolver(db); 21 let resolver = trait_.resolver(db);
@@ -68,7 +66,7 @@ fn direct_super_trait_refs(db: &dyn HirDatabase, trait_ref: &TraitRef) -> Vec<Tr
68 // FIXME: how to correctly handle higher-ranked bounds here? 66 // FIXME: how to correctly handle higher-ranked bounds here?
69 WhereClause::Implemented(tr) => Some( 67 WhereClause::Implemented(tr) => Some(
70 tr.clone() 68 tr.clone()
71 .shifted_out_to(DebruijnIndex::ONE) 69 .shifted_out_to(&Interner, DebruijnIndex::ONE)
72 .expect("FIXME unexpected higher-ranked trait bound"), 70 .expect("FIXME unexpected higher-ranked trait bound"),
73 ), 71 ),
74 _ => None, 72 _ => None,
@@ -136,25 +134,6 @@ pub(super) fn associated_type_by_name_including_super_traits(
136 }) 134 })
137} 135}
138 136
139pub(super) fn variant_data(db: &dyn DefDatabase, var: VariantId) -> Arc<VariantData> {
140 match var {
141 VariantId::StructId(it) => db.struct_data(it).variant_data.clone(),
142 VariantId::UnionId(it) => db.union_data(it).variant_data.clone(),
143 VariantId::EnumVariantId(it) => {
144 db.enum_data(it.parent).variants[it.local_id].variant_data.clone()
145 }
146 }
147}
148
149/// Helper for mutating `Arc<[T]>` (i.e. `Arc::make_mut` for Arc slices).
150/// The underlying values are cloned if there are other strong references.
151pub(crate) fn make_mut_slice<T: Clone>(a: &mut Arc<[T]>) -> &mut [T] {
152 if Arc::get_mut(a).is_none() {
153 *a = a.iter().cloned().collect();
154 }
155 Arc::get_mut(a).unwrap()
156}
157
158pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { 137pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
159 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def))); 138 let parent_generics = parent_generic_def(db, def).map(|def| Box::new(generics(db, def)));
160 Generics { def, params: db.generic_params(def), parent_generics } 139 Generics { def, params: db.generic_params(def), parent_generics }
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
index b85e6ab4d..6ef1d5336 100644
--- a/crates/hir_ty/src/walk.rs
+++ b/crates/hir_ty/src/walk.rs
@@ -1,130 +1,17 @@
1//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and 1//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and
2//! `Visit`). 2//! `Visit`).
3 3
4use std::mem; 4use chalk_ir::interner::HasInterner;
5
6use chalk_ir::DebruijnIndex;
7 5
8use crate::{ 6use crate::{
9 utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, GenericArg, GenericArgData, 7 AliasEq, AliasTy, Binders, CallableSig, FnSubst, GenericArg, GenericArgData, Interner,
10 Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, 8 OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause,
11}; 9};
12 10
13/// This allows walking structures that contain types to do something with those 11/// This allows walking structures that contain types to do something with those
14/// types, similar to Chalk's `Fold` trait. 12/// types, similar to Chalk's `Fold` trait.
15pub trait TypeWalk { 13pub trait TypeWalk {
16 fn walk(&self, f: &mut impl FnMut(&Ty)); 14 fn walk(&self, f: &mut impl FnMut(&Ty));
17 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
18 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
19 }
20 /// Walk the type, counting entered binders.
21 ///
22 /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
23 /// to the innermost binder, 1 to the next, etc.. So when we want to
24 /// substitute a certain bound variable, we can't just walk the whole type
25 /// and blindly replace each instance of a certain index; when we 'enter'
26 /// things that introduce new bound variables, we have to keep track of
27 /// that. Currently, the only thing that introduces bound variables on our
28 /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
29 /// variable for the self type.
30 fn walk_mut_binders(
31 &mut self,
32 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
33 binders: DebruijnIndex,
34 );
35
36 fn fold_binders(
37 mut self,
38 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
39 binders: DebruijnIndex,
40 ) -> Self
41 where
42 Self: Sized,
43 {
44 self.walk_mut_binders(
45 &mut |ty_mut, binders| {
46 let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
47 *ty_mut = f(ty, binders);
48 },
49 binders,
50 );
51 self
52 }
53
54 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
55 where
56 Self: Sized,
57 {
58 self.walk_mut(&mut |ty_mut| {
59 let ty = mem::replace(ty_mut, TyKind::Error.intern(&Interner));
60 *ty_mut = f(ty);
61 });
62 self
63 }
64
65 /// Substitutes `TyKind::Bound` vars with the given substitution.
66 fn subst_bound_vars(self, substs: &Substitution) -> Self
67 where
68 Self: Sized,
69 {
70 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
71 }
72
73 /// Substitutes `TyKind::Bound` vars with the given substitution.
74 fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self
75 where
76 Self: Sized,
77 {
78 self.walk_mut_binders(
79 &mut |ty, binders| {
80 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
81 if bound.debruijn >= binders {
82 *ty = substs.interned()[bound.index]
83 .assert_ty_ref(&Interner)
84 .clone()
85 .shifted_in_from(binders);
86 }
87 }
88 },
89 depth,
90 );
91 self
92 }
93
94 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
95 fn shifted_in_from(self, n: DebruijnIndex) -> Self
96 where
97 Self: Sized,
98 {
99 self.fold_binders(
100 &mut |ty, binders| match ty.kind(&Interner) {
101 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
102 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
103 }
104 _ => ty,
105 },
106 DebruijnIndex::INNERMOST,
107 )
108 }
109
110 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
111 fn shifted_out_to(self, n: DebruijnIndex) -> Option<Self>
112 where
113 Self: Sized + std::fmt::Debug,
114 {
115 Some(self.fold_binders(
116 &mut |ty, binders| {
117 match ty.kind(&Interner) {
118 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
119 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
120 .intern(&Interner)
121 }
122 _ => ty,
123 }
124 },
125 DebruijnIndex::INNERMOST,
126 ))
127 }
128} 15}
129 16
130impl TypeWalk for Ty { 17impl TypeWalk for Ty {
@@ -145,47 +32,26 @@ impl TypeWalk for Ty {
145 p.walk(f); 32 p.walk(f);
146 } 33 }
147 } 34 }
148 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { 35 TyKind::Slice(ty)
36 | TyKind::Array(ty, _)
37 | TyKind::Ref(_, _, ty)
38 | TyKind::Raw(_, ty) => {
149 ty.walk(f); 39 ty.walk(f);
150 } 40 }
151 _ => { 41 TyKind::Function(fn_pointer) => {
152 if let Some(substs) = self.substs() { 42 fn_pointer.substitution.0.walk(f);
153 for t in substs.iter(&Interner) {
154 t.walk(f);
155 }
156 }
157 }
158 }
159 f(self);
160 }
161
162 fn walk_mut_binders(
163 &mut self,
164 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
165 binders: DebruijnIndex,
166 ) {
167 match self.interned_mut() {
168 TyKind::Alias(AliasTy::Projection(p_ty)) => {
169 p_ty.substitution.walk_mut_binders(f, binders);
170 }
171 TyKind::Dyn(dyn_ty) => {
172 for p in make_mut_slice(dyn_ty.bounds.skip_binders_mut().interned_mut()) {
173 p.walk_mut_binders(f, binders.shifted_in());
174 }
175 }
176 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
177 o_ty.substitution.walk_mut_binders(f, binders);
178 } 43 }
179 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { 44 TyKind::Adt(_, substs)
180 ty.walk_mut_binders(f, binders); 45 | TyKind::FnDef(_, substs)
181 } 46 | TyKind::Tuple(_, substs)
182 _ => { 47 | TyKind::OpaqueType(_, substs)
183 if let Some(substs) = self.substs_mut() { 48 | TyKind::AssociatedType(_, substs)
184 substs.walk_mut_binders(f, binders); 49 | TyKind::Closure(.., substs) => {
185 } 50 substs.walk(f);
186 } 51 }
52 _ => {}
187 } 53 }
188 f(self, binders); 54 f(self);
189 } 55 }
190} 56}
191 57
@@ -195,43 +61,18 @@ impl<T: TypeWalk> TypeWalk for Vec<T> {
195 t.walk(f); 61 t.walk(f);
196 } 62 }
197 } 63 }
198 fn walk_mut_binders(
199 &mut self,
200 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
201 binders: DebruijnIndex,
202 ) {
203 for t in self {
204 t.walk_mut_binders(f, binders);
205 }
206 }
207} 64}
208 65
209impl TypeWalk for OpaqueTy { 66impl TypeWalk for OpaqueTy {
210 fn walk(&self, f: &mut impl FnMut(&Ty)) { 67 fn walk(&self, f: &mut impl FnMut(&Ty)) {
211 self.substitution.walk(f); 68 self.substitution.walk(f);
212 } 69 }
213
214 fn walk_mut_binders(
215 &mut self,
216 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
217 binders: DebruijnIndex,
218 ) {
219 self.substitution.walk_mut_binders(f, binders);
220 }
221} 70}
222 71
223impl TypeWalk for ProjectionTy { 72impl TypeWalk for ProjectionTy {
224 fn walk(&self, f: &mut impl FnMut(&Ty)) { 73 fn walk(&self, f: &mut impl FnMut(&Ty)) {
225 self.substitution.walk(f); 74 self.substitution.walk(f);
226 } 75 }
227
228 fn walk_mut_binders(
229 &mut self,
230 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
231 binders: DebruijnIndex,
232 ) {
233 self.substitution.walk_mut_binders(f, binders);
234 }
235} 76}
236 77
237impl TypeWalk for AliasTy { 78impl TypeWalk for AliasTy {
@@ -241,17 +82,6 @@ impl TypeWalk for AliasTy {
241 AliasTy::Opaque(it) => it.walk(f), 82 AliasTy::Opaque(it) => it.walk(f),
242 } 83 }
243 } 84 }
244
245 fn walk_mut_binders(
246 &mut self,
247 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
248 binders: DebruijnIndex,
249 ) {
250 match self {
251 AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
252 AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
253 }
254 }
255} 85}
256 86
257impl TypeWalk for GenericArg { 87impl TypeWalk for GenericArg {
@@ -260,18 +90,7 @@ impl TypeWalk for GenericArg {
260 GenericArgData::Ty(ty) => { 90 GenericArgData::Ty(ty) => {
261 ty.walk(f); 91 ty.walk(f);
262 } 92 }
263 } 93 _ => {}
264 }
265
266 fn walk_mut_binders(
267 &mut self,
268 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
269 binders: DebruijnIndex,
270 ) {
271 match self.interned_mut() {
272 GenericArgData::Ty(ty) => {
273 ty.walk_mut_binders(f, binders);
274 }
275 } 94 }
276 } 95 }
277} 96}
@@ -282,44 +101,18 @@ impl TypeWalk for Substitution {
282 t.walk(f); 101 t.walk(f);
283 } 102 }
284 } 103 }
285
286 fn walk_mut_binders(
287 &mut self,
288 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
289 binders: DebruijnIndex,
290 ) {
291 for t in self.interned_mut() {
292 t.walk_mut_binders(f, binders);
293 }
294 }
295} 104}
296 105
297impl<T: TypeWalk> TypeWalk for Binders<T> { 106impl<T: TypeWalk + HasInterner<Interner = Interner>> TypeWalk for Binders<T> {
298 fn walk(&self, f: &mut impl FnMut(&Ty)) { 107 fn walk(&self, f: &mut impl FnMut(&Ty)) {
299 self.skip_binders().walk(f); 108 self.skip_binders().walk(f);
300 } 109 }
301
302 fn walk_mut_binders(
303 &mut self,
304 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
305 binders: DebruijnIndex,
306 ) {
307 self.skip_binders_mut().walk_mut_binders(f, binders.shifted_in())
308 }
309} 110}
310 111
311impl TypeWalk for TraitRef { 112impl TypeWalk for TraitRef {
312 fn walk(&self, f: &mut impl FnMut(&Ty)) { 113 fn walk(&self, f: &mut impl FnMut(&Ty)) {
313 self.substitution.walk(f); 114 self.substitution.walk(f);
314 } 115 }
315
316 fn walk_mut_binders(
317 &mut self,
318 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
319 binders: DebruijnIndex,
320 ) {
321 self.substitution.walk_mut_binders(f, binders);
322 }
323} 116}
324 117
325impl TypeWalk for WhereClause { 118impl TypeWalk for WhereClause {
@@ -327,17 +120,7 @@ impl TypeWalk for WhereClause {
327 match self { 120 match self {
328 WhereClause::Implemented(trait_ref) => trait_ref.walk(f), 121 WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
329 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), 122 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
330 } 123 _ => {}
331 }
332
333 fn walk_mut_binders(
334 &mut self,
335 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
336 binders: DebruijnIndex,
337 ) {
338 match self {
339 WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
340 WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
341 } 124 }
342 } 125 }
343} 126}
@@ -348,16 +131,6 @@ impl TypeWalk for CallableSig {
348 t.walk(f); 131 t.walk(f);
349 } 132 }
350 } 133 }
351
352 fn walk_mut_binders(
353 &mut self,
354 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
355 binders: DebruijnIndex,
356 ) {
357 for t in make_mut_slice(&mut self.params_and_return) {
358 t.walk_mut_binders(f, binders);
359 }
360 }
361} 134}
362 135
363impl TypeWalk for AliasEq { 136impl TypeWalk for AliasEq {
@@ -368,16 +141,10 @@ impl TypeWalk for AliasEq {
368 AliasTy::Opaque(opaque) => opaque.walk(f), 141 AliasTy::Opaque(opaque) => opaque.walk(f),
369 } 142 }
370 } 143 }
144}
371 145
372 fn walk_mut_binders( 146impl TypeWalk for FnSubst<Interner> {
373 &mut self, 147 fn walk(&self, f: &mut impl FnMut(&Ty)) {
374 f: &mut impl FnMut(&mut Ty, DebruijnIndex), 148 self.0.walk(f)
375 binders: DebruijnIndex,
376 ) {
377 self.ty.walk_mut_binders(f, binders);
378 match &mut self.alias {
379 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
380 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
381 }
382 } 149 }
383} 150}