aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/Cargo.toml2
-rw-r--r--crates/hir_ty/src/autoderef.rs105
-rw-r--r--crates/hir_ty/src/builder.rs223
-rw-r--r--crates/hir_ty/src/chalk_cast.rs53
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)276
-rw-r--r--crates/hir_ty/src/chalk_ext.rs305
-rw-r--r--crates/hir_ty/src/db.rs87
-rw-r--r--crates/hir_ty/src/diagnostics.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs174
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs24
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs49
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs12
-rw-r--r--crates/hir_ty/src/display.rs321
-rw-r--r--crates/hir_ty/src/infer.rs198
-rw-r--r--crates/hir_ty/src/infer/coerce.rs64
-rw-r--r--crates/hir_ty/src/infer/expr.rs221
-rw-r--r--crates/hir_ty/src/infer/pat.rs92
-rw-r--r--crates/hir_ty/src/infer/path.rs39
-rw-r--r--crates/hir_ty/src/infer/unify.rs266
-rw-r--r--crates/hir_ty/src/interner.rs (renamed from crates/hir_ty/src/traits/chalk/interner.rs)170
-rw-r--r--crates/hir_ty/src/lib.rs1347
-rw-r--r--crates/hir_ty/src/lower.rs340
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs316
-rw-r--r--crates/hir_ty/src/op.rs74
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/tests/macros.rs28
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/tests/patterns.rs28
-rw-r--r--crates/hir_ty/src/tests/regression.rs38
-rw-r--r--crates/hir_ty/src/tests/simple.rs51
-rw-r--r--crates/hir_ty/src/tests/traits.rs1504
-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.rs140
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs560
-rw-r--r--crates/hir_ty/src/utils.rs73
-rw-r--r--crates/hir_ty/src/walk.rs150
38 files changed, 3677 insertions, 3852 deletions
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 030b7eebe..abc0e7532 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -12,7 +12,7 @@ doctest = false
12[dependencies] 12[dependencies]
13cov-mark = { version = "1.1", features = ["thread-local"] } 13cov-mark = { version = "1.1", features = ["thread-local"] }
14itertools = "0.10.0" 14itertools = "0.10.0"
15arrayvec = "0.6" 15arrayvec = "0.7"
16smallvec = "1.2.0" 16smallvec = "1.2.0"
17ena = "0.14.0" 17ena = "0.14.0"
18log = "0.4.8" 18log = "0.4.8"
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index dc5fc759a..2c07494a9 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,18 +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, 15 db::HirDatabase, static_lifetime, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds,
16 to_assoc_type_id, to_chalk_trait_id, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 traits::{InEnvironment, Solution}, 17 TyKind,
18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 18};
22 19
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -39,39 +36,48 @@ pub(crate) fn deref(
39 krate: CrateId, 36 krate: CrateId,
40 ty: InEnvironment<&Canonical<Ty>>, 37 ty: InEnvironment<&Canonical<Ty>>,
41) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
42 if let Some(derefed) = ty.goal.value.builtin_deref() { 39 let _p = profile::span("deref");
40 if let Some(derefed) = builtin_deref(&ty.goal.value) {
43 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 41 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
44 } else { 42 } else {
45 deref_by_trait(db, krate, ty) 43 deref_by_trait(db, krate, ty)
46 } 44 }
47} 45}
48 46
47fn builtin_deref(ty: &Ty) -> Option<Ty> {
48 match ty.kind(&Interner) {
49 TyKind::Ref(.., ty) => Some(ty.clone()),
50 TyKind::Raw(.., ty) => Some(ty.clone()),
51 _ => None,
52 }
53}
54
49fn deref_by_trait( 55fn deref_by_trait(
50 db: &dyn HirDatabase, 56 db: &dyn HirDatabase,
51 krate: CrateId, 57 krate: CrateId,
52 ty: InEnvironment<&Canonical<Ty>>, 58 ty: InEnvironment<&Canonical<Ty>>,
53) -> Option<Canonical<Ty>> { 59) -> Option<Canonical<Ty>> {
60 let _p = profile::span("deref_by_trait");
54 let deref_trait = match db.lang_item(krate, "deref".into())? { 61 let deref_trait = match db.lang_item(krate, "deref".into())? {
55 LangItemTarget::TraitId(it) => it, 62 LangItemTarget::TraitId(it) => it,
56 _ => return None, 63 _ => return None,
57 }; 64 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 65 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 66
60 let generic_params = generics(db.upcast(), target.into()); 67 let projection = {
61 if generic_params.len() != 1 { 68 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 69 if b.remaining() != 1 {
63 // namely Deref's Self type 70 // the Target type + Deref trait should only have one generic parameter,
64 return None; 71 // namely Deref's Self type
65 } 72 return None;
73 }
74 b.push(ty.goal.value.clone()).build()
75 };
66 76
67 // FIXME make the Canonical / bound var handling nicer 77 // FIXME make the Canonical / bound var handling nicer
68 78
69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71
72 // Check that the type implements Deref at all 79 // Check that the type implements Deref at all
73 let trait_ref = 80 let trait_ref = projection.trait_ref(db);
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 81 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 82 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 83 value: InEnvironment {
@@ -84,11 +90,8 @@ fn deref_by_trait(
84 } 90 }
85 91
86 // Now do the assoc type projection 92 // Now do the assoc type projection
87 let projection = AliasEq { 93 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 94 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 95 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 96 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 97 ty.goal.binders.len(&Interner),
@@ -96,16 +99,14 @@ fn deref_by_trait(
96 .intern(&Interner), 99 .intern(&Interner),
97 }; 100 };
98 101
99 let obligation = projection.cast(&Interner); 102 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 103
103 let canonical = Canonical { 104 let canonical = Canonical {
104 value: in_env, 105 value: in_env,
105 binders: CanonicalVarKinds::from_iter( 106 binders: CanonicalVarKinds::from_iter(
106 &Interner, 107 &Interner,
107 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new( 108 ty.goal.binders.iter(&Interner).cloned().chain(Some(chalk_ir::WithKind::new(
108 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 109 VariableKind::Ty(chalk_ir::TyVariableKind::General),
109 chalk_ir::UniverseIndex::ROOT, 110 chalk_ir::UniverseIndex::ROOT,
110 ))), 111 ))),
111 ), 112 ),
@@ -130,18 +131,25 @@ fn deref_by_trait(
130 // assumptions will be broken. We would need to properly introduce 131 // assumptions will be broken. We would need to properly introduce
131 // new variables in that case 132 // new variables in that case
132 133
133 for i in 1..vars.0.binders.len(&Interner) { 134 for i in 1..vars.binders.len(&Interner) {
134 if vars.0.value[i - 1].interned(&Interner) 135 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 136 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
136 { 137 {
137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 138 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
138 return None; 139 return None;
139 } 140 }
140 } 141 }
141 Some(Canonical { 142 // FIXME: we remove lifetime variables here since they can confuse
142 value: vars.0.value[vars.0.value.len() - 1].clone(), 143 // the method resolution code later
143 binders: vars.0.binders.clone(), 144 Some(fixup_lifetime_variables(Canonical {
144 }) 145 value: vars
146 .value
147 .subst
148 .at(&Interner, vars.value.subst.len(&Interner) - 1)
149 .assert_ty_ref(&Interner)
150 .clone(),
151 binders: vars.binders.clone(),
152 }))
145 } 153 }
146 Solution::Ambig(_) => { 154 Solution::Ambig(_) => {
147 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 155 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -149,3 +157,32 @@ fn deref_by_trait(
149 } 157 }
150 } 158 }
151} 159}
160
161fn fixup_lifetime_variables<T: Fold<Interner, Result = T> + HasInterner<Interner = Interner>>(
162 c: Canonical<T>,
163) -> Canonical<T> {
164 // Removes lifetime variables from the Canonical, replacing them by static lifetimes.
165 let mut i = 0;
166 let subst = Substitution::from_iter(
167 &Interner,
168 c.binders.iter(&Interner).map(|vk| match vk.kind {
169 VariableKind::Ty(_) => {
170 let index = i;
171 i += 1;
172 BoundVar::new(DebruijnIndex::INNERMOST, index).to_ty(&Interner).cast(&Interner)
173 }
174 VariableKind::Lifetime => static_lifetime().cast(&Interner),
175 VariableKind::Const(_) => unimplemented!(),
176 }),
177 );
178 let binders = CanonicalVarKinds::from_iter(
179 &Interner,
180 c.binders.iter(&Interner).filter(|vk| match vk.kind {
181 VariableKind::Ty(_) => true,
182 VariableKind::Lifetime => false,
183 VariableKind::Const(_) => true,
184 }),
185 );
186 let value = subst.apply(c.value, &Interner);
187 Canonical { binders, value }
188}
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
new file mode 100644
index 000000000..e25ef866d
--- /dev/null
+++ b/crates/hir_ty/src/builder.rs
@@ -0,0 +1,223 @@
1//! `TyBuilder`, a helper for building instances of `Ty` and related types.
2
3use std::iter;
4
5use chalk_ir::{
6 cast::{Cast, CastTo, Caster},
7 fold::Fold,
8 interner::HasInterner,
9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
10};
11use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
12use smallvec::SmallVec;
13
14use crate::{
15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
18};
19
20/// This is a builder for `Ty` or anything that needs a `Substitution`.
21pub struct TyBuilder<D> {
22 /// The `data` field is used to keep track of what we're building (e.g. an
23 /// ADT, a `TraitRef`, ...).
24 data: D,
25 vec: SmallVec<[GenericArg; 2]>,
26 param_count: usize,
27}
28
29impl<D> TyBuilder<D> {
30 fn new(data: D, param_count: usize) -> TyBuilder<D> {
31 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
32 }
33
34 fn build_internal(self) -> (D, Substitution) {
35 assert_eq!(self.vec.len(), self.param_count);
36 let subst = Substitution::from_iter(&Interner, self.vec);
37 (self.data, subst)
38 }
39
40 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
41 self.vec.push(arg.cast(&Interner));
42 self
43 }
44
45 pub fn remaining(&self) -> usize {
46 self.param_count - self.vec.len()
47 }
48
49 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
50 self.fill(
51 (starting_from..)
52 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
53 )
54 }
55
56 pub fn fill_with_unknown(self) -> Self {
57 self.fill(iter::repeat(TyKind::Error.intern(&Interner)))
58 }
59
60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
61 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
62 assert_eq!(self.remaining(), 0);
63 self
64 }
65
66 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
67 assert!(self.vec.is_empty());
68 assert!(parent_substs.len(&Interner) <= self.param_count);
69 self.vec.extend(parent_substs.iter(&Interner).cloned());
70 self
71 }
72}
73
74impl TyBuilder<()> {
75 pub fn unit() -> Ty {
76 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
77 }
78
79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer {
81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
87 })
88 .intern(&Interner)
89 }
90
91 pub fn builtin(builtin: BuiltinType) -> Ty {
92 match builtin {
93 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
94 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
95 BuiltinType::Str => TyKind::Str.intern(&Interner),
96 BuiltinType::Int(t) => {
97 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
98 }
99 BuiltinType::Uint(t) => {
100 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
101 }
102 BuiltinType::Float(t) => {
103 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
104 }
105 }
106 }
107
108 pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
109 let params = generics(db.upcast(), def.into());
110 params.type_params_subst(db)
111 }
112
113 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
114 let def = def.into();
115 let params = generics(db.upcast(), def);
116 let param_count = params.len();
117 TyBuilder::new((), param_count)
118 }
119
120 pub fn build(self) -> Substitution {
121 let ((), subst) = self.build_internal();
122 subst
123 }
124}
125
126impl TyBuilder<hir_def::AdtId> {
127 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
128 let generics = generics(db.upcast(), adt.into());
129 let param_count = generics.len();
130 TyBuilder::new(adt, param_count)
131 }
132
133 pub fn fill_with_defaults(
134 mut self,
135 db: &dyn HirDatabase,
136 mut fallback: impl FnMut() -> Ty,
137 ) -> Self {
138 let defaults = db.generic_defaults(self.data.into());
139 for default_ty in defaults.iter().skip(self.vec.len()) {
140 if default_ty.skip_binders().is_unknown() {
141 self.vec.push(fallback().cast(&Interner));
142 } else {
143 // each default can depend on the previous parameters
144 let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
145 self.vec
146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
147 }
148 }
149 self
150 }
151
152 pub fn build(self) -> Ty {
153 let (adt, subst) = self.build_internal();
154 TyKind::Adt(AdtId(adt), subst).intern(&Interner)
155 }
156}
157
158pub struct Tuple(usize);
159impl TyBuilder<Tuple> {
160 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
161 TyBuilder::new(Tuple(size), size)
162 }
163
164 pub fn build(self) -> Ty {
165 let (Tuple(size), subst) = self.build_internal();
166 TyKind::Tuple(size, subst).intern(&Interner)
167 }
168}
169
170impl TyBuilder<TraitId> {
171 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
172 let generics = generics(db.upcast(), trait_id.into());
173 let param_count = generics.len();
174 TyBuilder::new(trait_id, param_count)
175 }
176
177 pub fn build(self) -> TraitRef {
178 let (trait_id, substitution) = self.build_internal();
179 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
180 }
181}
182
183impl TyBuilder<TypeAliasId> {
184 pub fn assoc_type_projection(
185 db: &dyn HirDatabase,
186 type_alias: TypeAliasId,
187 ) -> TyBuilder<TypeAliasId> {
188 let generics = generics(db.upcast(), type_alias.into());
189 let param_count = generics.len();
190 TyBuilder::new(type_alias, param_count)
191 }
192
193 pub fn build(self) -> ProjectionTy {
194 let (type_alias, substitution) = self.build_internal();
195 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
196 }
197}
198
199impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
200 fn subst_binders(b: Binders<T>) -> Self {
201 let param_count = b.binders.len(&Interner);
202 TyBuilder::new(b, param_count)
203 }
204
205 pub fn build(self) -> <T as Fold<Interner>>::Result {
206 let (b, subst) = self.build_internal();
207 b.substitute(&Interner, &subst)
208 }
209}
210
211impl TyBuilder<Binders<Ty>> {
212 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
213 TyBuilder::subst_binders(db.ty(def.into()))
214 }
215
216 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
217 TyBuilder::subst_binders(db.impl_self_ty(def))
218 }
219
220 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
221 TyBuilder::subst_binders(db.value_ty(def))
222 }
223}
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index bf884ae15..000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,53 +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, Interner, TraitRef, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20
21impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause {
23 WhereClause::Implemented(self)
24 }
25}
26
27impl CastTo<WhereClause> for AliasEq {
28 fn cast_to(self, _interner: &Interner) -> WhereClause {
29 WhereClause::AliasEq(self)
30 }
31}
32
33impl CastTo<DomainGoal> for WhereClause {
34 fn cast_to(self, _interner: &Interner) -> DomainGoal {
35 DomainGoal::Holds(self)
36 }
37}
38
39macro_rules! transitive_impl {
40 ($a:ty, $b:ty, $c:ty) => {
41 impl CastTo<$c> for $a {
42 fn cast_to(self, interner: &Interner) -> $c {
43 self.cast::<$b>(interner).cast(interner)
44 }
45 }
46 };
47}
48
49// In Chalk, these can be done as blanket impls, but that doesn't work here
50// because of coherence
51
52transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_impl!(AliasEq, WhereClause, DomainGoal);
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/chalk_db.rs
index 011bef6f6..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, GenericArg}; 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, 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> {
@@ -80,19 +75,19 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
80 fn impls_for_trait( 75 fn impls_for_trait(
81 &self, 76 &self,
82 trait_id: TraitId, 77 trait_id: TraitId,
83 parameters: &[GenericArg<Interner>], 78 parameters: &[chalk_ir::GenericArg<Interner>],
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,
93 binders: &CanonicalVarKinds<Interner>, 88 binders: &CanonicalVarKinds<Interner>,
94 ) -> Option<chalk_ir::TyVariableKind> { 89 ) -> Option<chalk_ir::TyVariableKind> {
95 if let TyKind::BoundVar(bv) = ty.interned(&Interner) { 90 if let TyKind::BoundVar(bv) = ty.kind(&Interner) {
96 let binders = binders.as_slice(&Interner); 91 let binders = binders.as_slice(&Interner);
97 if bv.debruijn == DebruijnIndex::INNERMOST { 92 if bv.debruijn == DebruijnIndex::INNERMOST {
98 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind { 93 if let chalk_ir::VariableKind::Ty(tk) = binders[bv.index].kind {
@@ -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(
@@ -184,16 +179,16 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
184 .db 179 .db
185 .return_type_impl_traits(func) 180 .return_type_impl_traits(func)
186 .expect("impl trait id without impl traits"); 181 .expect("impl trait id without impl traits");
187 let data = &datas.value.impl_traits[idx as usize]; 182 let (datas, binders) = (*datas).as_ref().into_value_and_skipped_binders();
183 let data = &datas.impl_traits[idx as usize];
188 let bound = OpaqueTyDatumBound { 184 let bound = OpaqueTyDatumBound {
189 bounds: make_binders( 185 bounds: make_only_type_binders(
190 data.bounds.value.iter().cloned().map(|b| b.to_chalk(self.db)).collect(),
191 1, 186 1,
187 data.bounds.skip_binders().iter().cloned().collect(),
192 ), 188 ),
193 where_clauses: make_binders(vec![], 0), 189 where_clauses: make_only_type_binders(0, vec![]),
194 }; 190 };
195 let num_vars = datas.num_binders; 191 chalk_ir::Binders::new(binders, bound)
196 make_binders(bound, num_vars)
197 } 192 }
198 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => { 193 crate::ImplTraitId::AsyncBlockTypeImplTrait(..) => {
199 if let Some((future_trait, future_output)) = self 194 if let Some((future_trait, future_output)) = self
@@ -215,7 +210,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
215 let impl_bound = WhereClause::Implemented(TraitRef { 210 let impl_bound = WhereClause::Implemented(TraitRef {
216 trait_id: to_chalk_trait_id(future_trait), 211 trait_id: to_chalk_trait_id(future_trait),
217 // Self type as the first parameter. 212 // Self type as the first parameter.
218 substitution: Substitution::single( 213 substitution: Substitution::from1(
214 &Interner,
219 TyKind::BoundVar(BoundVar { 215 TyKind::BoundVar(BoundVar {
220 debruijn: DebruijnIndex::INNERMOST, 216 debruijn: DebruijnIndex::INNERMOST,
221 index: 0, 217 index: 0,
@@ -227,7 +223,8 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
227 alias: AliasTy::Projection(ProjectionTy { 223 alias: AliasTy::Projection(ProjectionTy {
228 associated_ty_id: to_assoc_type_id(future_output), 224 associated_ty_id: to_assoc_type_id(future_output),
229 // Self type as the first parameter. 225 // Self type as the first parameter.
230 substitution: Substitution::single( 226 substitution: Substitution::from1(
227 &Interner,
231 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 228 TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
232 .intern(&Interner), 229 .intern(&Interner),
233 ), 230 ),
@@ -237,25 +234,25 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
237 .intern(&Interner), 234 .intern(&Interner),
238 }); 235 });
239 let bound = OpaqueTyDatumBound { 236 let bound = OpaqueTyDatumBound {
240 bounds: make_binders( 237 bounds: make_only_type_binders(
238 1,
241 vec![ 239 vec![
242 wrap_in_empty_binders(impl_bound).to_chalk(self.db), 240 crate::wrap_empty_binders(impl_bound),
243 wrap_in_empty_binders(proj_bound).to_chalk(self.db), 241 crate::wrap_empty_binders(proj_bound),
244 ], 242 ],
245 1,
246 ), 243 ),
247 where_clauses: make_binders(vec![], 0), 244 where_clauses: make_only_type_binders(0, vec![]),
248 }; 245 };
249 // The opaque type has 1 parameter. 246 // The opaque type has 1 parameter.
250 make_binders(bound, 1) 247 make_only_type_binders(1, bound)
251 } else { 248 } else {
252 // 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.
253 let bound = OpaqueTyDatumBound { 250 let bound = OpaqueTyDatumBound {
254 bounds: make_binders(vec![], 0), 251 bounds: make_only_type_binders(0, vec![]),
255 where_clauses: make_binders(vec![], 0), 252 where_clauses: make_only_type_binders(0, vec![]),
256 }; 253 };
257 // The opaque type has 1 parameter. 254 // The opaque type has 1 parameter.
258 make_binders(bound, 1) 255 make_only_type_binders(1, bound)
259 } 256 }
260 } 257 }
261 }; 258 };
@@ -265,7 +262,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
265 262
266 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> {
267 // 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
268 TyKind::Unknown.intern(&Interner).to_chalk(self.db) 265 TyKind::Error.intern(&Interner)
269 } 266 }
270 267
271 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 {
@@ -286,33 +283,32 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
286 _closure_id: chalk_ir::ClosureId<Interner>, 283 _closure_id: chalk_ir::ClosureId<Interner>,
287 substs: &chalk_ir::Substitution<Interner>, 284 substs: &chalk_ir::Substitution<Interner>,
288 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> { 285 ) -> chalk_ir::Binders<rust_ir::FnDefInputsAndOutputDatum<Interner>> {
289 let sig_ty: Ty = 286 let sig_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
290 from_chalk(self.db, substs.at(&Interner, 0).assert_ty_ref(&Interner).clone());
291 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");
292 let io = rust_ir::FnDefInputsAndOutputDatum { 288 let io = rust_ir::FnDefInputsAndOutputDatum {
293 argument_types: sig.params().iter().map(|ty| ty.clone().to_chalk(self.db)).collect(), 289 argument_types: sig.params().iter().cloned().collect(),
294 return_type: sig.ret().clone().to_chalk(self.db), 290 return_type: sig.ret().clone(),
295 }; 291 };
296 make_binders(io.shifted_in(&Interner), 0) 292 make_only_type_binders(0, io.shifted_in(&Interner))
297 } 293 }
298 fn closure_upvars( 294 fn closure_upvars(
299 &self, 295 &self,
300 _closure_id: chalk_ir::ClosureId<Interner>, 296 _closure_id: chalk_ir::ClosureId<Interner>,
301 _substs: &chalk_ir::Substitution<Interner>, 297 _substs: &chalk_ir::Substitution<Interner>,
302 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 298 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
303 let ty = Ty::unit().to_chalk(self.db); 299 let ty = TyBuilder::unit();
304 make_binders(ty, 0) 300 make_only_type_binders(0, ty)
305 } 301 }
306 fn closure_fn_substitution( 302 fn closure_fn_substitution(
307 &self, 303 &self,
308 _closure_id: chalk_ir::ClosureId<Interner>, 304 _closure_id: chalk_ir::ClosureId<Interner>,
309 _substs: &chalk_ir::Substitution<Interner>, 305 _substs: &chalk_ir::Substitution<Interner>,
310 ) -> chalk_ir::Substitution<Interner> { 306 ) -> chalk_ir::Substitution<Interner> {
311 Substitution::empty().to_chalk(self.db) 307 Substitution::empty(&Interner)
312 } 308 }
313 309
314 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String { 310 fn trait_name(&self, trait_id: chalk_ir::TraitId<Interner>) -> String {
315 let id = from_chalk(self.db, trait_id); 311 let id = from_chalk_trait_id(trait_id);
316 self.db.trait_data(id).name.to_string() 312 self.db.trait_data(id).name.to_string()
317 } 313 }
318 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String { 314 fn adt_name(&self, chalk_ir::AdtId(adt_id): AdtId) -> String {
@@ -387,7 +383,7 @@ pub(crate) fn associated_ty_data_query(
387 // Lower bounds -- we could/should maybe move this to a separate query in `lower` 383 // Lower bounds -- we could/should maybe move this to a separate query in `lower`
388 let type_alias_data = db.type_alias_data(type_alias); 384 let type_alias_data = db.type_alias_data(type_alias);
389 let generic_params = generics(db.upcast(), type_alias.into()); 385 let generic_params = generics(db.upcast(), type_alias.into());
390 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 386 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); 387 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
392 let ctx = crate::TyLoweringContext::new(db, &resolver) 388 let ctx = crate::TyLoweringContext::new(db, &resolver)
393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); 389 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
@@ -403,10 +399,10 @@ pub(crate) fn associated_ty_data_query(
403 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);
404 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses }; 400 let bound_data = rust_ir::AssociatedTyDatumBound { bounds, where_clauses };
405 let datum = AssociatedTyDatum { 401 let datum = AssociatedTyDatum {
406 trait_id: trait_.to_chalk(db), 402 trait_id: to_chalk_trait_id(trait_),
407 id, 403 id,
408 name: type_alias, 404 name: type_alias,
409 binders: make_binders(bound_data, generic_params.len()), 405 binders: make_only_type_binders(generic_params.len(), bound_data),
410 }; 406 };
411 Arc::new(datum) 407 Arc::new(datum)
412} 408}
@@ -417,11 +413,11 @@ pub(crate) fn trait_datum_query(
417 trait_id: TraitId, 413 trait_id: TraitId,
418) -> Arc<TraitDatum> { 414) -> Arc<TraitDatum> {
419 debug!("trait_datum {:?}", trait_id); 415 debug!("trait_datum {:?}", trait_id);
420 let trait_: hir_def::TraitId = from_chalk(db, trait_id); 416 let trait_ = from_chalk_trait_id(trait_id);
421 let trait_data = db.trait_data(trait_); 417 let trait_data = db.trait_data(trait_);
422 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 418 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
423 let generic_params = generics(db.upcast(), trait_.into()); 419 let generic_params = generics(db.upcast(), trait_.into());
424 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 420 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
425 let flags = rust_ir::TraitFlags { 421 let flags = rust_ir::TraitFlags {
426 auto: trait_data.is_auto, 422 auto: trait_data.is_auto,
427 upstream: trait_.lookup(db.upcast()).container.krate() != krate, 423 upstream: trait_.lookup(db.upcast()).container.krate() != krate,
@@ -439,7 +435,7 @@ pub(crate) fn trait_datum_query(
439 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));
440 let trait_datum = TraitDatum { 436 let trait_datum = TraitDatum {
441 id: trait_id, 437 id: trait_id,
442 binders: make_binders(trait_datum_bound, bound_vars.len()), 438 binders: make_only_type_binders(bound_vars.len(&Interner), trait_datum_bound),
443 flags, 439 flags,
444 associated_ty_ids, 440 associated_ty_ids,
445 well_known, 441 well_known,
@@ -490,7 +486,7 @@ pub(crate) fn struct_datum_query(
490 let upstream = adt_id.module(db.upcast()).krate() != krate; 486 let upstream = adt_id.module(db.upcast()).krate() != krate;
491 let where_clauses = { 487 let where_clauses = {
492 let generic_params = generics(db.upcast(), adt_id.into()); 488 let generic_params = generics(db.upcast(), adt_id.into());
493 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 489 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
494 convert_where_clauses(db, adt_id.into(), &bound_vars) 490 convert_where_clauses(db, adt_id.into(), &bound_vars)
495 }; 491 };
496 let flags = rust_ir::AdtFlags { 492 let flags = rust_ir::AdtFlags {
@@ -508,7 +504,7 @@ pub(crate) fn struct_datum_query(
508 // FIXME set ADT kind 504 // FIXME set ADT kind
509 kind: rust_ir::AdtKind::Struct, 505 kind: rust_ir::AdtKind::Struct,
510 id: struct_id, 506 id: struct_id,
511 binders: make_binders(struct_datum_bound, num_params), 507 binders: make_only_type_binders(num_params, struct_datum_bound),
512 flags, 508 flags,
513 }; 509 };
514 Arc::new(struct_datum) 510 Arc::new(struct_datum)
@@ -535,11 +531,12 @@ fn impl_def_datum(
535 .impl_trait(impl_id) 531 .impl_trait(impl_id)
536 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk 532 // ImplIds for impls where the trait ref can't be resolved should never reach Chalk
537 .expect("invalid impl passed to Chalk") 533 .expect("invalid impl passed to Chalk")
538 .value; 534 .into_value_and_skipped_binders()
535 .0;
539 let impl_data = db.impl_data(impl_id); 536 let impl_data = db.impl_data(impl_id);
540 537
541 let generic_params = generics(db.upcast(), impl_id.into()); 538 let generic_params = generics(db.upcast(), impl_id.into());
542 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 539 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
543 let trait_ = trait_ref.hir_trait_id(); 540 let trait_ = trait_ref.hir_trait_id();
544 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { 541 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
545 rust_ir::ImplType::Local 542 rust_ir::ImplType::Local
@@ -555,7 +552,6 @@ fn impl_def_datum(
555 trait_ref.display(db), 552 trait_ref.display(db),
556 where_clauses 553 where_clauses
557 ); 554 );
558 let trait_ref = trait_ref.to_chalk(db);
559 555
560 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 };
561 557
@@ -577,7 +573,7 @@ fn impl_def_datum(
577 .collect(); 573 .collect();
578 debug!("impl_datum: {:?}", impl_datum_bound); 574 debug!("impl_datum: {:?}", impl_datum_bound);
579 let impl_datum = ImplDatum { 575 let impl_datum = ImplDatum {
580 binders: make_binders(impl_datum_bound, bound_vars.len()), 576 binders: make_only_type_binders(bound_vars.len(&Interner), impl_datum_bound),
581 impl_type, 577 impl_type,
582 polarity, 578 polarity,
583 associated_ty_value_ids, 579 associated_ty_value_ids,
@@ -605,18 +601,22 @@ fn type_alias_associated_ty_value(
605 _ => panic!("assoc ty value should be in impl"), 601 _ => panic!("assoc ty value should be in impl"),
606 }; 602 };
607 603
608 let trait_ref = db.impl_trait(impl_id).expect("assoc ty value should not exist").value; // we don't return any assoc ty values if the impl'd trait can't be resolved 604 let trait_ref = db
605 .impl_trait(impl_id)
606 .expect("assoc ty value should not exist")
607 .into_value_and_skipped_binders()
608 .0; // we don't return any assoc ty values if the impl'd trait can't be resolved
609 609
610 let assoc_ty = db 610 let assoc_ty = db
611 .trait_data(trait_ref.hir_trait_id()) 611 .trait_data(trait_ref.hir_trait_id())
612 .associated_type_by_name(&type_alias_data.name) 612 .associated_type_by_name(&type_alias_data.name)
613 .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
614 let ty = db.ty(type_alias.into()); 614 let (ty, binders) = db.ty(type_alias.into()).into_value_and_skipped_binders();
615 let value_bound = rust_ir::AssociatedTyValueBound { ty: ty.value.to_chalk(db) }; 615 let value_bound = rust_ir::AssociatedTyValueBound { ty };
616 let value = rust_ir::AssociatedTyValue { 616 let value = rust_ir::AssociatedTyValue {
617 impl_id: impl_id.to_chalk(db), 617 impl_id: impl_id.to_chalk(db),
618 associated_ty_id: to_assoc_type_id(assoc_ty), 618 associated_ty_id: to_assoc_type_id(assoc_ty),
619 value: make_binders(value_bound, ty.num_binders), 619 value: chalk_ir::Binders::new(binders, value_bound),
620 }; 620 };
621 Arc::new(value) 621 Arc::new(value)
622} 622}
@@ -628,34 +628,25 @@ pub(crate) fn fn_def_datum_query(
628) -> Arc<FnDefDatum> { 628) -> Arc<FnDefDatum> {
629 let callable_def: CallableDefId = from_chalk(db, fn_def_id); 629 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
630 let generic_params = generics(db.upcast(), callable_def.into()); 630 let generic_params = generics(db.upcast(), callable_def.into());
631 let sig = db.callable_item_signature(callable_def); 631 let (sig, binders) = db.callable_item_signature(callable_def).into_value_and_skipped_binders();
632 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 632 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
633 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);
634 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
635 // 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
636 inputs_and_output: make_binders( 636 inputs_and_output: make_only_type_binders(
637 0,
637 rust_ir::FnDefInputsAndOutputDatum { 638 rust_ir::FnDefInputsAndOutputDatum {
638 argument_types: sig 639 argument_types: sig.params().iter().cloned().collect(),
639 .value 640 return_type: sig.ret().clone(),
640 .params()
641 .iter()
642 .map(|ty| ty.clone().to_chalk(db))
643 .collect(),
644 return_type: sig.value.ret().clone().to_chalk(db),
645 } 641 }
646 .shifted_in(&Interner), 642 .shifted_in(&Interner),
647 0,
648 ), 643 ),
649 where_clauses, 644 where_clauses,
650 }; 645 };
651 let datum = FnDefDatum { 646 let datum = FnDefDatum {
652 id: fn_def_id, 647 id: fn_def_id,
653 sig: chalk_ir::FnSig { 648 sig: chalk_ir::FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: sig.is_varargs },
654 abi: (), 649 binders: chalk_ir::Binders::new(binders, bound),
655 safety: chalk_ir::Safety::Safe,
656 variadic: sig.value.is_varargs,
657 },
658 binders: make_binders(bound, sig.num_binders),
659 }; 650 };
660 Arc::new(datum) 651 Arc::new(datum)
661} 652}
@@ -685,42 +676,65 @@ pub(crate) fn adt_variance_query(
685 ) 676 )
686} 677}
687 678
688impl From<FnDefId> for crate::db::InternedCallableDefId { 679pub(super) fn convert_where_clauses(
689 fn from(fn_def_id: FnDefId) -> Self { 680 db: &dyn HirDatabase,
690 InternKey::from_intern_id(fn_def_id.0) 681 def: GenericDefId,
691 } 682 substs: &Substitution,
692} 683) -> Vec<chalk_ir::QuantifiedWhereClause<Interner>> {
693 684 let generic_predicates = db.generic_predicates(def);
694impl From<crate::db::InternedCallableDefId> for FnDefId { 685 let mut result = Vec::with_capacity(generic_predicates.len());
695 fn from(callable_def_id: crate::db::InternedCallableDefId) -> Self { 686 for pred in generic_predicates.iter() {
696 chalk_ir::FnDefId(callable_def_id.as_intern_id()) 687 result.push(pred.clone().substitute(&Interner, substs));
697 } 688 }
698} 689 result
699
700impl From<OpaqueTyId> for crate::db::InternedOpaqueTyId {
701 fn from(id: OpaqueTyId) -> Self {
702 InternKey::from_intern_id(id.0)
703 }
704}
705
706impl From<crate::db::InternedOpaqueTyId> for OpaqueTyId {
707 fn from(id: crate::db::InternedOpaqueTyId) -> Self {
708 chalk_ir::OpaqueTyId(id.as_intern_id())
709 }
710}
711
712impl From<chalk_ir::ClosureId<Interner>> for crate::db::InternedClosureId {
713 fn from(id: chalk_ir::ClosureId<Interner>) -> Self {
714 Self::from_intern_id(id.0)
715 }
716} 690}
717 691
718impl From<crate::db::InternedClosureId> for chalk_ir::ClosureId<Interner> { 692pub(super) fn generic_predicate_to_inline_bound(
719 fn from(id: crate::db::InternedClosureId) -> Self { 693 db: &dyn HirDatabase,
720 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,
721 } 739 }
722} 740}
723
724fn wrap_in_empty_binders<T: crate::TypeWalk>(value: T) -> crate::Binders<T> {
725 crate::Binders::wrap_empty(value)
726}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
new file mode 100644
index 000000000..8c4542956
--- /dev/null
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -0,0 +1,305 @@
1//! Various extensions traits for Chalk types.
2
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};
14
15pub trait TyExt {
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;
40}
41
42impl TyExt for Ty {
43 fn is_unit(&self) -> bool {
44 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
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 }
305}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 58e4247c6..cf67d4266 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,51 +87,68 @@ 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(trait_solve_wait)]
132 #[salsa::transparent]
122 fn trait_solve( 133 fn trait_solve(
123 &self, 134 &self,
124 krate: CrateId, 135 krate: CrateId,
125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 136 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
126 ) -> Option<crate::traits::Solution>; 137 ) -> Option<crate::Solution>;
127 138
128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 139 #[salsa::invoke(crate::traits::trait_solve_query)]
140 fn trait_solve_query(
141 &self,
142 krate: CrateId,
143 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
144 ) -> Option<crate::Solution>;
145
146 #[salsa::invoke(chalk_db::program_clauses_for_chalk_env_query)]
129 fn program_clauses_for_chalk_env( 147 fn program_clauses_for_chalk_env(
130 &self, 148 &self,
131 krate: CrateId, 149 krate: CrateId,
132 env: chalk_ir::Environment<chalk::Interner>, 150 env: chalk_ir::Environment<Interner>,
133 ) -> chalk_ir::ProgramClauses<chalk::Interner>; 151 ) -> chalk_ir::ProgramClauses<Interner>;
134} 152}
135 153
136fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> { 154fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult> {
@@ -146,6 +164,15 @@ fn infer_wait(db: &dyn HirDatabase, def: DefWithBodyId) -> Arc<InferenceResult>
146 db.infer_query(def) 164 db.infer_query(def)
147} 165}
148 166
167fn trait_solve_wait(
168 db: &dyn HirDatabase,
169 krate: CrateId,
170 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
171) -> Option<crate::Solution> {
172 let _p = profile::span("trait_solve::wait");
173 db.trait_solve_query(krate, goal)
174}
175
149#[test] 176#[test]
150fn hir_database_is_object_safe() { 177fn hir_database_is_object_safe() {
151 fn _assert_object_safe(_: &dyn HirDatabase) {} 178 fn _assert_object_safe(_: &dyn HirDatabase) {}
@@ -156,6 +183,14 @@ pub struct InternedTypeParamId(salsa::InternId);
156impl_intern_key!(InternedTypeParamId); 183impl_intern_key!(InternedTypeParamId);
157 184
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 185#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
186pub struct InternedLifetimeParamId(salsa::InternId);
187impl_intern_key!(InternedLifetimeParamId);
188
189#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
190pub struct InternedConstParamId(salsa::InternId);
191impl_intern_key!(InternedConstParamId);
192
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub struct InternedOpaqueTyId(salsa::InternId); 194pub struct InternedOpaqueTyId(salsa::InternId);
160impl_intern_key!(InternedOpaqueTyId); 195impl_intern_key!(InternedOpaqueTyId);
161 196
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/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 33a0f4d7d..075dc4131 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -35,6 +35,8 @@ use crate::{
35}; 35};
36 36
37mod allow { 37mod allow {
38 pub(super) const BAD_STYLE: &str = "bad_style";
39 pub(super) const NONSTANDARD_STYLE: &str = "nonstandard_style";
38 pub(super) const NON_SNAKE_CASE: &str = "non_snake_case"; 40 pub(super) const NON_SNAKE_CASE: &str = "non_snake_case";
39 pub(super) const NON_UPPER_CASE_GLOBAL: &str = "non_upper_case_globals"; 41 pub(super) const NON_UPPER_CASE_GLOBAL: &str = "non_upper_case_globals";
40 pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types"; 42 pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
@@ -83,15 +85,44 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
83 } 85 }
84 86
85 /// Checks whether not following the convention is allowed for this item. 87 /// Checks whether not following the convention is allowed for this item.
86 /// 88 fn allowed(&self, id: AttrDefId, allow_name: &str, recursing: bool) -> bool {
87 /// Currently this method doesn't check parent attributes. 89 let is_allowed = |def_id| {
88 fn allowed(&self, id: AttrDefId, allow_name: &str) -> bool { 90 let attrs = self.db.attrs(def_id);
89 self.db.attrs(id).by_key("allow").tt_values().any(|tt| tt.to_string().contains(allow_name)) 91 // don't bug the user about directly no_mangle annotated stuff, they can't do anything about it
92 (!recursing && attrs.by_key("no_mangle").exists())
93 || attrs.by_key("allow").tt_values().any(|tt| {
94 let allows = tt.to_string();
95 allows.contains(allow_name)
96 || allows.contains(allow::BAD_STYLE)
97 || allows.contains(allow::NONSTANDARD_STYLE)
98 })
99 };
100
101 is_allowed(id)
102 // go upwards one step or give up
103 || match id {
104 AttrDefId::ModuleId(m) => m.containing_module(self.db.upcast()).map(|v| v.into()),
105 AttrDefId::FunctionId(f) => Some(f.lookup(self.db.upcast()).container.into()),
106 AttrDefId::StaticId(sid) => Some(sid.lookup(self.db.upcast()).container.into()),
107 AttrDefId::ConstId(cid) => Some(cid.lookup(self.db.upcast()).container.into()),
108 AttrDefId::TraitId(tid) => Some(tid.lookup(self.db.upcast()).container.into()),
109 AttrDefId::ImplId(iid) => Some(iid.lookup(self.db.upcast()).container.into()),
110 // These warnings should not explore macro definitions at all
111 AttrDefId::MacroDefId(_) => None,
112 // Will never occur under an enum/struct/union/type alias
113 AttrDefId::AdtId(_) => None,
114 AttrDefId::FieldId(_) => None,
115 AttrDefId::EnumVariantId(_) => None,
116 AttrDefId::TypeAliasId(_) => None,
117 AttrDefId::GenericParamId(_) => None,
118 }
119 .map(|mid| self.allowed(mid, allow_name, true))
120 .unwrap_or(false)
90 } 121 }
91 122
92 fn validate_func(&mut self, func: FunctionId) { 123 fn validate_func(&mut self, func: FunctionId) {
93 let data = self.db.function_data(func); 124 let data = self.db.function_data(func);
94 if data.is_in_extern_block { 125 if data.is_in_extern_block() {
95 cov_mark::hit!(extern_func_incorrect_case_ignored); 126 cov_mark::hit!(extern_func_incorrect_case_ignored);
96 return; 127 return;
97 } 128 }
@@ -99,8 +130,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
99 let body = self.db.body(func.into()); 130 let body = self.db.body(func.into());
100 131
101 // Recursively validate inner scope items, such as static variables and constants. 132 // Recursively validate inner scope items, such as static variables and constants.
102 let db = self.db; 133 for (_, block_def_map) in body.blocks(self.db.upcast()) {
103 for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
104 for (_, module) in block_def_map.modules() { 134 for (_, module) in block_def_map.modules() {
105 for def_id in module.scope.declarations() { 135 for def_id in module.scope.declarations() {
106 let mut validator = DeclValidator::new(self.db, self.krate, self.sink); 136 let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
@@ -110,7 +140,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
110 } 140 }
111 141
112 // Check whether non-snake case identifiers are allowed for this function. 142 // Check whether non-snake case identifiers are allowed for this function.
113 if self.allowed(func.into(), allow::NON_SNAKE_CASE) { 143 if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
114 return; 144 return;
115 } 145 }
116 146
@@ -329,8 +359,9 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
329 fn validate_struct(&mut self, struct_id: StructId) { 359 fn validate_struct(&mut self, struct_id: StructId) {
330 let data = self.db.struct_data(struct_id); 360 let data = self.db.struct_data(struct_id);
331 361
332 let non_camel_case_allowed = self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES); 362 let non_camel_case_allowed =
333 let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE); 363 self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES, false);
364 let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE, false);
334 365
335 // Check the structure name. 366 // Check the structure name.
336 let struct_name = data.name.to_string(); 367 let struct_name = data.name.to_string();
@@ -462,7 +493,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
462 let data = self.db.enum_data(enum_id); 493 let data = self.db.enum_data(enum_id);
463 494
464 // Check whether non-camel case names are allowed for this enum. 495 // Check whether non-camel case names are allowed for this enum.
465 if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES) { 496 if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
466 return; 497 return;
467 } 498 }
468 499
@@ -585,7 +616,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
585 fn validate_const(&mut self, const_id: ConstId) { 616 fn validate_const(&mut self, const_id: ConstId) {
586 let data = self.db.const_data(const_id); 617 let data = self.db.const_data(const_id);
587 618
588 if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL) { 619 if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
589 return; 620 return;
590 } 621 }
591 622
@@ -633,7 +664,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
633 return; 664 return;
634 } 665 }
635 666
636 if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL) { 667 if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
637 return; 668 return;
638 } 669 }
639 670
@@ -868,23 +899,116 @@ fn main() {
868 fn allow_attributes() { 899 fn allow_attributes() {
869 check_diagnostics( 900 check_diagnostics(
870 r#" 901 r#"
871 #[allow(non_snake_case)] 902#[allow(non_snake_case)]
872 fn NonSnakeCaseName(SOME_VAR: u8) -> u8{ 903fn NonSnakeCaseName(SOME_VAR: u8) -> u8{
873 let OtherVar = SOME_VAR + 1; 904 // cov_flags generated output from elsewhere in this file
874 OtherVar 905 extern "C" {
906 #[no_mangle]
907 static lower_case: u8;
875 } 908 }
876 909
877 #[allow(non_snake_case, non_camel_case_types)] 910 let OtherVar = SOME_VAR + 1;
878 pub struct some_type { 911 OtherVar
879 SOME_FIELD: u8, 912}
880 SomeField: u16, 913
914#[allow(nonstandard_style)]
915mod CheckNonstandardStyle {
916 fn HiImABadFnName() {}
917}
918
919#[allow(bad_style)]
920mod CheckBadStyle {
921 fn HiImABadFnName() {}
922}
923
924mod F {
925 #![allow(non_snake_case)]
926 fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {}
927}
928
929#[allow(non_snake_case, non_camel_case_types)]
930pub struct some_type {
931 SOME_FIELD: u8,
932 SomeField: u16,
933}
934
935#[allow(non_upper_case_globals)]
936pub const some_const: u8 = 10;
937
938#[allow(non_upper_case_globals)]
939pub static SomeStatic: u8 = 10;
940 "#,
941 );
881 } 942 }
882 943
883 #[allow(non_upper_case_globals)] 944 #[test]
884 pub const some_const: u8 = 10; 945 fn allow_attributes_crate_attr() {
946 check_diagnostics(
947 r#"
948#![allow(non_snake_case)]
885 949
886 #[allow(non_upper_case_globals)] 950mod F {
887 pub static SomeStatic: u8 = 10; 951 fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {}
952}
953 "#,
954 );
955 }
956
957 #[test]
958 #[ignore]
959 fn bug_trait_inside_fn() {
960 // FIXME:
961 // This is broken, and in fact, should not even be looked at by this
962 // lint in the first place. There's weird stuff going on in the
963 // collection phase.
964 // It's currently being brought in by:
965 // * validate_func on `a` recursing into modules
966 // * then it finds the trait and then the function while iterating
967 // through modules
968 // * then validate_func is called on Dirty
969 // * ... which then proceeds to look at some unknown module taking no
970 // attrs from either the impl or the fn a, and then finally to the root
971 // module
972 //
973 // It should find the attribute on the trait, but it *doesn't even see
974 // the trait* as far as I can tell.
975
976 check_diagnostics(
977 r#"
978trait T { fn a(); }
979struct U {}
980impl T for U {
981 fn a() {
982 // this comes out of bitflags, mostly
983 #[allow(non_snake_case)]
984 trait __BitFlags {
985 const HiImAlsoBad: u8 = 2;
986 #[inline]
987 fn Dirty(&self) -> bool {
988 false
989 }
990 }
991
992 }
993}
994 "#,
995 );
996 }
997
998 #[test]
999 #[ignore]
1000 fn bug_traits_arent_checked() {
1001 // FIXME: Traits and functions in traits aren't currently checked by
1002 // r-a, even though rustc will complain about them.
1003 check_diagnostics(
1004 r#"
1005trait BAD_TRAIT {
1006 // ^^^^^^^^^ Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
1007 fn BAD_FUNCTION();
1008 // ^^^^^^^^^^^^ Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
1009 fn BadFunction();
1010 // ^^^^^^^^^^^^ Function `BadFunction` should have snake_case name, e.g. `bad_function`
1011}
888 "#, 1012 "#,
889 ); 1013 );
890 } 1014 }
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 3909ad354..79602c3dd 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -14,8 +14,7 @@ use crate::{
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data, 17 AdtId, InferenceResult, Interner, TyExt, TyKind,
18 AdtId, InferenceResult, Interner, Ty, TyKind,
19}; 18};
20 19
21pub(crate) use hir_def::{ 20pub(crate) use hir_def::{
@@ -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())
@@ -245,7 +244,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
245 Some(callee) => callee, 244 Some(callee) => callee,
246 None => return, 245 None => return,
247 }; 246 };
248 let sig = db.callable_item_signature(callee.into()).value; 247 let sig =
248 db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0;
249 249
250 (sig, args) 250 (sig, args)
251 } 251 }
@@ -314,7 +314,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
314 if pat_ty == match_expr_ty 314 if pat_ty == match_expr_ty
315 || match_expr_ty 315 || match_expr_ty
316 .as_reference() 316 .as_reference()
317 .map(|(match_expr_ty, _)| match_expr_ty == pat_ty) 317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
318 .unwrap_or(false) 318 .unwrap_or(false)
319 { 319 {
320 // If we had a NotUsefulMatchArm diagnostic, we could 320 // If we had a NotUsefulMatchArm diagnostic, we could
@@ -378,7 +378,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
378 _ => return, 378 _ => return,
379 }; 379 };
380 380
381 let (params, required) = match mismatch.expected.interned(&Interner) { 381 let (params, required) = match mismatch.expected.kind(&Interner) {
382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) 382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
383 if *enum_id == core_result_enum => 383 if *enum_id == core_result_enum =>
384 { 384 {
@@ -392,7 +392,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
392 _ => return, 392 _ => return,
393 }; 393 };
394 394
395 if params.len() > 0 && params[0] == mismatch.actual { 395 if params.len(&Interner) > 0
396 && params.at(&Interner, 0).ty(&Interner) == Some(&mismatch.actual)
397 {
396 let (_, source_map) = db.body_with_source_map(self.owner); 398 let (_, source_map) = db.body_with_source_map(self.owner);
397 399
398 if let Ok(source_ptr) = source_map.expr_syntax(id) { 400 if let Ok(source_ptr) = source_map.expr_syntax(id) {
@@ -421,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
421 None => return, 423 None => return,
422 }; 424 };
423 425
424 if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { 426 if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty {
425 return; 427 return;
426 } 428 }
427 429
@@ -450,7 +452,7 @@ pub fn record_literal_missing_fields(
450 return None; 452 return None;
451 } 453 }
452 454
453 let variant_data = variant_data(db.upcast(), variant_def); 455 let variant_data = variant_def.variant_data(db.upcast());
454 456
455 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
456 let missed_fields: Vec<LocalFieldId> = variant_data 458 let missed_fields: Vec<LocalFieldId> = variant_data
@@ -480,7 +482,7 @@ pub fn record_pattern_missing_fields(
480 return None; 482 return None;
481 } 483 }
482 484
483 let variant_data = variant_data(db.upcast(), variant_def); 485 let variant_data = variant_def.variant_data(db.upcast());
484 486
485 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
486 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 5a5cdcbf3..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
@@ -539,7 +539,7 @@ impl Matrix {
539 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { 539 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) {
540 // Or patterns are expanded here 540 // Or patterns are expanded here
541 for pat_id in pat_ids { 541 for pat_id in pat_ids {
542 self.0.push(PatStack::from_pattern(pat_id)); 542 self.0.push(row.replace_head_with([pat_id].iter()));
543 } 543 }
544 } else { 544 } else {
545 self.0.push(row); 545 self.0.push(row);
@@ -626,7 +626,7 @@ pub(super) fn is_useful(
626 // - enum with no variants 626 // - enum with no variants
627 // - `!` type 627 // - `!` type
628 // In those cases, no match arm is useful. 628 // In those cases, no match arm is useful.
629 match cx.infer[cx.match_expr].strip_references().interned(&Interner) { 629 match cx.infer[cx.match_expr].strip_references().kind(&Interner) {
630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { 630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
631 if cx.db.enum_data(*enum_id).variants.is_empty() { 631 if cx.db.enum_data(*enum_id).variants.is_empty() {
632 return Ok(Usefulness::NotUseful); 632 return Ok(Usefulness::NotUseful);
@@ -792,7 +792,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Opt
792 Pat::Tuple { .. } => { 792 Pat::Tuple { .. } => {
793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); 793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild");
794 Some(Constructor::Tuple { 794 Some(Constructor::Tuple {
795 arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), 795 arity: cx.infer.type_of_pat[pat_id]
796 .as_tuple()
797 .ok_or(MatchCheckErr::Unknown)?
798 .len(&Interner),
796 }) 799 })
797 } 800 }
798 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { 801 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] {
@@ -1085,6 +1088,20 @@ fn main() {
1085 } 1088 }
1086 1089
1087 #[test] 1090 #[test]
1091 fn or_pattern_no_diagnostic() {
1092 check_diagnostics(
1093 r#"
1094enum Either {A, B}
1095
1096fn main() {
1097 match (Either::A, Either::B) {
1098 (Either::A | Either::B, _) => (),
1099 }
1100}"#,
1101 )
1102 }
1103
1104 #[test]
1088 fn mismatched_types() { 1105 fn mismatched_types() {
1089 // Match statements with arms that don't match the 1106 // Match statements with arms that don't match the
1090 // expression pattern do not fire this diagnostic. 1107 // expression pattern do not fire this diagnostic.
@@ -1336,30 +1353,6 @@ fn bang(never: !) {
1336 } 1353 }
1337 1354
1338 #[test] 1355 #[test]
1339 fn or_pattern_panic() {
1340 check_diagnostics(
1341 r#"
1342pub enum Category { Infinity, Zero }
1343
1344fn panic(a: Category, b: Category) {
1345 match (a, b) {
1346 (Category::Zero | Category::Infinity, _) => (),
1347 (_, Category::Zero | Category::Infinity) => (),
1348 }
1349
1350 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
1351 // so this acts as a regression test for that.
1352 match (a, b) {
1353 //^^^^^^ Missing match arm
1354 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (),
1355 (Category::Infinity | Category::Zero, _) => (),
1356 }
1357}
1358"#,
1359 );
1360 }
1361
1362 #[test]
1363 fn unknown_type() { 1356 fn unknown_type() {
1364 check_diagnostics( 1357 check_diagnostics(
1365 r#" 1358 r#"
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 1f49a4909..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,
@@ -32,7 +34,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
32 let def = self.owner; 34 let def = self.owner;
33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
34 let is_unsafe = match self.owner { 36 let is_unsafe = match self.owner {
35 DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, 37 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, 38 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
37 }; 39 };
38 if is_unsafe 40 if is_unsafe
@@ -86,7 +88,7 @@ fn walk_unsafe(
86 match expr { 88 match expr {
87 &Expr::Call { callee, .. } => { 89 &Expr::Call { callee, .. } => {
88 if let Some(func) = infer[callee].as_fn_def(db) { 90 if let Some(func) = infer[callee].as_fn_def(db) {
89 if db.function_data(func).qualifier.is_unsafe { 91 if db.function_data(func).is_unsafe() {
90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 92 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
91 } 93 }
92 } 94 }
@@ -103,14 +105,14 @@ fn walk_unsafe(
103 Expr::MethodCall { .. } => { 105 Expr::MethodCall { .. } => {
104 if infer 106 if infer
105 .method_resolution(current) 107 .method_resolution(current)
106 .map(|func| db.function_data(func).qualifier.is_unsafe) 108 .map(|func| db.function_data(func).is_unsafe())
107 .unwrap_or(false) 109 .unwrap_or(false)
108 { 110 {
109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 111 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
110 } 112 }
111 } 113 }
112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => { 114 Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
113 if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) { 115 if let TyKind::Raw(..) = &infer[*expr].kind(&Interner) {
114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 116 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
115 } 117 }
116 } 118 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 51480304b..e7c9dabc2 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,14 +1,19 @@
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,
9 generics::TypeParamProvenance, 14 generics::TypeParamProvenance,
10 item_scope::ItemInNs, 15 item_scope::ItemInNs,
11 path::{GenericArg, Path, PathKind}, 16 path::{Path, PathKind},
12 type_ref::{TypeBound, TypeRef}, 17 type_ref::{TypeBound, TypeRef},
13 visibility::Visibility, 18 visibility::Visibility,
14 AssocContainerId, Lookup, ModuleId, TraitId, 19 AssocContainerId, Lookup, ModuleId, TraitId,
@@ -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, ImplTraitId, Interner, Lifetime, OpaqueTy, 26 to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const,
22 ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, 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.substitution[0].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, 268 if self.substitution.len(&Interner) > 1 {
258 f.display_target,
259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len() > 1 {
262 write!(f, "<")?; 269 write!(f, "<")?;
263 f.write_joined(&self.substitution[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)?;
@@ -274,7 +281,40 @@ impl HirDisplay for OpaqueTy {
274 return write!(f, "{}", TYPE_HINT_TRUNCATION); 281 return write!(f, "{}", TYPE_HINT_TRUNCATION);
275 } 282 }
276 283
277 self.substitution[0].hir_fmt(f) 284 self.substitution.at(&Interner, 0).hir_fmt(f)
285 }
286}
287
288impl HirDisplay for GenericArg {
289 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
290 match self.interned() {
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, "_"),
311 }
312 }
313}
314
315impl HirDisplay for BoundVar {
316 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
317 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
278 } 318 }
279} 319}
280 320
@@ -284,7 +324,7 @@ impl HirDisplay for Ty {
284 return write!(f, "{}", TYPE_HINT_TRUNCATION); 324 return write!(f, "{}", TYPE_HINT_TRUNCATION);
285 } 325 }
286 326
287 match self.interned(&Interner) { 327 match self.kind(&Interner) {
288 TyKind::Never => write!(f, "!")?, 328 TyKind::Never => write!(f, "!")?,
289 TyKind::Str => write!(f, "str")?, 329 TyKind::Str => write!(f, "str")?,
290 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, 330 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
@@ -297,16 +337,15 @@ impl HirDisplay for Ty {
297 t.hir_fmt(f)?; 337 t.hir_fmt(f)?;
298 write!(f, "]")?; 338 write!(f, "]")?;
299 } 339 }
300 TyKind::Array(t) => { 340 TyKind::Array(t, c) => {
301 write!(f, "[")?; 341 write!(f, "[")?;
302 t.hir_fmt(f)?; 342 t.hir_fmt(f)?;
303 write!(f, "; _]")?; 343 write!(f, "; ")?;
344 c.hir_fmt(f)?;
345 write!(f, "]")?;
304 } 346 }
305 TyKind::Raw(m, t) | TyKind::Ref(m, t) => { 347 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
306 let ty_display = 348 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
307 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
308
309 if matches!(self.interned(&Interner), TyKind::Raw(..)) {
310 write!( 349 write!(
311 f, 350 f,
312 "*{}", 351 "*{}",
@@ -328,7 +367,7 @@ impl HirDisplay for Ty {
328 367
329 // FIXME: all this just to decide whether to use parentheses... 368 // FIXME: all this just to decide whether to use parentheses...
330 let datas; 369 let datas;
331 let predicates: Vec<_> = match t.interned(&Interner) { 370 let predicates: Vec<_> = match t.kind(&Interner) {
332 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { 371 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
333 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() 372 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
334 } 373 }
@@ -344,8 +383,8 @@ impl HirDisplay for Ty {
344 let data = (*datas) 383 let data = (*datas)
345 .as_ref() 384 .as_ref()
346 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 385 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
347 let bounds = data.subst(parameters); 386 let bounds = data.substitute(&Interner, parameters);
348 bounds.value 387 bounds.into_value_and_skipped_binders().0
349 } else { 388 } else {
350 Vec::new() 389 Vec::new()
351 } 390 }
@@ -360,26 +399,26 @@ impl HirDisplay for Ty {
360 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) 399 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
361 && predicates.len() <= 2 400 && predicates.len() <= 2
362 { 401 {
363 return write!(f, "{}", ty_display); 402 return t.hir_fmt(f);
364 } 403 }
365 } 404 }
366 405
367 if predicates.len() > 1 { 406 if predicates.len() > 1 {
368 write!(f, "(")?; 407 write!(f, "(")?;
369 write!(f, "{}", ty_display)?; 408 t.hir_fmt(f)?;
370 write!(f, ")")?; 409 write!(f, ")")?;
371 } else { 410 } else {
372 write!(f, "{}", ty_display)?; 411 t.hir_fmt(f)?;
373 } 412 }
374 } 413 }
375 TyKind::Tuple(_, substs) => { 414 TyKind::Tuple(_, substs) => {
376 if substs.len() == 1 { 415 if substs.len(&Interner) == 1 {
377 write!(f, "(")?; 416 write!(f, "(")?;
378 substs[0].hir_fmt(f)?; 417 substs.at(&Interner, 0).hir_fmt(f)?;
379 write!(f, ",)")?; 418 write!(f, ",)")?;
380 } else { 419 } else {
381 write!(f, "(")?; 420 write!(f, "(")?;
382 f.write_joined(&*substs.0, ", ")?; 421 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
383 write!(f, ")")?; 422 write!(f, ")")?;
384 } 423 }
385 } 424 }
@@ -389,7 +428,7 @@ impl HirDisplay for Ty {
389 } 428 }
390 TyKind::FnDef(def, parameters) => { 429 TyKind::FnDef(def, parameters) => {
391 let def = from_chalk(f.db, *def); 430 let def = from_chalk(f.db, *def);
392 let sig = f.db.callable_item_signature(def).subst(parameters); 431 let sig = f.db.callable_item_signature(def).substitute(&Interner, parameters);
393 match def { 432 match def {
394 CallableDefId::FunctionId(ff) => { 433 CallableDefId::FunctionId(ff) => {
395 write!(f, "fn {}", f.db.function_data(ff).name)? 434 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -399,7 +438,7 @@ impl HirDisplay for Ty {
399 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 438 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
400 } 439 }
401 }; 440 };
402 if parameters.len() > 0 { 441 if parameters.len(&Interner) > 0 {
403 let generics = generics(f.db.upcast(), def.into()); 442 let generics = generics(f.db.upcast(), def.into());
404 let (parent_params, self_param, type_params, _impl_trait_params) = 443 let (parent_params, self_param, type_params, _impl_trait_params) =
405 generics.provenance_split(); 444 generics.provenance_split();
@@ -407,7 +446,7 @@ impl HirDisplay for Ty {
407 // 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?
408 if total_len > 0 { 447 if total_len > 0 {
409 write!(f, "<")?; 448 write!(f, "<")?;
410 f.write_joined(&parameters.0[..total_len], ", ")?; 449 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
411 write!(f, ">")?; 450 write!(f, ">")?;
412 } 451 }
413 } 452 }
@@ -415,15 +454,9 @@ impl HirDisplay for Ty {
415 f.write_joined(sig.params(), ", ")?; 454 f.write_joined(sig.params(), ", ")?;
416 write!(f, ")")?; 455 write!(f, ")")?;
417 let ret = sig.ret(); 456 let ret = sig.ret();
418 if *ret != Ty::unit() { 457 if !ret.is_unit() {
419 let ret_display = ret.into_displayable( 458 write!(f, " -> ")?;
420 f.db, 459 ret.hir_fmt(f)?;
421 f.max_size,
422 f.omit_verbose_types,
423 f.display_target,
424 );
425
426 write!(f, " -> {}", ret_display)?;
427 } 460 }
428 } 461 }
429 TyKind::Adt(AdtId(def_id), parameters) => { 462 TyKind::Adt(AdtId(def_id), parameters) => {
@@ -451,7 +484,7 @@ impl HirDisplay for Ty {
451 } 484 }
452 } 485 }
453 486
454 if parameters.len() > 0 { 487 if parameters.len(&Interner) > 0 {
455 let parameters_to_write = if f.display_target.is_source_code() 488 let parameters_to_write = if f.display_target.is_source_code()
456 || f.omit_verbose_types() 489 || f.omit_verbose_types()
457 { 490 {
@@ -460,30 +493,35 @@ impl HirDisplay for Ty {
460 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 493 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
461 .filter(|defaults| !defaults.is_empty()) 494 .filter(|defaults| !defaults.is_empty())
462 { 495 {
463 None => parameters.0.as_ref(), 496 None => parameters.as_slice(&Interner),
464 Some(default_parameters) => { 497 Some(default_parameters) => {
465 let mut default_from = 0; 498 let mut default_from = 0;
466 for (i, parameter) in parameters.iter().enumerate() { 499 for (i, parameter) in parameters.iter(&Interner).enumerate() {
467 match (parameter.interned(&Interner), default_parameters.get(i)) 500 match (
468 { 501 parameter.assert_ty_ref(&Interner).kind(&Interner),
469 (&TyKind::Unknown, _) | (_, None) => { 502 default_parameters.get(i),
503 ) {
504 (&TyKind::Error, _) | (_, None) => {
470 default_from = i + 1; 505 default_from = i + 1;
471 } 506 }
472 (_, Some(default_parameter)) => { 507 (_, Some(default_parameter)) => {
473 let actual_default = default_parameter 508 let actual_default =
474 .clone() 509 default_parameter.clone().substitute(
475 .subst(&parameters.prefix(i)); 510 &Interner,
476 if parameter != &actual_default { 511 &subst_prefix(parameters, i),
512 );
513 if parameter.assert_ty_ref(&Interner) != &actual_default
514 {
477 default_from = i + 1; 515 default_from = i + 1;
478 } 516 }
479 } 517 }
480 } 518 }
481 } 519 }
482 &parameters.0[0..default_from] 520 &parameters.as_slice(&Interner)[0..default_from]
483 } 521 }
484 } 522 }
485 } else { 523 } else {
486 parameters.0.as_ref() 524 parameters.as_slice(&Interner)
487 }; 525 };
488 if !parameters_to_write.is_empty() { 526 if !parameters_to_write.is_empty() {
489 write!(f, "<")?; 527 write!(f, "<")?;
@@ -504,9 +542,9 @@ impl HirDisplay for Ty {
504 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 542 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
505 if f.display_target.is_test() { 543 if f.display_target.is_test() {
506 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 544 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
507 if parameters.len() > 0 { 545 if parameters.len(&Interner) > 0 {
508 write!(f, "<")?; 546 write!(f, "<")?;
509 f.write_joined(&*parameters.0, ", ")?; 547 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
510 write!(f, ">")?; 548 write!(f, ">")?;
511 } 549 }
512 } else { 550 } else {
@@ -518,7 +556,7 @@ impl HirDisplay for Ty {
518 projection_ty.hir_fmt(f)?; 556 projection_ty.hir_fmt(f)?;
519 } 557 }
520 } 558 }
521 TyKind::ForeignType(type_alias) => { 559 TyKind::Foreign(type_alias) => {
522 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias)); 560 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
523 write!(f, "{}", type_alias.name)?; 561 write!(f, "{}", type_alias.name)?;
524 } 562 }
@@ -531,13 +569,13 @@ impl HirDisplay for Ty {
531 let data = (*datas) 569 let data = (*datas)
532 .as_ref() 570 .as_ref()
533 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 571 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
534 let bounds = data.subst(&parameters); 572 let bounds = data.substitute(&Interner, &parameters);
535 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 573 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
536 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 574 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
537 } 575 }
538 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 576 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
539 write!(f, "impl Future<Output = ")?; 577 write!(f, "impl Future<Output = ")?;
540 parameters[0].hir_fmt(f)?; 578 parameters.at(&Interner, 0).hir_fmt(f)?;
541 write!(f, ">")?; 579 write!(f, ">")?;
542 } 580 }
543 } 581 }
@@ -548,7 +586,7 @@ impl HirDisplay for Ty {
548 DisplaySourceCodeError::Closure, 586 DisplaySourceCodeError::Closure,
549 )); 587 ));
550 } 588 }
551 let sig = substs[0].callable_sig(f.db); 589 let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db);
552 if let Some(sig) = sig { 590 if let Some(sig) = sig {
553 if sig.params().is_empty() { 591 if sig.params().is_empty() {
554 write!(f, "||")?; 592 write!(f, "||")?;
@@ -560,13 +598,8 @@ impl HirDisplay for Ty {
560 write!(f, "|")?; 598 write!(f, "|")?;
561 }; 599 };
562 600
563 let ret_display = sig.ret().into_displayable( 601 write!(f, " -> ")?;
564 f.db, 602 sig.ret().hir_fmt(f)?;
565 f.max_size,
566 f.omit_verbose_types,
567 f.display_target,
568 );
569 write!(f, " -> {}", ret_display)?;
570 } else { 603 } else {
571 write!(f, "{{closure}}")?; 604 write!(f, "{{closure}}")?;
572 } 605 }
@@ -580,26 +613,27 @@ impl HirDisplay for Ty {
580 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 613 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
581 } 614 }
582 TypeParamProvenance::ArgumentImplTrait => { 615 TypeParamProvenance::ArgumentImplTrait => {
583 let substs = Substitution::type_params_for_generics(f.db, &generics); 616 let substs = generics.type_params_subst(f.db);
584 let bounds = f 617 let bounds =
585 .db 618 f.db.generic_predicates(id.parent)
586 .generic_predicates(id.parent) 619 .into_iter()
587 .into_iter() 620 .map(|pred| pred.clone().substitute(&Interner, &substs))
588 .map(|pred| pred.clone().subst(&substs)) 621 .filter(|wc| match &wc.skip_binders() {
589 .filter(|wc| match &wc.skip_binders() { 622 WhereClause::Implemented(tr) => {
590 WhereClause::Implemented(tr) => tr.self_type_parameter() == self, 623 &tr.self_type_parameter(&Interner) == self
591 WhereClause::AliasEq(AliasEq { 624 }
592 alias: AliasTy::Projection(proj), 625 WhereClause::AliasEq(AliasEq {
593 ty: _, 626 alias: AliasTy::Projection(proj),
594 }) => proj.self_type_parameter() == self, 627 ty: _,
595 _ => false, 628 }) => &proj.self_type_parameter(&Interner) == self,
596 }) 629 _ => false,
597 .collect::<Vec<_>>(); 630 })
631 .collect::<Vec<_>>();
598 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; 632 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
599 } 633 }
600 } 634 }
601 } 635 }
602 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 636 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
603 TyKind::Dyn(dyn_ty) => { 637 TyKind::Dyn(dyn_ty) => {
604 write_bounds_like_dyn_trait_with_prefix( 638 write_bounds_like_dyn_trait_with_prefix(
605 "dyn", 639 "dyn",
@@ -617,15 +651,15 @@ impl HirDisplay for Ty {
617 let data = (*datas) 651 let data = (*datas)
618 .as_ref() 652 .as_ref()
619 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 653 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
620 let bounds = data.subst(&opaque_ty.substitution); 654 let bounds = data.substitute(&Interner, &opaque_ty.substitution);
621 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 655 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
622 } 656 }
623 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 657 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
624 write!(f, "{{async block}}")?; 658 write!(f, "{{async block}}")?;
625 } 659 }
626 }; 660 };
627 } 661 }
628 TyKind::Unknown => { 662 TyKind::Error => {
629 if f.display_target.is_source_code() { 663 if f.display_target.is_source_code() {
630 return Err(HirDisplayError::DisplaySourceCodeError( 664 return Err(HirDisplayError::DisplaySourceCodeError(
631 DisplaySourceCodeError::UnknownType, 665 DisplaySourceCodeError::UnknownType,
@@ -634,6 +668,8 @@ impl HirDisplay for Ty {
634 write!(f, "{{unknown}}")?; 668 write!(f, "{{unknown}}")?;
635 } 669 }
636 TyKind::InferenceVar(..) => write!(f, "_")?, 670 TyKind::InferenceVar(..) => write!(f, "_")?,
671 TyKind::Generator(..) => write!(f, "{{generator}}")?,
672 TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
637 } 673 }
638 Ok(()) 674 Ok(())
639 } 675 }
@@ -652,10 +688,9 @@ impl HirDisplay for CallableSig {
652 } 688 }
653 write!(f, ")")?; 689 write!(f, ")")?;
654 let ret = self.ret(); 690 let ret = self.ret();
655 if *ret != Ty::unit() { 691 if !ret.is_unit() {
656 let ret_display = 692 write!(f, " -> ")?;
657 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 693 ret.hir_fmt(f)?;
658 write!(f, " -> {}", ret_display)?;
659 } 694 }
660 Ok(()) 695 Ok(())
661 } 696 }
@@ -712,15 +747,17 @@ fn write_bounds_like_dyn_trait(
712 if !first { 747 if !first {
713 write!(f, " + ")?; 748 write!(f, " + ")?;
714 } 749 }
715 // We assume that the self type is $0 (i.e. the 750 // We assume that the self type is ^0.0 (i.e. the
716 // existential) here, which is the only thing that's 751 // existential) here, which is the only thing that's
717 // possible in actual Rust, and hence don't print it 752 // possible in actual Rust, and hence don't print it
718 write!(f, "{}", f.db.trait_data(trait_).name)?; 753 write!(f, "{}", f.db.trait_data(trait_).name)?;
719 if let [_, params @ ..] = &*trait_ref.substitution.0 { 754 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
720 if is_fn_trait { 755 if is_fn_trait {
721 if let Some(args) = params.first().and_then(|it| it.as_tuple()) { 756 if let Some(args) =
757 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
758 {
722 write!(f, "(")?; 759 write!(f, "(")?;
723 f.write_joined(&*args.0, ", ")?; 760 f.write_joined(args.as_slice(&Interner), ", ")?;
724 write!(f, ")")?; 761 write!(f, ")")?;
725 } 762 }
726 } else if !params.is_empty() { 763 } else if !params.is_empty() {
@@ -752,6 +789,10 @@ fn write_bounds_like_dyn_trait(
752 } 789 }
753 ty.hir_fmt(f)?; 790 ty.hir_fmt(f)?;
754 } 791 }
792
793 // FIXME implement these
794 WhereClause::LifetimeOutlives(_) => {}
795 WhereClause::TypeOutlives(_) => {}
755 } 796 }
756 first = false; 797 first = false;
757 } 798 }
@@ -761,31 +802,29 @@ fn write_bounds_like_dyn_trait(
761 Ok(()) 802 Ok(())
762} 803}
763 804
764impl TraitRef { 805fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
765 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> { 806 if f.should_truncate() {
766 if f.should_truncate() { 807 return write!(f, "{}", TYPE_HINT_TRUNCATION);
767 return write!(f, "{}", TYPE_HINT_TRUNCATION); 808 }
768 }
769 809
770 self.substitution[0].hir_fmt(f)?; 810 tr.self_type_parameter(&Interner).hir_fmt(f)?;
771 if use_as { 811 if use_as {
772 write!(f, " as ")?; 812 write!(f, " as ")?;
773 } else { 813 } else {
774 write!(f, ": ")?; 814 write!(f, ": ")?;
775 } 815 }
776 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; 816 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
777 if self.substitution.len() > 1 { 817 if tr.substitution.len(&Interner) > 1 {
778 write!(f, "<")?; 818 write!(f, "<")?;
779 f.write_joined(&self.substitution[1..], ", ")?; 819 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
780 write!(f, ">")?; 820 write!(f, ">")?;
781 }
782 Ok(())
783 } 821 }
822 Ok(())
784} 823}
785 824
786impl HirDisplay for TraitRef { 825impl HirDisplay for TraitRef {
787 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 826 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
788 self.hir_fmt_ext(f, false) 827 fmt_trait_ref(self, f, false)
789 } 828 }
790} 829}
791 830
@@ -799,7 +838,7 @@ impl HirDisplay for WhereClause {
799 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 838 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
800 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 839 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
801 write!(f, "<")?; 840 write!(f, "<")?;
802 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 841 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
803 write!( 842 write!(
804 f, 843 f,
805 ">::{} = ", 844 ">::{} = ",
@@ -808,20 +847,44 @@ impl HirDisplay for WhereClause {
808 ty.hir_fmt(f)?; 847 ty.hir_fmt(f)?;
809 } 848 }
810 WhereClause::AliasEq(_) => write!(f, "{{error}}")?, 849 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
850
851 // FIXME implement these
852 WhereClause::TypeOutlives(..) => {}
853 WhereClause::LifetimeOutlives(..) => {}
811 } 854 }
812 Ok(()) 855 Ok(())
813 } 856 }
814} 857}
815 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
816impl HirDisplay for Lifetime { 867impl HirDisplay for Lifetime {
817 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> {
818 match self { 875 match self {
819 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);
820 let generics = generics(f.db.upcast(), id.parent); 880 let generics = generics(f.db.upcast(), id.parent);
821 let param_data = &generics.params.lifetimes[id.local_id]; 881 let param_data = &generics.params.lifetimes[id.local_id];
822 write!(f, "{}", &param_data.name) 882 write!(f, "{}", param_data.name)
823 } 883 }
824 Lifetime::Static => write!(f, "'static"), 884 LifetimeData::Static => write!(f, "'static"),
885 LifetimeData::Empty(_) => Ok(()),
886 LifetimeData::Erased => Ok(()),
887 LifetimeData::Phantom(_, _) => Ok(()),
825 } 888 }
826 } 889 }
827} 890}
@@ -832,9 +895,11 @@ impl HirDisplay for DomainGoal {
832 DomainGoal::Holds(wc) => { 895 DomainGoal::Holds(wc) => {
833 write!(f, "Holds(")?; 896 write!(f, "Holds(")?;
834 wc.hir_fmt(f)?; 897 wc.hir_fmt(f)?;
835 write!(f, ")") 898 write!(f, ")")?;
836 } 899 }
900 _ => write!(f, "?")?,
837 } 901 }
902 Ok(())
838 } 903 }
839} 904}
840 905
@@ -1016,11 +1081,11 @@ impl HirDisplay for Path {
1016 } 1081 }
1017} 1082}
1018 1083
1019impl HirDisplay for GenericArg { 1084impl HirDisplay for hir_def::path::GenericArg {
1020 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 1085 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1021 match self { 1086 match self {
1022 GenericArg::Type(ty) => ty.hir_fmt(f), 1087 hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1023 GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), 1088 hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1024 } 1089 }
1025 } 1090 }
1026} 1091}
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index e4407ff50..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},
@@ -37,12 +37,12 @@ use stdx::impl_from;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{DomainGoal, Guidance, Solution}, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, 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, to_chalk_trait_id, AliasEq, AliasTy, Interner, 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.
@@ -120,7 +120,7 @@ struct InternedStandardTypes {
120 120
121impl Default for InternedStandardTypes { 121impl Default for InternedStandardTypes {
122 fn default() -> Self { 122 fn default() -> Self {
123 InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) } 123 InternedStandardTypes { unknown: TyKind::Error.intern(&Interner) }
124 } 124 }
125} 125}
126 126
@@ -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 }
@@ -210,6 +201,7 @@ struct InferenceContext<'a> {
210 table: unify::InferenceTable, 201 table: unify::InferenceTable,
211 trait_env: Arc<TraitEnvironment>, 202 trait_env: Arc<TraitEnvironment>,
212 obligations: Vec<DomainGoal>, 203 obligations: Vec<DomainGoal>,
204 last_obligations_check: Option<u32>,
213 result: InferenceResult, 205 result: InferenceResult,
214 /// The return type of the function being inferred, or the closure if we're 206 /// The return type of the function being inferred, or the closure if we're
215 /// currently within one. 207 /// currently within one.
@@ -245,7 +237,8 @@ impl<'a> InferenceContext<'a> {
245 result: InferenceResult::default(), 237 result: InferenceResult::default(),
246 table: unify::InferenceTable::new(), 238 table: unify::InferenceTable::new(),
247 obligations: Vec::default(), 239 obligations: Vec::default(),
248 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature 240 last_obligations_check: None,
241 return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature
249 trait_env: owner 242 trait_env: owner
250 .as_generic_def_id() 243 .as_generic_def_id()
251 .map_or_else(Default::default, |d| db.trait_environment(d)), 244 .map_or_else(Default::default, |d| db.trait_environment(d)),
@@ -259,7 +252,7 @@ impl<'a> InferenceContext<'a> {
259 } 252 }
260 253
261 fn err_ty(&self) -> Ty { 254 fn err_ty(&self) -> Ty {
262 TyKind::Unknown.intern(&Interner) 255 TyKind::Error.intern(&Interner)
263 } 256 }
264 257
265 fn resolve_all(mut self) -> InferenceResult { 258 fn resolve_all(mut self) -> InferenceResult {
@@ -323,30 +316,44 @@ impl<'a> InferenceContext<'a> {
323 316
324 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 317 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
325 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 318 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
326 match ty.interned(&Interner) { 319 match ty.kind(&Interner) {
327 TyKind::Unknown => self.table.new_type_var(), 320 TyKind::Error => self.table.new_type_var(),
328 _ => ty, 321 _ => ty,
329 } 322 }
330 } 323 }
331 324
332 fn insert_type_vars(&mut self, ty: Ty) -> Ty { 325 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
333 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 326 fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
334 } 327 }
335 328
336 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
330 if self.last_obligations_check == Some(self.table.revision) {
331 // no change
332 return;
333 }
334 let _span = profile::span("resolve_obligations_as_possible");
335
336 self.last_obligations_check = Some(self.table.revision);
337 let obligations = mem::replace(&mut self.obligations, Vec::new()); 337 let obligations = mem::replace(&mut self.obligations, Vec::new());
338 for obligation in obligations { 338 for obligation in obligations {
339 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 339 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
341 let solution = 341 let solution =
342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
343 343
344 match solution { 344 match solution {
345 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
346 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 );
347 } 354 }
348 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
349 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
350 self.obligations.push(obligation); 357 self.obligations.push(obligation);
351 } 358 }
352 Some(_) => { 359 Some(_) => {
@@ -360,6 +367,11 @@ impl<'a> InferenceContext<'a> {
360 } 367 }
361 } 368 }
362 369
370 fn push_obligation(&mut self, o: DomainGoal) {
371 self.obligations.push(o);
372 self.last_obligations_check = None;
373 }
374
363 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 375 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
364 self.table.unify(ty1, ty2) 376 self.table.unify(ty1, ty2)
365 } 377 }
@@ -395,21 +407,19 @@ impl<'a> InferenceContext<'a> {
395 _ => panic!("resolve_associated_type called with non-associated type"), 407 _ => panic!("resolve_associated_type called with non-associated type"),
396 }; 408 };
397 let ty = self.table.new_type_var(); 409 let ty = self.table.new_type_var();
398 let substs = Substitution::build_for_def(self.db, res_assoc_ty) 410 let trait_ref = TyBuilder::trait_ref(self.db, trait_)
399 .push(inner_ty) 411 .push(inner_ty)
400 .fill(params.iter().cloned()) 412 .fill(params.iter().cloned())
401 .build(); 413 .build();
402 let trait_ref =
403 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
404 let alias_eq = AliasEq { 414 let alias_eq = AliasEq {
405 alias: AliasTy::Projection(ProjectionTy { 415 alias: AliasTy::Projection(ProjectionTy {
406 associated_ty_id: to_assoc_type_id(res_assoc_ty), 416 associated_ty_id: to_assoc_type_id(res_assoc_ty),
407 substitution: substs, 417 substitution: trait_ref.substitution.clone(),
408 }), 418 }),
409 ty: ty.clone(), 419 ty: ty.clone(),
410 }; 420 };
411 self.obligations.push(trait_ref.cast(&Interner)); 421 self.push_obligation(trait_ref.cast(&Interner));
412 self.obligations.push(alias_eq.cast(&Interner)); 422 self.push_obligation(alias_eq.cast(&Interner));
413 self.resolve_ty_as_possible(ty) 423 self.resolve_ty_as_possible(ty)
414 } 424 }
415 None => self.err_ty(), 425 None => self.err_ty(),
@@ -424,19 +434,23 @@ impl<'a> InferenceContext<'a> {
424 /// to do it as well. 434 /// to do it as well.
425 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
426 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
427 ty.fold(&mut |ty| match ty.interned(&Interner) { 437 fold_tys(
428 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 ty,
429 self.normalize_projection_ty(proj_ty.clone()) 439 |ty, _| match ty.kind(&Interner) {
430 } 440 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
431 _ => ty, 441 self.normalize_projection_ty(proj_ty.clone())
432 }) 442 }
443 _ => ty,
444 },
445 DebruijnIndex::INNERMOST,
446 )
433 }