aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/Cargo.toml8
-rw-r--r--crates/hir_ty/src/autoderef.rs68
-rw-r--r--crates/hir_ty/src/builder.rs30
-rw-r--r--crates/hir_ty/src/chalk_cast.rs73
-rw-r--r--crates/hir_ty/src/chalk_db.rs (renamed from crates/hir_ty/src/traits/chalk.rs)262
-rw-r--r--crates/hir_ty/src/chalk_ext.rs294
-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.rs169
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs14
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--crates/hir_ty/src/display.rs275
-rw-r--r--crates/hir_ty/src/infer.rs165
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs91
-rw-r--r--crates/hir_ty/src/infer/pat.rs59
-rw-r--r--crates/hir_ty/src/infer/path.rs18
-rw-r--r--crates/hir_ty/src/infer/unify.rs218
-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.rs1290
-rw-r--r--crates/hir_ty/src/lower.rs300
-rw-r--r--crates/hir_ty/src/mapping.rs154
-rw-r--r--crates/hir_ty/src/method_resolution.rs329
-rw-r--r--crates/hir_ty/src/op.rs66
-rw-r--r--crates/hir_ty/src/primitive.rs5
-rw-r--r--crates/hir_ty/src/tests/macros.rs201
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs57
-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.rs1467
-rw-r--r--crates/hir_ty/src/tls.rs (renamed from crates/hir_ty/src/traits/chalk/tls.rs)14
-rw-r--r--crates/hir_ty/src/traits.rs140
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs575
-rw-r--r--crates/hir_ty/src/utils.rs53
-rw-r--r--crates/hir_ty/src/walk.rs150
37 files changed, 3407 insertions, 3549 deletions
diff --git a/crates/hir_ty/Cargo.toml b/crates/hir_ty/Cargo.toml
index 030b7eebe..66b3418f2 100644
--- a/crates/hir_ty/Cargo.toml
+++ b/crates/hir_ty/Cargo.toml
@@ -12,15 +12,15 @@ 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"
19rustc-hash = "1.1.0" 19rustc-hash = "1.1.0"
20scoped-tls = "1" 20scoped-tls = "1"
21chalk-solve = { version = "0.60", default-features = false } 21chalk-solve = { version = "0.64", default-features = false }
22chalk-ir = "0.60" 22chalk-ir = "0.64"
23chalk-recursive = "0.60" 23chalk-recursive = "0.64"
24la-arena = { version = "0.2.0", path = "../../lib/arena" } 24la-arena = { version = "0.2.0", path = "../../lib/arena" }
25 25
26stdx = { path = "../stdx", version = "0.0.0" } 26stdx = { path = "../stdx", version = "0.0.0" }
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index 70c56cc45..2c07494a9 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -6,16 +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 traits::{InEnvironment, Solution}, 16 DebruijnIndex, InEnvironment, Interner, ProjectionTyExt, Solution, Substitution, Ty, TyBuilder,
17 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty, 17 TyKind,
18 TyBuilder, TyKind,
19}; 18};
20 19
21const AUTODEREF_RECURSION_LIMIT: usize = 10; 20const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -37,18 +36,28 @@ pub(crate) fn deref(
37 krate: CrateId, 36 krate: CrateId,
38 ty: InEnvironment<&Canonical<Ty>>, 37 ty: InEnvironment<&Canonical<Ty>>,
39) -> Option<Canonical<Ty>> { 38) -> Option<Canonical<Ty>> {
40 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) {
41 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 41 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
42 } else { 42 } else {
43 deref_by_trait(db, krate, ty) 43 deref_by_trait(db, krate, ty)
44 } 44 }
45} 45}
46 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
47fn deref_by_trait( 55fn deref_by_trait(
48 db: &dyn HirDatabase, 56 db: &dyn HirDatabase,
49 krate: CrateId, 57 krate: CrateId,
50 ty: InEnvironment<&Canonical<Ty>>, 58 ty: InEnvironment<&Canonical<Ty>>,
51) -> Option<Canonical<Ty>> { 59) -> Option<Canonical<Ty>> {
60 let _p = profile::span("deref_by_trait");
52 let deref_trait = match db.lang_item(krate, "deref".into())? { 61 let deref_trait = match db.lang_item(krate, "deref".into())? {
53 LangItemTarget::TraitId(it) => it, 62 LangItemTarget::TraitId(it) => it,
54 _ => return None, 63 _ => return None,
@@ -97,7 +106,7 @@ fn deref_by_trait(
97 binders: CanonicalVarKinds::from_iter( 106 binders: CanonicalVarKinds::from_iter(
98 &Interner, 107 &Interner,
99 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(
100 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 109 VariableKind::Ty(chalk_ir::TyVariableKind::General),
101 chalk_ir::UniverseIndex::ROOT, 110 chalk_ir::UniverseIndex::ROOT,
102 ))), 111 ))),
103 ), 112 ),
@@ -122,23 +131,25 @@ fn deref_by_trait(
122 // assumptions will be broken. We would need to properly introduce 131 // assumptions will be broken. We would need to properly introduce
123 // new variables in that case 132 // new variables in that case
124 133
125 for i in 1..vars.0.binders.len(&Interner) { 134 for i in 1..vars.binders.len(&Interner) {
126 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) 135 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
127 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 136 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
128 { 137 {
129 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 138 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
130 return None; 139 return None;
131 } 140 }
132 } 141 }
133 Some(Canonical { 142 // FIXME: we remove lifetime variables here since they can confuse
143 // the method resolution code later
144 Some(fixup_lifetime_variables(Canonical {
134 value: vars 145 value: vars
135 .0
136 .value 146 .value
137 .at(&Interner, vars.0.value.len(&Interner) - 1) 147 .subst
148 .at(&Interner, vars.value.subst.len(&Interner) - 1)
138 .assert_ty_ref(&Interner) 149 .assert_ty_ref(&Interner)
139 .clone(), 150 .clone(),
140 binders: vars.0.binders.clone(), 151 binders: vars.binders.clone(),
141 }) 152 }))
142 } 153 }
143 Solution::Ambig(_) => { 154 Solution::Ambig(_) => {
144 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution); 155 info!("Ambiguous solution for derefing {:?}: {:?}", ty.goal, solution);
@@ -146,3 +157,32 @@ fn deref_by_trait(
146 } 157 }
147 } 158 }
148} 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
index 4a9a8058f..e25ef866d 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -4,6 +4,7 @@ use std::iter;
4 4
5use chalk_ir::{ 5use chalk_ir::{
6 cast::{Cast, CastTo, Caster}, 6 cast::{Cast, CastTo, Caster},
7 fold::Fold,
7 interner::HasInterner, 8 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar, 9 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9}; 10};
@@ -12,8 +13,8 @@ use smallvec::SmallVec;
12 13
13use crate::{ 14use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, 15 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, 16 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId, 17 TraitRef, Ty, TyDefId, TyExt, TyKind, ValueTyDefId,
17}; 18};
18 19
19/// This is a builder for `Ty` or anything that needs a `Substitution`. 20/// This is a builder for `Ty` or anything that needs a `Substitution`.
@@ -32,8 +33,7 @@ impl<D> TyBuilder<D> {
32 33
33 fn build_internal(self) -> (D, Substitution) { 34 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count); 35 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form 36 let subst = Substitution::from_iter(&Interner, self.vec);
36 let subst = Substitution(self.vec);
37 (self.data, subst) 37 (self.data, subst)
38 } 38 }
39 39
@@ -54,7 +54,7 @@ impl<D> TyBuilder<D> {
54 } 54 }
55 55
56 pub fn fill_with_unknown(self) -> Self { 56 pub fn fill_with_unknown(self) -> Self {
57 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) 57 self.fill(iter::repeat(TyKind::Error.intern(&Interner)))
58 } 58 }
59 59
60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self { 60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
@@ -78,9 +78,12 @@ impl TyBuilder<()> {
78 78
79 pub fn fn_ptr(sig: CallableSig) -> Ty { 79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer { 80 TyKind::Function(FnPointer {
81 num_args: sig.params().len(), 81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, 82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), 83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
84 }) 87 })
85 .intern(&Interner) 88 .intern(&Interner)
86 } 89 }
@@ -138,8 +141,9 @@ impl TyBuilder<hir_def::AdtId> {
138 self.vec.push(fallback().cast(&Interner)); 141 self.vec.push(fallback().cast(&Interner));
139 } else { 142 } else {
140 // each default can depend on the previous parameters 143 // each default can depend on the previous parameters
141 let subst_so_far = Substitution(self.vec.clone()); 144 let subst_so_far = Substitution::from_iter(&Interner, self.vec.clone());
142 self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); 145 self.vec
146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
143 } 147 }
144 } 148 }
145 self 149 self
@@ -192,15 +196,15 @@ impl TyBuilder<TypeAliasId> {
192 } 196 }
193} 197}
194 198
195impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { 199impl<T: HasInterner<Interner = Interner> + Fold<Interner>> TyBuilder<Binders<T>> {
196 fn subst_binders(b: Binders<T>) -> Self { 200 fn subst_binders(b: Binders<T>) -> Self {
197 let param_count = b.num_binders; 201 let param_count = b.binders.len(&Interner);
198 TyBuilder::new(b, param_count) 202 TyBuilder::new(b, param_count)
199 } 203 }
200 204
201 pub fn build(self) -> T { 205 pub fn build(self) -> <T as Fold<Interner>>::Result {
202 let (b, subst) = self.build_internal(); 206 let (b, subst) = self.build_internal();
203 b.subst(&subst) 207 b.substitute(&Interner, &subst)
204 } 208 }
205} 209}
206 210
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
deleted file mode 100644
index df6492113..000000000
--- a/crates/hir_ty/src/chalk_cast.rs
+++ /dev/null
@@ -1,73 +0,0 @@
1//! Implementations of the Chalk `Cast` trait for our types.
2
3use chalk_ir::{
4 cast::{Cast, CastTo},
5 interner::HasInterner,
6};
7
8use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
9
10macro_rules! has_interner {
11 ($t:ty) => {
12 impl HasInterner for $t {
13 type Interner = crate::Interner;
14 }
15 };
16}
17
18has_interner!(WhereClause);
19has_interner!(DomainGoal);
20has_interner!(GenericArg);
21has_interner!(Ty);
22
23impl CastTo<WhereClause> for TraitRef {
24 fn cast_to(self, _interner: &Interner) -> WhereClause {
25 WhereClause::Implemented(self)
26 }
27}
28
29impl CastTo<WhereClause> for AliasEq {
30 fn cast_to(self, _interner: &Interner) -> WhereClause {
31 WhereClause::AliasEq(self)
32 }
33}
34
35impl CastTo<DomainGoal> for WhereClause {
36 fn cast_to(self, _interner: &Interner) -> DomainGoal {
37 DomainGoal::Holds(self)
38 }
39}
40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
47macro_rules! transitive_impl {
48 ($a:ty, $b:ty, $c:ty) => {
49 impl CastTo<$c> for $a {
50 fn cast_to(self, interner: &Interner) -> $c {
51 self.cast::<$b>(interner).cast(interner)
52 }
53 }
54 };
55}
56
57// In Chalk, these can be done as blanket impls, but that doesn't work here
58// because of coherence
59
60transitive_impl!(TraitRef, WhereClause, DomainGoal);
61transitive_impl!(AliasEq, WhereClause, DomainGoal);
62
63macro_rules! reflexive_impl {
64 ($a:ty) => {
65 impl CastTo<$a> for $a {
66 fn cast_to(self, _interner: &Interner) -> $a {
67 self
68 }
69 }
70 };
71}
72
73reflexive_impl!(GenericArg);
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/chalk_db.rs
index 541e6082f..8f054d06b 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/chalk_db.rs
@@ -1,52 +1,47 @@
1//! Conversion code from/to Chalk. 1//! The implementation of `RustIrDatabase` for Chalk, which provides information
2//! about the code that Chalk needs.
2use std::sync::Arc; 3use std::sync::Arc;
3 4
4use log::debug; 5use log::debug;
5 6
6use chalk_ir::{fold::shift::Shift, CanonicalVarKinds}; 7use chalk_ir::{cast::Cast, fold::shift::Shift, CanonicalVarKinds};
7use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait}; 8use chalk_solve::rust_ir::{self, OpaqueTyDatumBound, WellKnownTrait};
8 9
9use base_db::{salsa::InternKey, CrateId}; 10use base_db::CrateId;
10use hir_def::{ 11use hir_def::{
11 lang_item::{lang_attr, LangItemTarget}, 12 lang_item::{lang_attr, LangItemTarget},
12 AssocContainerId, AssocItemId, HasModule, Lookup, TypeAliasId, 13 AssocContainerId, AssocItemId, GenericDefId, HasModule, Lookup, TypeAliasId,
13}; 14};
14use hir_expand::name::name; 15use hir_expand::name::name;
15 16
16use super::ChalkContext;
17use crate::{ 17use crate::{
18 db::HirDatabase, 18 db::HirDatabase,
19 display::HirDisplay, 19 display::HirDisplay,
20 from_assoc_type_id, 20 from_assoc_type_id, from_chalk_trait_id, make_only_type_binders,
21 mapping::{from_chalk, ToChalk, TypeAliasAsValue},
21 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS}, 22 method_resolution::{TyFingerprint, ALL_FLOAT_FPS, ALL_INT_FPS},
22 to_assoc_type_id, to_chalk_trait_id, 23 to_assoc_type_id, to_chalk_trait_id,
24 traits::ChalkContext,
23 utils::generics, 25 utils::generics,
24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, 26 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, Interner, ProjectionTy,
25 TraitRef, Ty, TyBuilder, TyKind, WhereClause, 27 ProjectionTyExt, QuantifiedWhereClause, Substitution, TraitRef, TraitRefExt, Ty, TyBuilder,
28 TyExt, TyKind, WhereClause,
26}; 29};
27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
29};
30
31pub use self::interner::Interner;
32pub(crate) use self::interner::*;
33 30
34pub(super) mod tls; 31pub(crate) type AssociatedTyDatum = chalk_solve::rust_ir::AssociatedTyDatum<Interner>;
35mod interner; 32pub(crate) type TraitDatum = chalk_solve::rust_ir::TraitDatum<Interner>;
36mod mapping; 33pub(crate) type StructDatum = chalk_solve::rust_ir::AdtDatum<Interner>;
37 34pub(crate) type ImplDatum = chalk_solve::rust_ir::ImplDatum<Interner>;
38pub(crate) trait ToChalk { 35pub(crate) type OpaqueTyDatum = chalk_solve::rust_ir::OpaqueTyDatum<Interner>;
39 type Chalk; 36
40 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk; 37pub(crate) type AssocTypeId = chalk_ir::AssocTypeId<Interner>;
41 fn from_chalk(db: &dyn HirDatabase, chalk: Self::Chalk) -> Self; 38pub(crate) type TraitId = chalk_ir::TraitId<Interner>;
42} 39pub(crate) type AdtId = chalk_ir::AdtId<Interner>;
43 40pub(crate) type ImplId = chalk_ir::ImplId<Interner>;
44pub(crate) fn from_chalk<T, ChalkT>(db: &dyn HirDatabase, chalk: ChalkT) -> T 41pub(crate) type AssociatedTyValueId = chalk_solve::rust_ir::AssociatedTyValueId<Interner>;
45where 42pub(crate) type AssociatedTyValue = chalk_solve::rust_ir::AssociatedTyValue<Interner>;
46 T: ToChalk<Chalk = ChalkT>, 43pub(crate) type FnDefDatum = chalk_solve::rust_ir::FnDefDatum<Interner>;
47{ 44pub(crate) type Variances = chalk_ir::Variances<Interner>;
48 T::from_chalk(db, chalk)
49}
50 45
51impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { 46impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
52 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> { 47 fn associated_ty_data(&self, id: AssocTypeId) -> Arc<AssociatedTyDatum> {
@@ -84,9 +79,9 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
84 binders: &CanonicalVarKinds<Interner>, 79 binders: &CanonicalVarKinds<Interner>,
85 ) -> Vec<ImplId> { 80 ) -> Vec<ImplId> {
86 debug!("impls_for_trait {:?}", trait_id); 81 debug!("impls_for_trait {:?}", trait_id);
87 let trait_: hir_def::TraitId = from_chalk(self.db, trait_id); 82 let trait_: hir_def::TraitId = from_chalk_trait_id(trait_id);
88 83
89 let ty: Ty = from_chalk(self.db, parameters[0].assert_ty_ref(&Interner).clone()); 84 let ty: Ty = parameters[0].assert_ty_ref(&Interner).clone();
90 85
91 fn binder_kind( 86 fn binder_kind(
92 ty: &Ty, 87 ty: &Ty,
@@ -103,7 +98,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
103 None 98 None
104 } 99 }
105 100
106 let self_ty_fp = TyFingerprint::for_impl(&ty); 101 let self_ty_fp = TyFingerprint::for_trait_impl(&ty);
107 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) { 102 let fps: &[TyFingerprint] = match binder_kind(&ty, binders) {
108 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS, 103 Some(chalk_ir::TyVariableKind::Integer) => &ALL_INT_FPS,
109 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS, 104 Some(chalk_ir::TyVariableKind::Float) => &ALL_FLOAT_FPS,
@@ -166,7 +161,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
166 Some(LangItemTarget::TraitId(trait_)) => trait_, 161 Some(LangItemTarget::TraitId(trait_)) => trait_,
167 _ => return None, 162 _ => return None,
168 }; 163 };
169 Some(trait_.to_chalk(self.db)) 164 Some(to_chalk_trait_id(trait_))
170 } 165 }
171 166
172 fn program_clauses_for_env( 167 fn program_clauses_for_env(
@@ -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 = TyBuilder::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(&Interner).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 {
@@ -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,7 +413,7 @@ 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());
@@ -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(&Interner)), 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,
@@ -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,7 +531,8 @@ 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());
@@ -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(&Interner)), 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 = generic_params.bound_vars_subst(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
index b7463366b..8c4542956 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,13 +1,305 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use crate::{Interner, Ty, TyKind}; 3use chalk_ir::Mutability;
4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6};
7
8use crate::{
9 db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
10 from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
11 CallableSig, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
12 Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
13};
4 14
5pub trait TyExt { 15pub trait TyExt {
6 fn is_unit(&self) -> bool; 16 fn is_unit(&self) -> bool;
17 fn is_never(&self) -> bool;
18 fn is_unknown(&self) -> bool;
19
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
21 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
24 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
25 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
26
27 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
28 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
29
30 fn strip_references(&self) -> &Ty;
31
32 /// If this is a `dyn Trait`, returns that trait.
33 fn dyn_trait(&self) -> Option<TraitId>;
34
35 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
36 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
37
38 /// FIXME: Get rid of this, it's not a good abstraction
39 fn equals_ctor(&self, other: &Ty) -> bool;
7} 40}
8 41
9impl TyExt for Ty { 42impl TyExt for Ty {
10 fn is_unit(&self) -> bool { 43 fn is_unit(&self) -> bool {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _)) 44 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 } 45 }
46
47 fn is_never(&self) -> bool {
48 matches!(self.kind(&Interner), TyKind::Never)
49 }
50
51 fn is_unknown(&self) -> bool {
52 matches!(self.kind(&Interner), TyKind::Error)
53 }
54
55 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
56 match self.kind(&Interner) {
57 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
58 _ => None,
59 }
60 }
61
62 fn as_tuple(&self) -> Option<&Substitution> {
63 match self.kind(&Interner) {
64 TyKind::Tuple(_, substs) => Some(substs),
65 _ => None,
66 }
67 }
68
69 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
70 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
71 Some(func)
72 } else {
73 None
74 }
75 }
76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
77 match self.kind(&Interner) {
78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, lifetime.clone(), *mutability)),
79 _ => None,
80 }
81 }
82
83 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
84 match self.kind(&Interner) {
85 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
86 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
87 _ => None,
88 }
89 }
90
91 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
92 match *self.kind(&Interner) {
93 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
94 TyKind::FnDef(callable, ..) => {
95 Some(db.lookup_intern_callable_def(callable.into()).into())
96 }
97 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
98 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
99 _ => None,
100 }
101 }
102
103 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
104 match self.kind(&Interner) {
105 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
106 _ => None,
107 }
108 }
109
110 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
111 match self.kind(&Interner) {
112 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
113 TyKind::FnDef(def, parameters) => {
114 let callable_def = db.lookup_intern_callable_def((*def).into());
115 let sig = db.callable_item_signature(callable_def);
116 Some(sig.substitute(&Interner, &parameters))
117 }
118 TyKind::Closure(.., substs) => {
119 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
120 sig_param.callable_sig(db)
121 }
122 _ => None,
123 }
124 }
125
126 fn dyn_trait(&self) -> Option<TraitId> {
127 let trait_ref = match self.kind(&Interner) {
128 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
129 match b.skip_binders() {
130 WhereClause::Implemented(trait_ref) => Some(trait_ref),
131 _ => None,
132 }
133 }),
134 _ => None,
135 }?;
136 Some(from_chalk_trait_id(trait_ref.trait_id))
137 }
138
139 fn strip_references(&self) -> &Ty {
140 let mut t: &Ty = self;
141 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
142 t = ty;
143 }
144 t
145 }
146
147 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
148 match self.kind(&Interner) {
149 TyKind::OpaqueType(opaque_ty_id, ..) => {
150 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
151 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
152 let krate = def.module(db.upcast()).krate();
153 if let Some(future_trait) = db
154 .lang_item(krate, "future_trait".into())
155 .and_then(|item| item.as_trait())
156 {
157 // This is only used by type walking.
158 // Parameters will be walked outside, and projection predicate is not used.
159 // So just provide the Future trait.
160 let impl_bound = Binders::empty(
161 &Interner,
162 WhereClause::Implemented(TraitRef {
163 trait_id: to_chalk_trait_id(future_trait),
164 substitution: Substitution::empty(&Interner),
165 }),
166 );
167 Some(vec![impl_bound])
168 } else {
169 None
170 }
171 }
172 ImplTraitId::ReturnTypeImplTrait(..) => None,
173 }
174 }
175 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
176 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
177 {
178 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
179 db.return_type_impl_traits(func).map(|it| {
180 let data = (*it)
181 .as_ref()
182 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
183 data.substitute(&Interner, &opaque_ty.substitution)
184 })
185 }
186 // It always has an parameter for Future::Output type.
187 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
188 };
189
190 predicates.map(|it| it.into_value_and_skipped_binders().0)
191 }
192 TyKind::Placeholder(idx) => {
193 let id = from_placeholder_idx(db, *idx);
194 let generic_params = db.generic_params(id.parent);
195 let param_data = &generic_params.types[id.local_id];
196 match param_data.provenance {
197 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
198 let substs = TyBuilder::type_params_subst(db, id.parent);
199 let predicates = db
200 .generic_predicates(id.parent)
201 .into_iter()
202 .map(|pred| pred.clone().substitute(&Interner, &substs))
203 .filter(|wc| match &wc.skip_binders() {
204 WhereClause::Implemented(tr) => {
205 &tr.self_type_parameter(&Interner) == self
206 }
207 WhereClause::AliasEq(AliasEq {
208 alias: AliasTy::Projection(proj),
209 ty: _,
210 }) => &proj.self_type_parameter(&Interner) == self,
211 _ => false,
212 })
213 .collect::<Vec<_>>();
214
215 Some(predicates)
216 }
217 _ => None,
218 }
219 }
220 _ => None,
221 }
222 }
223
224 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
225 match self.kind(&Interner) {
226 TyKind::AssociatedType(id, ..) => {
227 match from_assoc_type_id(*id).lookup(db.upcast()).container {
228 AssocContainerId::TraitId(trait_id) => Some(trait_id),
229 _ => None,
230 }
231 }
232 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
233 match from_assoc_type_id(projection_ty.associated_ty_id)
234 .lookup(db.upcast())
235 .container
236 {
237 AssocContainerId::TraitId(trait_id) => Some(trait_id),
238 _ => None,
239 }
240 }
241 _ => None,
242 }
243 }
244
245 fn equals_ctor(&self, other: &Ty) -> bool {
246 match (self.kind(&Interner), other.kind(&Interner)) {
247 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
248 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
249 true
250 }
251 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
252 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
253 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
254 ty_id == ty_id2
255 }
256 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
257 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
258 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
259 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
260 mutability == mutability2
261 }
262 (
263 TyKind::Function(FnPointer { num_binders, sig, .. }),
264 TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }),
265 ) => num_binders == num_binders2 && sig == sig2,
266 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
267 cardinality == cardinality2
268 }
269 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
270 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
271 _ => false,
272 }
273 }
274}
275
276pub trait ProjectionTyExt {
277 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
278 fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
279}
280
281impl ProjectionTyExt for ProjectionTy {
282 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
283 TraitRef {
284 trait_id: to_chalk_trait_id(self.trait_(db)),
285 substitution: self.substitution.clone(),
286 }
287 }
288
289 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
290 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
291 AssocContainerId::TraitId(it) => it,
292 _ => panic!("projection ty without parent trait"),
293 }
294 }
295}
296
297pub trait TraitRefExt {
298 fn hir_trait_id(&self) -> TraitId;
299}
300
301impl TraitRefExt for TraitRef {
302 fn hir_trait_id(&self) -> TraitId {
303 from_chalk_trait_id(self.trait_id)
304 }
13} 305}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 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 1c9f9ede7..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,10 +85,39 @@ 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) {
@@ -109,7 +140,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
109 } 140 }
110 141
111 // Check whether non-snake case identifiers are allowed for this function. 142 // Check whether non-snake case identifiers are allowed for this function.
112 if self.allowed(func.into(), allow::NON_SNAKE_CASE) { 143 if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
113 return; 144 return;
114 } 145 }
115 146
@@ -328,8 +359,9 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
328 fn validate_struct(&mut self, struct_id: StructId) { 359 fn validate_struct(&mut self, struct_id: StructId) {
329 let data = self.db.struct_data(struct_id); 360 let data = self.db.struct_data(struct_id);
330 361
331 let non_camel_case_allowed = self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES); 362 let non_camel_case_allowed =
332 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);
333 365
334 // Check the structure name. 366 // Check the structure name.
335 let struct_name = data.name.to_string(); 367 let struct_name = data.name.to_string();
@@ -461,7 +493,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
461 let data = self.db.enum_data(enum_id); 493 let data = self.db.enum_data(enum_id);
462 494
463 // Check whether non-camel case names are allowed for this enum. 495 // Check whether non-camel case names are allowed for this enum.
464 if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES) { 496 if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
465 return; 497 return;
466 } 498 }
467 499
@@ -584,7 +616,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
584 fn validate_const(&mut self, const_id: ConstId) { 616 fn validate_const(&mut self, const_id: ConstId) {
585 let data = self.db.const_data(const_id); 617 let data = self.db.const_data(const_id);
586 618
587 if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL) { 619 if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
588 return; 620 return;
589 } 621 }
590 622
@@ -632,7 +664,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
632 return; 664 return;
633 } 665 }
634 666
635 if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL) { 667 if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
636 return; 668 return;
637 } 669 }
638 670
@@ -867,23 +899,116 @@ fn main() {
867 fn allow_attributes() { 899 fn allow_attributes() {
868 check_diagnostics( 900 check_diagnostics(
869 r#" 901 r#"
870 #[allow(non_snake_case)] 902#[allow(non_snake_case)]
871 fn NonSnakeCaseName(SOME_VAR: u8) -> u8{ 903fn NonSnakeCaseName(SOME_VAR: u8) -> u8{
872 let OtherVar = SOME_VAR + 1; 904 // cov_flags generated output from elsewhere in this file
873 OtherVar 905 extern "C" {
906 #[no_mangle]
907 static lower_case: u8;
874 } 908 }
875 909
876 #[allow(non_snake_case, non_camel_case_types)] 910 let OtherVar = SOME_VAR + 1;
877 pub struct some_type { 911 OtherVar
878 SOME_FIELD: u8, 912}
879 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 );
880 } 942 }
881 943
882 #[allow(non_upper_case_globals)] 944 #[test]
883 pub const some_const: u8 = 10; 945 fn allow_attributes_crate_attr() {
946 check_diagnostics(
947 r#"
948#![allow(non_snake_case)]
884 949
885 #[allow(non_upper_case_globals)] 950mod F {
886 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}
887 "#, 1012 "#,
888 ); 1013 );
889 } 1014 }
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 8169b759f..79602c3dd 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -14,7 +14,6 @@ use crate::{
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data,
18 AdtId, InferenceResult, Interner, TyExt, TyKind, 17 AdtId, InferenceResult, Interner, TyExt, TyKind,
19}; 18};
20 19
@@ -104,7 +103,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
104 let root = source_ptr.file_syntax(db.upcast()); 103 let root = source_ptr.file_syntax(db.upcast());
105 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { 104 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) {
106 if let Some(_) = record_expr.record_expr_field_list() { 105 if let Some(_) = record_expr.record_expr_field_list() {
107 let variant_data = variant_data(db.upcast(), variant_def); 106 let variant_data = variant_def.variant_data(db.upcast());
108 let missed_fields = missed_fields 107 let missed_fields = missed_fields
109 .into_iter() 108 .into_iter()
110 .map(|idx| variant_data.fields()[idx].name.clone()) 109 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -135,7 +134,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
135 let root = source_ptr.file_syntax(db.upcast()); 134 let root = source_ptr.file_syntax(db.upcast());
136 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { 135 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
137 if let Some(_) = record_pat.record_pat_field_list() { 136 if let Some(_) = record_pat.record_pat_field_list() {
138 let variant_data = variant_data(db.upcast(), variant_def); 137 let variant_data = variant_def.variant_data(db.upcast());
139 let missed_fields = missed_fields 138 let missed_fields = missed_fields
140 .into_iter() 139 .into_iter()
141 .map(|idx| variant_data.fields()[idx].name.clone()) 140 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -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
@@ -452,7 +452,7 @@ pub fn record_literal_missing_fields(
452 return None; 452 return None;
453 } 453 }
454 454
455 let variant_data = variant_data(db.upcast(), variant_def); 455 let variant_data = variant_def.variant_data(db.upcast());
456 456
457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
458 let missed_fields: Vec<LocalFieldId> = variant_data 458 let missed_fields: Vec<LocalFieldId> = variant_data
@@ -482,7 +482,7 @@ pub fn record_pattern_missing_fields(
482 return None; 482 return None;
483 } 483 }
484 484
485 let variant_data = variant_data(db.upcast(), variant_def); 485 let variant_data = variant_def.variant_data(db.upcast());
486 486
487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
488 let missed_fields: Vec<LocalFieldId> = variant_data 488 let missed_fields: Vec<LocalFieldId> = variant_data
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 34291578a..e9762622f 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index b5efe9df5..ed97dc0e3 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,9 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; 14use crate::{
15 db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind,
16};
15 17
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 19 owner: DefWithBodyId,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 385bd9405..4fb7d9cf2 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,9 +1,15 @@
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::{
12 body,
7 db::DefDatabase, 13 db::DefDatabase,
8 find_path, 14 find_path,
9 generics::TypeParamProvenance, 15 generics::TypeParamProvenance,
@@ -13,13 +19,15 @@ use hir_def::{
13 visibility::Visibility, 19 visibility::Visibility,
14 AssocContainerId, Lookup, ModuleId, TraitId, 20 AssocContainerId, Lookup, ModuleId, TraitId,
15}; 21};
16use hir_expand::name::Name; 22use hir_expand::{hygiene::Hygiene, name::Name};
17 23
18use crate::{ 24use crate::{
19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 25 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, 26 from_placeholder_idx, lt_from_placeholder_idx, mapping::from_chalk, primitive, subst_prefix,
21 CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, 27 to_assoc_type_id, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, Const,
22 ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, 28 ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, LifetimeData,
29 LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt, QuantifiedWhereClause,
30 Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
23}; 31};
24 32
25pub struct HirFormatter<'a> { 33pub struct HirFormatter<'a> {
@@ -46,6 +54,10 @@ pub trait HirDisplay {
46 where 54 where
47 Self: Sized, 55 Self: Sized,
48 { 56 {
57 assert!(
58 !matches!(display_target, DisplayTarget::SourceCode { .. }),
59 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
60 );
49 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target } 61 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
50 } 62 }
51 63
@@ -230,7 +242,7 @@ where
230 Err(HirDisplayError::FmtError) => Err(fmt::Error), 242 Err(HirDisplayError::FmtError) => Err(fmt::Error),
231 Err(HirDisplayError::DisplaySourceCodeError(_)) => { 243 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
232 // This should never happen 244 // This should never happen
233 panic!("HirDisplay failed when calling Display::fmt!") 245 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
234 } 246 }
235 } 247 }
236 } 248 }
@@ -251,16 +263,12 @@ impl HirDisplay for ProjectionTy {
251 } 263 }
252 264
253 let trait_ = f.db.trait_data(self.trait_(f.db)); 265 let trait_ = f.db.trait_data(self.trait_(f.db));
254 let first_parameter = self.self_type_parameter().into_displayable( 266 write!(f, "<")?;
255 f.db, 267 self.self_type_parameter(&Interner).hir_fmt(f)?;
256 f.max_size, 268 write!(f, " as {}", trait_.name)?;
257 f.omit_verbose_types,
258 f.display_target,
259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len(&Interner) > 1 { 269 if self.substitution.len(&Interner) > 1 {
262 write!(f, "<")?; 270 write!(f, "<")?;
263 f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; 271 f.write_joined(&self.substitution.as_slice(&Interner)[1..], ", ")?;
264 write!(f, ">")?; 272 write!(f, ">")?;
265 } 273 }
266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 274 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -282,10 +290,35 @@ impl HirDisplay for GenericArg {
282 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 290 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
283 match self.interned() { 291 match self.interned() {
284 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), 292 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
293 crate::GenericArgData::Lifetime(lt) => lt.hir_fmt(f),
294 crate::GenericArgData::Const(c) => c.hir_fmt(f),
295 }
296 }
297}
298
299impl HirDisplay for Const {
300 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
301 let data = self.interned();
302 match data.value {
303 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
304 ConstValue::InferenceVar(..) => write!(f, "_"),
305 ConstValue::Placeholder(idx) => {
306 let id = const_from_placeholder_idx(f.db, idx);
307 let generics = generics(f.db.upcast(), id.parent);
308 let param_data = &generics.params.consts[id.local_id];
309 write!(f, "{}", param_data.name)
310 }
311 ConstValue::Concrete(_) => write!(f, "_"),
285 } 312 }
286 } 313 }
287} 314}
288 315
316impl HirDisplay for BoundVar {
317 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
318 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
319 }
320}
321
289impl HirDisplay for Ty { 322impl HirDisplay for Ty {
290 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 323 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
291 if f.should_truncate() { 324 if f.should_truncate() {
@@ -305,15 +338,14 @@ impl HirDisplay for Ty {
305 t.hir_fmt(f)?; 338 t.hir_fmt(f)?;
306 write!(f, "]")?; 339 write!(f, "]")?;
307 } 340 }
308 TyKind::Array(t) => { 341 TyKind::Array(t, c) => {
309 write!(f, "[")?; 342 write!(f, "[")?;
310 t.hir_fmt(f)?; 343 t.hir_fmt(f)?;
311 write!(f, "; _]")?; 344 write!(f, "; ")?;
345 c.hir_fmt(f)?;
346 write!(f, "]")?;
312 } 347 }
313 TyKind::Raw(m, t) | TyKind::Ref(m, t) => { 348 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
314 let ty_display =
315 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
316
317 if matches!(self.kind(&Interner), TyKind::Raw(..)) { 349 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
318 write!( 350 write!(
319 f, 351 f,
@@ -352,8 +384,8 @@ impl HirDisplay for Ty {
352 let data = (*datas) 384 let data = (*datas)
353 .as_ref() 385 .as_ref()
354 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 386 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
355 let bounds = data.subst(parameters); 387 let bounds = data.substitute(&Interner, parameters);
356 bounds.value 388 bounds.into_value_and_skipped_binders().0
357 } else { 389 } else {
358 Vec::new() 390 Vec::new()
359 } 391 }
@@ -368,16 +400,16 @@ impl HirDisplay for Ty {
368 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) 400 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
369 && predicates.len() <= 2 401 && predicates.len() <= 2
370 { 402 {
371 return write!(f, "{}", ty_display); 403 return t.hir_fmt(f);
372 } 404 }
373 } 405 }
374 406
375 if predicates.len() > 1 { 407 if predicates.len() > 1 {
376 write!(f, "(")?; 408 write!(f, "(")?;
377 write!(f, "{}", ty_display)?; 409 t.hir_fmt(f)?;
378 write!(f, ")")?; 410 write!(f, ")")?;
379 } else { 411 } else {
380 write!(f, "{}", ty_display)?; 412 t.hir_fmt(f)?;
381 } 413 }
382 } 414 }
383 TyKind::Tuple(_, substs) => { 415 TyKind::Tuple(_, substs) => {
@@ -387,7 +419,7 @@ impl HirDisplay for Ty {
387 write!(f, ",)")?; 419 write!(f, ",)")?;
388 } else { 420 } else {
389 write!(f, "(")?; 421 write!(f, "(")?;
390 f.write_joined(&*substs.0, ", ")?; 422 f.write_joined(&*substs.as_slice(&Interner), ", ")?;
391 write!(f, ")")?; 423 write!(f, ")")?;
392 } 424 }
393 } 425 }
@@ -397,7 +429,7 @@ impl HirDisplay for Ty {
397 } 429 }
398 TyKind::FnDef(def, parameters) => { 430 TyKind::FnDef(def, parameters) => {
399 let def = from_chalk(f.db, *def); 431 let def = from_chalk(f.db, *def);
400 let sig = f.db.callable_item_signature(def).subst(parameters); 432 let sig = f.db.callable_item_signature(def).substitute(&Interner, parameters);
401 match def { 433 match def {
402 CallableDefId::FunctionId(ff) => { 434 CallableDefId::FunctionId(ff) => {
403 write!(f, "fn {}", f.db.function_data(ff).name)? 435 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -415,7 +447,7 @@ impl HirDisplay for Ty {
415 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 447 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
416 if total_len > 0 { 448 if total_len > 0 {
417 write!(f, "<")?; 449 write!(f, "<")?;
418 f.write_joined(&parameters.0[..total_len], ", ")?; 450 f.write_joined(&parameters.as_slice(&Interner)[..total_len], ", ")?;
419 write!(f, ">")?; 451 write!(f, ">")?;
420 } 452 }
421 } 453 }
@@ -424,14 +456,8 @@ impl HirDisplay for Ty {
424 write!(f, ")")?; 456 write!(f, ")")?;
425 let ret = sig.ret(); 457 let ret = sig.ret();
426 if !ret.is_unit() { 458 if !ret.is_unit() {
427 let ret_display = ret.into_displayable( 459 write!(f, " -> ")?;
428 f.db, 460 ret.hir_fmt(f)?;
429 f.max_size,
430 f.omit_verbose_types,
431 f.display_target,
432 );
433
434 write!(f, " -> {}", ret_display)?;
435 } 461 }
436 } 462 }
437 TyKind::Adt(AdtId(def_id), parameters) => { 463 TyKind::Adt(AdtId(def_id), parameters) => {
@@ -468,7 +494,7 @@ impl HirDisplay for Ty {
468 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 494 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
469 .filter(|defaults| !defaults.is_empty()) 495 .filter(|defaults| !defaults.is_empty())
470 { 496 {
471 None => parameters.0.as_ref(), 497 None => parameters.as_slice(&Interner),
472 Some(default_parameters) => { 498 Some(default_parameters) => {
473 let mut default_from = 0; 499 let mut default_from = 0;
474 for (i, parameter) in parameters.iter(&Interner).enumerate() { 500 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -476,13 +502,15 @@ impl HirDisplay for Ty {
476 parameter.assert_ty_ref(&Interner).kind(&Interner), 502 parameter.assert_ty_ref(&Interner).kind(&Interner),
477 default_parameters.get(i), 503 default_parameters.get(i),
478 ) { 504 ) {
479 (&TyKind::Unknown, _) | (_, None) => { 505 (&TyKind::Error, _) | (_, None) => {
480 default_from = i + 1; 506 default_from = i + 1;
481 } 507 }
482 (_, Some(default_parameter)) => { 508 (_, Some(default_parameter)) => {
483 let actual_default = default_parameter 509 let actual_default =
484 .clone() 510 default_parameter.clone().substitute(
485 .subst(&parameters.prefix(i)); 511 &Interner,
512 &subst_prefix(parameters, i),
513 );
486 if parameter.assert_ty_ref(&Interner) != &actual_default 514 if parameter.assert_ty_ref(&Interner) != &actual_default
487 { 515 {
488 default_from = i + 1; 516 default_from = i + 1;
@@ -490,11 +518,11 @@ impl HirDisplay for Ty {
490 } 518 }
491 } 519 }
492 } 520 }
493 &parameters.0[0..default_from] 521 &parameters.as_slice(&Interner)[0..default_from]
494 } 522 }
495 } 523 }
496 } else { 524 } else {
497 parameters.0.as_ref() 525 parameters.as_slice(&Interner)
498 }; 526 };
499 if !parameters_to_write.is_empty() { 527 if !parameters_to_write.is_empty() {
500 write!(f, "<")?; 528 write!(f, "<")?;
@@ -517,7 +545,7 @@ impl HirDisplay for Ty {
517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 545 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
518 if parameters.len(&Interner) > 0 { 546 if parameters.len(&Interner) > 0 {
519 write!(f, "<")?; 547 write!(f, "<")?;
520 f.write_joined(&*parameters.0, ", ")?; 548 f.write_joined(&*parameters.as_slice(&Interner), ", ")?;
521 write!(f, ">")?; 549 write!(f, ">")?;
522 } 550 }
523 } else { 551 } else {
@@ -529,7 +557,7 @@ impl HirDisplay for Ty {
529 projection_ty.hir_fmt(f)?; 557 projection_ty.hir_fmt(f)?;
530 } 558 }
531 } 559 }
532 TyKind::ForeignType(type_alias) => { 560 TyKind::Foreign(type_alias) => {
533 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias)); 561 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
534 write!(f, "{}", type_alias.name)?; 562 write!(f, "{}", type_alias.name)?;
535 } 563 }
@@ -542,8 +570,8 @@ impl HirDisplay for Ty {
542 let data = (*datas) 570 let data = (*datas)
543 .as_ref() 571 .as_ref()
544 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 572 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
545 let bounds = data.subst(&parameters); 573 let bounds = data.substitute(&Interner, &parameters);
546 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 574 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
547 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 575 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
548 } 576 }
549 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 577 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
@@ -571,13 +599,8 @@ impl HirDisplay for Ty {
571 write!(f, "|")?; 599 write!(f, "|")?;
572 }; 600 };
573 601
574 let ret_display = sig.ret().into_displayable( 602 write!(f, " -> ")?;
575 f.db, 603 sig.ret().hir_fmt(f)?;
576 f.max_size,
577 f.omit_verbose_types,
578 f.display_target,
579 );
580 write!(f, " -> {}", ret_display)?;
581 } else { 604 } else {
582 write!(f, "{{closure}}")?; 605 write!(f, "{{closure}}")?;
583 } 606 }
@@ -592,25 +615,26 @@ impl HirDisplay for Ty {
592 } 615 }
593 TypeParamProvenance::ArgumentImplTrait => { 616 TypeParamProvenance::ArgumentImplTrait => {
594 let substs = generics.type_params_subst(f.db); 617 let substs = generics.type_params_subst(f.db);
595 let bounds = f 618 let bounds =
596 .db 619 f.db.generic_predicates(id.parent)
597 .generic_predicates(id.parent) 620 .into_iter()
598 .into_iter() 621 .map(|pred| pred.clone().substitute(&Interner, &substs))
599 .map(|pred| pred.clone().subst(&substs)) 622 .filter(|wc| match &wc.skip_binders() {
600 .filter(|wc| match &wc.skip_binders() { 623 WhereClause::Implemented(tr) => {
601 WhereClause::Implemented(tr) => tr.self_type_parameter() == self, 624 &tr.self_type_parameter(&Interner) == self
602 WhereClause::AliasEq(AliasEq { 625 }
603 alias: AliasTy::Projection(proj), 626 WhereClause::AliasEq(AliasEq {
604 ty: _, 627 alias: AliasTy::Projection(proj),
605 }) => proj.self_type_parameter() == self, 628 ty: _,
606 _ => false, 629 }) => &proj.self_type_parameter(&Interner) == self,
607 }) 630 _ => false,
608 .collect::<Vec<_>>(); 631 })
632 .collect::<Vec<_>>();
609 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; 633 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
610 } 634 }
611 } 635 }
612 } 636 }
613 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 637 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
614 TyKind::Dyn(dyn_ty) => { 638 TyKind::Dyn(dyn_ty) => {
615 write_bounds_like_dyn_trait_with_prefix( 639 write_bounds_like_dyn_trait_with_prefix(
616 "dyn", 640 "dyn",
@@ -628,15 +652,15 @@ impl HirDisplay for Ty {
628 let data = (*datas) 652 let data = (*datas)
629 .as_ref() 653 .as_ref()
630 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 654 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
631 let bounds = data.subst(&opaque_ty.substitution); 655 let bounds = data.substitute(&Interner, &opaque_ty.substitution);
632 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 656 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
633 } 657 }
634 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 658 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
635 write!(f, "{{async block}}")?; 659 write!(f, "{{async block}}")?;
636 } 660 }
637 }; 661 };
638 } 662 }
639 TyKind::Unknown => { 663 TyKind::Error => {
640 if f.display_target.is_source_code() { 664 if f.display_target.is_source_code() {
641 return Err(HirDisplayError::DisplaySourceCodeError( 665 return Err(HirDisplayError::DisplaySourceCodeError(
642 DisplaySourceCodeError::UnknownType, 666 DisplaySourceCodeError::UnknownType,
@@ -645,6 +669,8 @@ impl HirDisplay for Ty {
645 write!(f, "{{unknown}}")?; 669 write!(f, "{{unknown}}")?;
646 } 670 }
647 TyKind::InferenceVar(..) => write!(f, "_")?, 671 TyKind::InferenceVar(..) => write!(f, "_")?,
672 TyKind::Generator(..) => write!(f, "{{generator}}")?,
673 TyKind::GeneratorWitness(..) => write!(f, "{{generator witness}}")?,
648 } 674 }
649 Ok(()) 675 Ok(())
650 } 676 }
@@ -664,9 +690,8 @@ impl HirDisplay for CallableSig {
664 write!(f, ")")?; 690 write!(f, ")")?;
665 let ret = self.ret(); 691 let ret = self.ret();
666 if !ret.is_unit() { 692 if !ret.is_unit() {
667 let ret_display = 693 write!(f, " -> ")?;
668 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 694 ret.hir_fmt(f)?;
669 write!(f, " -> {}", ret_display)?;
670 } 695 }
671 Ok(()) 696 Ok(())
672 } 697 }
@@ -723,17 +748,17 @@ fn write_bounds_like_dyn_trait(
723 if !first { 748 if !first {
724 write!(f, " + ")?; 749 write!(f, " + ")?;
725 } 750 }
726 // We assume that the self type is $0 (i.e. the 751 // We assume that the self type is ^0.0 (i.e. the
727 // existential) here, which is the only thing that's 752 // existential) here, which is the only thing that's
728 // possible in actual Rust, and hence don't print it 753 // possible in actual Rust, and hence don't print it
729 write!(f, "{}", f.db.trait_data(trait_).name)?; 754 write!(f, "{}", f.db.trait_data(trait_).name)?;
730 if let [_, params @ ..] = &*trait_ref.substitution.0 { 755 if let [_, params @ ..] = &*trait_ref.substitution.as_slice(&Interner) {
731 if is_fn_trait { 756 if is_fn_trait {
732 if let Some(args) = 757 if let Some(args) =
733 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 758 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
734 { 759 {
735 write!(f, "(")?; 760 write!(f, "(")?;
736 f.write_joined(&*args.0, ", ")?; 761 f.write_joined(args.as_slice(&Interner), ", ")?;
737 write!(f, ")")?; 762 write!(f, ")")?;
738 } 763 }
739 } else if !params.is_empty() { 764 } else if !params.is_empty() {
@@ -765,6 +790,10 @@ fn write_bounds_like_dyn_trait(
765 } 790 }
766 ty.hir_fmt(f)?; 791 ty.hir_fmt(f)?;
767 } 792 }
793
794 // FIXME implement these
795 WhereClause::LifetimeOutlives(_) => {}
796 WhereClause::TypeOutlives(_) => {}
768 } 797 }
769 first = false; 798 first = false;
770 } 799 }
@@ -774,31 +803,29 @@ fn write_bounds_like_dyn_trait(
774 Ok(()) 803 Ok(())
775} 804}
776 805
777impl TraitRef { 806fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
778 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> { 807 if f.should_truncate() {
779 if f.should_truncate() { 808 return write!(f, "{}", TYPE_HINT_TRUNCATION);
780 return write!(f, "{}", TYPE_HINT_TRUNCATION); 809 }
781 }
782 810
783 self.self_type_parameter().hir_fmt(f)?; 811 tr.self_type_parameter(&Interner).hir_fmt(f)?;
784 if use_as { 812 if use_as {
785 write!(f, " as ")?; 813 write!(f, " as ")?;
786 } else { 814 } else {
787 write!(f, ": ")?; 815 write!(f, ": ")?;
788 } 816 }
789 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; 817 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
790 if self.substitution.len(&Interner) > 1 { 818 if tr.substitution.len(&Interner) > 1 {
791 write!(f, "<")?; 819 write!(f, "<")?;
792 f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; 820 f.write_joined(&tr.substitution.as_slice(&Interner)[1..], ", ")?;
793 write!(f, ">")?; 821 write!(f, ">")?;
794 }
795 Ok(())
796 } 822 }
823 Ok(())
797} 824}
798 825
799impl HirDisplay for TraitRef { 826impl HirDisplay for TraitRef {
800 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 827 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
801 self.hir_fmt_ext(f, false) 828 fmt_trait_ref(self, f, false)
802 } 829 }
803} 830}
804 831
@@ -812,7 +839,7 @@ impl HirDisplay for WhereClause {
812 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 839 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
813 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 840 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
814 write!(f, "<")?; 841 write!(f, "<")?;
815 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 842 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
816 write!( 843 write!(
817 f, 844 f,
818 ">::{} = ", 845 ">::{} = ",
@@ -821,20 +848,44 @@ impl HirDisplay for WhereClause {
821 ty.hir_fmt(f)?; 848 ty.hir_fmt(f)?;
822 } 849 }
823 WhereClause::AliasEq(_) => write!(f, "{{error}}")?, 850 WhereClause::AliasEq(_) => write!(f, "{{error}}")?,
851
852 // FIXME implement these
853 WhereClause::TypeOutlives(..) => {}
854 WhereClause::LifetimeOutlives(..) => {}
824 } 855 }
825 Ok(()) 856 Ok(())
826 } 857 }
827} 858}
828 859
860impl HirDisplay for LifetimeOutlives {
861 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
862 self.a.hir_fmt(f)?;
863 write!(f, ": ")?;
864 self.b.hir_fmt(f)
865 }
866}
867
829impl HirDisplay for Lifetime { 868impl HirDisplay for Lifetime {
830 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 869 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
870 self.interned().hir_fmt(f)
871 }
872}
873
874impl HirDisplay for LifetimeData {
875 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
831 match self { 876 match self {
832 Lifetime::Parameter(id) => { 877 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
878 LifetimeData::InferenceVar(_) => write!(f, "_"),
879 LifetimeData::Placeholder(idx) => {
880 let id = lt_from_placeholder_idx(f.db, *idx);
833 let generics = generics(f.db.upcast(), id.parent); 881 let generics = generics(f.db.upcast(), id.parent);
834 let param_data = &generics.params.lifetimes[id.local_id]; 882 let param_data = &generics.params.lifetimes[id.local_id];
835 write!(f, "{}", &param_data.name) 883 write!(f, "{}", param_data.name)
836 } 884 }
837 Lifetime::Static => write!(f, "'static"), 885 LifetimeData::Static => write!(f, "'static"),
886 LifetimeData::Empty(_) => Ok(()),
887 LifetimeData::Erased => Ok(()),
888 LifetimeData::Phantom(_, _) => Ok(()),
838 } 889 }
839 } 890 }
840} 891}
@@ -845,9 +896,11 @@ impl HirDisplay for DomainGoal {
845 DomainGoal::Holds(wc) => { 896 DomainGoal::Holds(wc) => {
846 write!(f, "Holds(")?; 897 write!(f, "Holds(")?;
847 wc.hir_fmt(f)?; 898 wc.hir_fmt(f)?;
848 write!(f, ")") 899 write!(f, ")")?;
849 } 900 }
901 _ => write!(f, "?")?,
850 } 902 }
903 Ok(())
851 } 904 }
852} 905}
853 906
@@ -945,6 +998,18 @@ impl HirDisplay for TypeRef {
945 write!(f, "dyn ")?; 998 write!(f, "dyn ")?;
946 f.write_joined(bounds, " + ")?; 999 f.write_joined(bounds, " + ")?;
947 } 1000 }
1001 TypeRef::Macro(macro_call) => {
1002 let macro_call = macro_call.to_node(f.db.upcast());
1003 let ctx = body::LowerCtx::with_hygiene(&Hygiene::new_unhygienic());
1004 match macro_call.path() {
1005 Some(path) => match Path::from_src(path, &ctx) {
1006 Some(path) => path.hir_fmt(f)?,
1007 None => write!(f, "{{macro}}")?,
1008 },
1009 None => write!(f, "{{macro}}")?,
1010 }
1011 write!(f, "!(..)")?;
1012 }
948 TypeRef::Error => write!(f, "{{error}}")?, 1013 TypeRef::Error => write!(f, "{{error}}")?,
949 } 1014 }
950 Ok(()) 1015 Ok(())
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 1b1d4458c..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, 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, AliasEq, AliasTy, Interner, TyBuilder, TyKind, 44 lower::ImplTraitLoweringMode, to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner,
45 TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -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 }
@@ -247,7 +238,7 @@ impl<'a> InferenceContext<'a> {
247 table: unify::InferenceTable::new(), 238 table: unify::InferenceTable::new(),
248 obligations: Vec::default(), 239 obligations: Vec::default(),
249 last_obligations_check: None, 240 last_obligations_check: None,
250 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature 241 return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature
251 trait_env: owner 242 trait_env: owner
252 .as_generic_def_id() 243 .as_generic_def_id()
253 .map_or_else(Default::default, |d| db.trait_environment(d)), 244 .map_or_else(Default::default, |d| db.trait_environment(d)),
@@ -261,7 +252,7 @@ impl<'a> InferenceContext<'a> {
261 } 252 }
262 253
263 fn err_ty(&self) -> Ty { 254 fn err_ty(&self) -> Ty {
264 TyKind::Unknown.intern(&Interner) 255 TyKind::Error.intern(&Interner)
265 } 256 }
266 257
267 fn resolve_all(mut self) -> InferenceResult { 258 fn resolve_all(mut self) -> InferenceResult {
@@ -326,13 +317,13 @@ impl<'a> InferenceContext<'a> {
326 /// 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.
327 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 318 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
328 match ty.kind(&Interner) { 319 match ty.kind(&Interner) {
329 TyKind::Unknown => self.table.new_type_var(), 320 TyKind::Error => self.table.new_type_var(),
330 _ => ty, 321 _ => ty,
331 } 322 }
332 } 323 }
333 324
334 fn insert_type_vars(&mut self, ty: Ty) -> Ty { 325 fn insert_type_vars(&mut self, ty: Ty) -> Ty {
335 ty.fold(&mut |ty| self.insert_type_vars_shallow(ty)) 326 fold_tys(ty, |ty, _| self.insert_type_vars_shallow(ty), DebruijnIndex::INNERMOST)
336 } 327 }
337 328
338 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
@@ -345,17 +336,24 @@ impl<'a> InferenceContext<'a> {
345 self.last_obligations_check = Some(self.table.revision); 336 self.last_obligations_check = Some(self.table.revision);
346 let obligations = mem::replace(&mut self.obligations, Vec::new()); 337 let obligations = mem::replace(&mut self.obligations, Vec::new());
347 for obligation in obligations { 338 for obligation in obligations {
348 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 339 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
349 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
350 let solution = 341 let solution =
351 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
352 343
353 match solution { 344 match solution {
354 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
355 canonicalized.apply_solution(self, substs.0); 346 canonicalized.apply_solution(
347 self,
348 Canonical {
349 binders: canonical_subst.binders,
350 // FIXME: handle constraints
351 value: canonical_subst.value.subst,
352 },
353 );
356 } 354 }
357 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
358 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
359 self.obligations.push(obligation); 357 self.obligations.push(obligation);
360 } 358 }
361 Some(_) => { 359 Some(_) => {
@@ -436,12 +434,16 @@ impl<'a> InferenceContext<'a> {
436 /// to do it as well. 434 /// to do it as well.
437 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
438 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
439 ty.fold(&mut |ty| match ty.kind(&Interner) { 437 fold_tys(
440 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 ty,
441 self.normalize_projection_ty(proj_ty.clone()) 439 |ty, _| match ty.kind(&Interner) {
442 } 440 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
443 _ => ty, 441 self.normalize_projection_ty(proj_ty.clone())
444 }) 442 }
443 _ => ty,
444 },
445 DebruijnIndex::INNERMOST,
446 )
445 } 447 }
446 448
447 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty { 449 fn normalize_projection_ty(&mut self, proj_ty: ProjectionTy) -> Ty {
@@ -470,55 +472,32 @@ impl<'a> InferenceContext<'a> {
470 TypeNs::AdtId(AdtId::StructId(strukt)) => { 472 TypeNs::AdtId(AdtId::StructId(strukt)) => {
471 let substs = ctx.substs_from_path(path, strukt.into(), true); 473 let substs = ctx.substs_from_path(path, strukt.into(), true);
472 let ty = self.db.ty(strukt.into()); 474 let ty = self.db.ty(strukt.into());
473 let ty = self.insert_type_vars(ty.subst(&substs)); 475 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
474 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) 476 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
475 } 477 }
476 TypeNs::AdtId(AdtId::UnionId(u)) => { 478 TypeNs::AdtId(AdtId::UnionId(u)) => {
477 let substs = ctx.substs_from_path(path, u.into(), true); 479 let substs = ctx.substs_from_path(path, u.into(), true);
478 let ty = self.db.ty(u.into()); 480 let ty = self.db.ty(u.into());
479 let ty = self.insert_type_vars(ty.subst(&substs)); 481 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
480 forbid_unresolved_segments((ty, Some(u.into())), unresolved) 482 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
481 } 483 }
482 TypeNs::EnumVariantId(var) => { 484 TypeNs::EnumVariantId(var) => {
483 let substs = ctx.substs_from_path(path, var.into(), true); 485 let substs = ctx.substs_from_path(path, var.into(), true);
484 let ty = self.db.ty(var.parent.into()); 486 let ty = self.db.ty(var.parent.into());
485 let ty = self.insert_type_vars(ty.subst(&substs)); 487 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
486 forbid_unresolved_segments((ty, Some(var.into())), unresolved) 488 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
487 } 489 }
488 TypeNs::SelfType(impl_id) => { 490 TypeNs::SelfType(impl_id) => {
489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 491 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
490 let substs = generics.type_params_subst(self.db); 492 let substs = generics.type_params_subst(self.db);
491 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 493 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
492 match unresolved { 494 self.resolve_variant_on_alias(ty, unresolved, path)
493 None => {
494 let variant = ty_variant(&ty);
495 (ty, variant)
496 }
497 Some(1) => {
498 let segment = path.mod_path().segments().last().unwrap();
499 // this could be an enum variant or associated type
500 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
501 let enum_data = self.db.enum_data(enum_id);
502 if let Some(local_id) = enum_data.variant(segment) {
503 let variant = EnumVariantId { parent: enum_id, local_id };
504 return (ty, Some(variant.into()));
505 }
506 }
507 // FIXME potentially resolve assoc type
508 (self.err_ty(), None)
509 }
510 Some(_) => {
511 // FIXME diagnostic
512 (self.err_ty(), None)
513 }
514 }
515 } 495 }
516 TypeNs::TypeAliasId(it) => { 496 TypeNs::TypeAliasId(it) => {
517 let ty = TyBuilder::def_ty(self.db, it.into()) 497 let ty = TyBuilder::def_ty(self.db, it.into())
518 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 498 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
519 .build(); 499 .build();
520 let variant = ty_variant(&ty); 500 self.resolve_variant_on_alias(ty, unresolved, path)
521 forbid_unresolved_segments((ty, variant), unresolved)
522 } 501 }
523 TypeNs::AdtSelfType(_) => { 502 TypeNs::AdtSelfType(_) => {
524 // FIXME this could happen in array size expressions, once we're checking them 503 // FIXME this could happen in array size expressions, once we're checking them
@@ -542,19 +521,46 @@ impl<'a> InferenceContext<'a> {
542 result 521 result
543 } else { 522 } else {
544 // FIXME diagnostic 523 // FIXME diagnostic
545 (TyKind::Unknown.intern(&Interner), None) 524 (TyKind::Error.intern(&Interner), None)
546 } 525 }
547 } 526 }
527 }
548 528
549 fn ty_variant(ty: &Ty) -> Option<VariantId> { 529 fn resolve_variant_on_alias(
550 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 530 &mut self,
551 AdtId::StructId(s) => Some(VariantId::StructId(s)), 531 ty: Ty,
552 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 532 unresolved: Option<usize>,
553 AdtId::EnumId(_) => { 533 path: &Path,
554 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` 534 ) -> (Ty, Option<VariantId>) {
555 None 535 match unresolved {
536 None => {
537 let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
538 AdtId::StructId(s) => Some(VariantId::StructId(s)),
539 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
540 AdtId::EnumId(_) => {
541 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
542 None
543 }
544 });
545 (ty, variant)
546 }
547 Some(1) => {
548 let segment = path.mod_path().segments().last().unwrap();
549 // this could be an enum variant or associated type
550 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
551 let enum_data = self.db.enum_data(enum_id);
552 if let Some(local_id) = enum_data.variant(segment) {
553 let variant = EnumVariantId { parent: enum_id, local_id };
554 return (ty, Some(variant.into()));
555 }
556 } 556 }
557 }) 557 // FIXME potentially resolve assoc type
558 (self.err_ty(), None)
559 }
560 Some(_) => {
561 // FIXME diagnostic
562 (self.err_ty(), None)
563 }
558 } 564 }
559 } 565 }
560 566
@@ -692,25 +698,6 @@ impl<'a> InferenceContext<'a> {
692 } 698 }
693} 699}
694 700
695/// The kinds of placeholders we need during type inference. There's separate
696/// values for general types, and for integer and float variables. The latter
697/// two are used for inference of literal values (e.g. `100` could be one of
698/// several integer types).
699#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
700pub struct InferenceVar {
701 index: u32,
702}
703
704impl InferenceVar {
705 fn to_inner(self) -> unify::TypeVarId {
706 unify::TypeVarId(self.index)
707 }
708
709 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
710 InferenceVar { index }
711 }
712}
713
714/// When inferring an expression, we propagate downward whatever type hint we 701/// When inferring an expression, we propagate downward whatever type hint we
715/// are able in the form of an `Expectation`. 702/// are able in the form of an `Expectation`.
716#[derive(Clone, PartialEq, Eq, Debug)] 703#[derive(Clone, PartialEq, Eq, Debug)]
@@ -755,7 +742,7 @@ impl Expectation {
755 fn none() -> Self { 742 fn none() -> Self {
756 Expectation { 743 Expectation {
757 // FIXME 744 // FIXME
758 ty: TyKind::Unknown.intern(&Interner), 745 ty: TyKind::Error.intern(&Interner),
759 rvalue_hint: false, 746 rvalue_hint: false,
760 } 747 }
761 } 748 }
@@ -763,7 +750,7 @@ impl Expectation {
763 fn coercion_target(&self) -> Ty { 750 fn coercion_target(&self) -> Ty {
764 if self.rvalue_hint { 751 if self.rvalue_hint {
765 // FIXME 752 // FIXME
766 TyKind::Unknown.intern(&Interner) 753 TyKind::Error.intern(&Interner)
767 } else { 754 } else {
768 self.ty.clone() 755 self.ty.clone()
769 } 756 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 028a4d568..1f463a425 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{autoderef, traits::Solution, Interner, Ty, TyBuilder, TyKind}; 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
@@ -71,17 +71,19 @@ impl<'a> InferenceContext<'a> {
71 } 71 }
72 72
73 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
74 match (from_ty.interned_mut(), to_ty.kind(&Interner)) { 74 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
75 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
76 (TyKind::Raw(_, inner), TyKind::Raw(m2 @ Mutability::Not, ..)) => {
77 from_ty = TyKind::Raw(*m2, inner.clone()).intern(&Interner);
78 }
76 // `&mut T` -> `&T` 79 // `&mut T` -> `&T`
77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 80 (TyKind::Ref(_, lt, inner), TyKind::Ref(m2 @ Mutability::Not, ..)) => {
78 | (TyKind::Ref(m1, ..), TyKind::Ref(m2 @ Mutability::Not, ..)) => { 81 from_ty = TyKind::Ref(*m2, lt.clone(), inner.clone()).intern(&Interner);
79 *m1 = *m2;
80 } 82 }
81 // `&T` -> `*const T` 83 // `&T` -> `*const T`
82 // `&mut T` -> `*mut T`/`*const T` 84 // `&mut T` -> `*mut T`/`*const T`
83 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) 85 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
84 | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { 86 | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => {
85 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); 87 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
86 } 88 }
87 89
@@ -111,7 +113,9 @@ impl<'a> InferenceContext<'a> {
111 // Auto Deref if cannot coerce 113 // Auto Deref if cannot coerce
112 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) { 114 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
113 // FIXME: DerefMut 115 // FIXME: DerefMut
114 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2), 116 (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => {
117 self.unify_autoderef_behind_ref(st1, st2)
118 }
115 119
116 // Otherwise, normal unify 120 // Otherwise, normal unify
117 _ => self.unify(&from_ty, to_ty), 121 _ => self.unify(&from_ty, to_ty),
@@ -137,7 +141,7 @@ impl<'a> InferenceContext<'a> {
137 b.push(from_ty.clone()).push(to_ty.clone()).build() 141 b.push(from_ty.clone()).push(to_ty.clone()).build()
138 }; 142 };
139 143
140 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); 144 let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner));
141 145
142 let canonicalizer = self.canonicalizer(); 146 let canonicalizer = self.canonicalizer();
143 let canonicalized = canonicalizer.canonicalize_obligation(goal); 147 let canonicalized = canonicalizer.canonicalize_obligation(goal);
@@ -146,7 +150,14 @@ impl<'a> InferenceContext<'a> {
146 150
147 match solution { 151 match solution {
148 Solution::Unique(v) => { 152 Solution::Unique(v) => {
149 canonicalized.apply_solution(self, v.0); 153 canonicalized.apply_solution(
154 self,
155 Canonical {
156 binders: v.binders,
157 // FIXME handle constraints
158 value: v.value.subst,
159 },
160 );
150 } 161 }
151 _ => return None, 162 _ => return None,
152 }; 163 };
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index c584a2c08..50497eecb 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -3,7 +3,7 @@
3use std::iter::{repeat, repeat_with}; 3use std::iter::{repeat, repeat_with};
4use std::{mem, sync::Arc}; 4use std::{mem, sync::Arc};
5 5
6use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 6use chalk_ir::{cast::Cast, fold::Shift, Mutability, TyVariableKind};
7use hir_def::{ 7use hir_def::{
8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp}, 8 expr::{Array, BinaryOp, Expr, ExprId, Literal, Statement, UnaryOp},
9 path::{GenericArg, GenericArgs}, 9 path::{GenericArg, GenericArgs},
@@ -15,15 +15,16 @@ use stdx::always;
15use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
16 16
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef, dummy_usize_const,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 mapping::from_chalk,
20 method_resolution, op, 21 method_resolution, op,
21 primitive::{self, UintTy}, 22 primitive::{self, UintTy},
22 to_chalk_trait_id, 23 static_lifetime, to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait, InEnvironment}, 24 traits::FnTrait,
24 utils::{generics, variant_data, Generics}, 25 utils::{generics, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, Interner, Rawness, Scalar, Substitution, 26 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 TraitRef, Ty, TyBuilder, TyKind, 27 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27}; 28};
28 29
29use super::{ 30use super::{
@@ -180,7 +181,8 @@ impl<'a> InferenceContext<'a> {
180 let inner_ty = self.infer_expr(*body, &Expectation::none()); 181 let inner_ty = self.infer_expr(*body, &Expectation::none());
181 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); 182 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
182 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); 183 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
183 TyKind::OpaqueType(opaque_ty_id, Substitution::single(inner_ty)).intern(&Interner) 184 TyKind::OpaqueType(opaque_ty_id, Substitution::from1(&Interner, inner_ty))
185 .intern(&Interner)
184 } 186 }
185 Expr::Loop { body, label } => { 187 Expr::Loop { body, label } => {
186 self.breakables.push(BreakableContext { 188 self.breakables.push(BreakableContext {
@@ -259,14 +261,17 @@ impl<'a> InferenceContext<'a> {
259 }; 261 };
260 sig_tys.push(ret_ty.clone()); 262 sig_tys.push(ret_ty.clone());
261 let sig_ty = TyKind::Function(FnPointer { 263 let sig_ty = TyKind::Function(FnPointer {
262 num_args: sig_tys.len() - 1, 264 num_binders: 0,
263 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, 265 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
264 substs: Substitution::from_iter(&Interner, sig_tys.clone()), 266 substitution: FnSubst(
267 Substitution::from_iter(&Interner, sig_tys.clone()).shifted_in(&Interner),
268 ),
265 }) 269 })
266 .intern(&Interner); 270 .intern(&Interner);
267 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into(); 271 let closure_id = self.db.intern_closure((self.owner, tgt_expr)).into();
268 let closure_ty = 272 let closure_ty =
269 TyKind::Closure(closure_id, Substitution::single(sig_ty)).intern(&Interner); 273 TyKind::Closure(closure_id, Substitution::from1(&Interner, sig_ty))
274 .intern(&Interner);
270 275
271 // Eagerly try to relate the closure type with the expected 276 // Eagerly try to relate the closure type with the expected
272 // type, otherwise we often won't have enough information to 277 // type, otherwise we often won't have enough information to
@@ -313,7 +318,13 @@ impl<'a> InferenceContext<'a> {
313 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
314 } 319 }
315 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
316 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 321 .infer_method_call(
322 tgt_expr,
323 *receiver,
324 &args,
325 &method_name,
326 generic_args.as_deref(),
327 ),
317 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
318 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
319 330
@@ -394,16 +405,19 @@ impl<'a> InferenceContext<'a> {
394 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
395 } 406 }
396 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
397 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
398 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
399 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
400 } 411 }
401 412
402 self.unify(&ty, &expected.ty); 413 self.unify(&ty, &expected.ty);
403 414
404 let substs = ty.substs().cloned().unwrap_or_else(|| Substitution::empty(&Interner)); 415 let substs = ty
416 .as_adt()
417 .map(|(_, s)| s.clone())
418 .unwrap_or_else(|| Substitution::empty(&Interner));
405 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default(); 419 let field_types = def_id.map(|it| self.db.field_types(it)).unwrap_or_default();
406 let variant_data = def_id.map(|it| variant_data(self.db.upcast(), it)); 420 let variant_data = def_id.map(|it| it.variant_data(self.db.upcast()));
407 for field in fields.iter() { 421 for field in fields.iter() {
408 let field_def = 422 let field_def =
409 variant_data.as_ref().and_then(|it| match it.field(&field.name) { 423 variant_data.as_ref().and_then(|it| match it.field(&field.name) {
@@ -415,11 +429,8 @@ impl<'a> InferenceContext<'a> {
415 None 429 None
416 } 430 }
417 }); 431 });
418 if let Some(field_def) = field_def {
419 self.result.record_field_resolutions.insert(field.expr, field_def);
420 }
421 let field_ty = field_def.map_or(self.err_ty(), |it| { 432 let field_ty = field_def.map_or(self.err_ty(), |it| {
422 field_types[it.local_id].clone().subst(&substs) 433 field_types[it.local_id].clone().substitute(&Interner, &substs)
423 }); 434 });
424 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 435 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
425 } 436 }
@@ -453,7 +464,7 @@ impl<'a> InferenceContext<'a> {
453 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
454 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
455 substs 466 substs
456 .interned(&Interner) 467 .as_slice(&Interner)
457 .get(idx) 468 .get(idx)
458 .map(|a| a.assert_ty_ref(&Interner)) 469 .map(|a| a.assert_ty_ref(&Interner))
459 .cloned() 470 .cloned()
@@ -466,7 +477,7 @@ impl<'a> InferenceContext<'a> {
466 Some( 477 Some(
467 self.db.field_types((*s).into())[field.local_id] 478 self.db.field_types((*s).into())[field.local_id]
468 .clone() 479 .clone()
469 .subst(&parameters), 480 .substitute(&Interner, &parameters),
470 ) 481 )
471 } else { 482 } else {
472 None 483 None
@@ -480,7 +491,7 @@ impl<'a> InferenceContext<'a> {
480 Some( 491 Some(
481 self.db.field_types((*u).into())[field.local_id] 492 self.db.field_types((*u).into())[field.local_id]
482 .clone() 493 .clone()
483 .subst(&parameters), 494 .substitute(&Interner, &parameters),
484 ) 495 )
485 } else { 496 } else {
486 None 497 None
@@ -527,7 +538,7 @@ impl<'a> InferenceContext<'a> {
527 let inner_ty = self.infer_expr_inner(*expr, &expectation); 538 let inner_ty = self.infer_expr_inner(*expr, &expectation);
528 match rawness { 539 match rawness {
529 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), 540 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
530 Rawness::Ref => TyKind::Ref(mutability, inner_ty), 541 Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty),
531 } 542 }
532 .intern(&Interner) 543 .intern(&Interner)
533 } 544 }
@@ -702,7 +713,7 @@ impl<'a> InferenceContext<'a> {
702 } 713 }
703 Expr::Array(array) => { 714 Expr::Array(array) => {
704 let elem_ty = match expected.ty.kind(&Interner) { 715 let elem_ty = match expected.ty.kind(&Interner) {
705 TyKind::Array(st) | TyKind::Slice(st) => st.clone(), 716 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
706 _ => self.table.new_type_var(), 717 _ => self.table.new_type_var(),
707 }; 718 };
708 719
@@ -726,17 +737,19 @@ impl<'a> InferenceContext<'a> {
726 } 737 }
727 } 738 }
728 739
729 TyKind::Array(elem_ty).intern(&Interner) 740 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
730 } 741 }
731 Expr::Literal(lit) => match lit { 742 Expr::Literal(lit) => match lit {
732 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 743 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
733 Literal::String(..) => { 744 Literal::String(..) => {
734 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner) 745 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner))
746 .intern(&Interner)
735 } 747 }
736 Literal::ByteString(..) => { 748 Literal::ByteString(..) => {
737 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 749 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
738 let array_type = TyKind::Array(byte_type).intern(&Interner); 750 let array_type =
739 TyKind::Ref(Mutability::Not, array_type).intern(&Interner) 751 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
752 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
740 } 753 }
741 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 754 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
742 Literal::Int(_v, ty) => match ty { 755 Literal::Int(_v, ty) => match ty {
@@ -853,10 +866,10 @@ impl<'a> InferenceContext<'a> {
853 self.write_method_resolution(tgt_expr, func); 866 self.write_method_resolution(tgt_expr, func);
854 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) 867 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
855 } 868 }
856 None => (receiver_ty, Binders::new(0, self.err_ty()), None), 869 None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None),
857 }; 870 };
858 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); 871 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
859 let method_ty = method_ty.subst(&substs); 872 let method_ty = method_ty.substitute(&Interner, &substs);
860 let method_ty = self.insert_type_vars(method_ty); 873 let method_ty = self.insert_type_vars(method_ty);
861 self.register_obligations_for_call(&method_ty); 874 self.register_obligations_for_call(&method_ty);
862 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { 875 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) {
@@ -872,7 +885,9 @@ impl<'a> InferenceContext<'a> {
872 // Apply autoref so the below unification works correctly 885 // Apply autoref so the below unification works correctly
873 // FIXME: return correct autorefs from lookup_method 886 // FIXME: return correct autorefs from lookup_method
874 let actual_receiver_ty = match expected_receiver_ty.as_reference() {