aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/autoderef.rs63
-rw-r--r--crates/hir_ty/src/builder.rs223
-rw-r--r--crates/hir_ty/src/chalk_cast.rs22
-rw-r--r--crates/hir_ty/src/chalk_ext.rs305
-rw-r--r--crates/hir_ty/src/db.rs16
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs5
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs24
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs49
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs12
-rw-r--r--crates/hir_ty/src/display.rs299
-rw-r--r--crates/hir_ty/src/infer.rs183
-rw-r--r--crates/hir_ty/src/infer/coerce.rs56
-rw-r--r--crates/hir_ty/src/infer/expr.rs216
-rw-r--r--crates/hir_ty/src/infer/pat.rs92
-rw-r--r--crates/hir_ty/src/infer/path.rs39
-rw-r--r--crates/hir_ty/src/infer/unify.rs154
-rw-r--r--crates/hir_ty/src/lib.rs1220
-rw-r--r--crates/hir_ty/src/lower.rs316
-rw-r--r--crates/hir_ty/src/method_resolution.rs232
-rw-r--r--crates/hir_ty/src/op.rs22
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/tests/macros.rs149
-rw-r--r--crates/hir_ty/src/tests/method_resolution.rs22
-rw-r--r--crates/hir_ty/src/tests/simple.rs33
-rw-r--r--crates/hir_ty/src/tests/traits.rs43
-rw-r--r--crates/hir_ty/src/traits.rs104
-rw-r--r--crates/hir_ty/src/traits/chalk.rs89
-rw-r--r--crates/hir_ty/src/traits/chalk/interner.rs43
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs212
-rw-r--r--crates/hir_ty/src/types.rs549
-rw-r--r--crates/hir_ty/src/utils.rs63
-rw-r--r--crates/hir_ty/src/walk.rs423
32 files changed, 3008 insertions, 2272 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index dc5fc759a..f8e9db9ae 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,12 +12,8 @@ use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
16 to_assoc_type_id, to_chalk_trait_id, 16 InEnvironment, Interner, ProjectionTyExt, Solution, Ty, TyBuilder, TyKind,
17 traits::{InEnvironment, Solution},
18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 17};
22 18
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -39,13 +35,21 @@ pub(crate) fn deref(
39 krate: CrateId, 35 krate: CrateId,
40 ty: InEnvironment<&Canonical<Ty>>, 36 ty: InEnvironment<&Canonical<Ty>>,
41) -> Option<Canonical<Ty>> { 37) -> Option<Canonical<Ty>> {
42 if let Some(derefed) = ty.goal.value.builtin_deref() { 38 if let Some(derefed) = builtin_deref(&ty.goal.value) {
43 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() }) 39 Some(Canonical { value: derefed, binders: ty.goal.binders.clone() })
44 } else { 40 } else {
45 deref_by_trait(db, krate, ty) 41 deref_by_trait(db, krate, ty)
46 } 42 }
47} 43}
48 44
45fn builtin_deref(ty: &Ty) -> Option<Ty> {
46 match ty.kind(&Interner) {
47 TyKind::Ref(.., ty) => Some(ty.clone()),
48 TyKind::Raw(.., ty) => Some(ty.clone()),
49 _ => None,
50 }
51}
52
49fn deref_by_trait( 53fn deref_by_trait(
50 db: &dyn HirDatabase, 54 db: &dyn HirDatabase,
51 krate: CrateId, 55 krate: CrateId,
@@ -57,21 +61,20 @@ fn deref_by_trait(
57 }; 61 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 62 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 63
60 let generic_params = generics(db.upcast(), target.into()); 64 let projection = {
61 if generic_params.len() != 1 { 65 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 66 if b.remaining() != 1 {
63 // namely Deref's Self type 67 // the Target type + Deref trait should only have one generic parameter,
64 return None; 68 // namely Deref's Self type
65 } 69 return None;
70 }
71 b.push(ty.goal.value.clone()).build()
72 };
66 73
67 // FIXME make the Canonical / bound var handling nicer 74 // FIXME make the Canonical / bound var handling nicer
68 75
69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71
72 // Check that the type implements Deref at all 76 // Check that the type implements Deref at all
73 let trait_ref = 77 let trait_ref = projection.trait_ref(db);
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 78 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 79 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 80 value: InEnvironment {
@@ -84,11 +87,8 @@ fn deref_by_trait(
84 } 87 }
85 88
86 // Now do the assoc type projection 89 // Now do the assoc type projection
87 let projection = AliasEq { 90 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 91 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 92 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 93 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 94 ty.goal.binders.len(&Interner),
@@ -96,9 +96,7 @@ fn deref_by_trait(
96 .intern(&Interner), 96 .intern(&Interner),
97 }; 97 };
98 98
99 let obligation = projection.cast(&Interner); 99 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 100
103 let canonical = Canonical { 101 let canonical = Canonical {
104 value: in_env, 102 value: in_env,
@@ -130,8 +128,8 @@ fn deref_by_trait(
130 // assumptions will be broken. We would need to properly introduce 128 // assumptions will be broken. We would need to properly introduce
131 // new variables in that case 129 // new variables in that case
132 130
133 for i in 1..vars.0.binders.len(&Interner) { 131 for i in 1..vars.binders.len(&Interner) {
134 if vars.0.value[i - 1].interned(&Interner) 132 if vars.value.subst.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 133 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
136 { 134 {
137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 135 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -139,8 +137,13 @@ fn deref_by_trait(
139 } 137 }
140 } 138 }
141 Some(Canonical { 139 Some(Canonical {
142 value: vars.0.value[vars.0.value.len() - 1].clone(), 140 value: vars
143 binders: vars.0.binders.clone(), 141 .value
142 .subst
143 .at(&Interner, vars.value.subst.len(&Interner) - 1)
144 .assert_ty_ref(&Interner)
145 .clone(),
146 binders: vars.binders.clone(),
144 }) 147 })
145 } 148 }
146 Solution::Ambig(_) => { 149 Solution::Ambig(_) => {
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
new file mode 100644
index 000000000..09512d1ce
--- /dev/null
+++ b/crates/hir_ty/src/builder.rs
@@ -0,0 +1,223 @@
1//! `TyBuilder`, a helper for building instances of `Ty` and related types.
2
3use std::iter;
4
5use chalk_ir::{
6 cast::{Cast, CastTo, Caster},
7 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9};
10use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
11use smallvec::SmallVec;
12
13use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TraitRef, Ty, TyDefId, TyExt, TyKind, TypeWalk, ValueTyDefId,
17};
18
19/// This is a builder for `Ty` or anything that needs a `Substitution`.
20pub struct TyBuilder<D> {
21 /// The `data` field is used to keep track of what we're building (e.g. an
22 /// ADT, a `TraitRef`, ...).
23 data: D,
24 vec: SmallVec<[GenericArg; 2]>,
25 param_count: usize,
26}
27
28impl<D> TyBuilder<D> {
29 fn new(data: D, param_count: usize) -> TyBuilder<D> {
30 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
31 }
32
33 fn build_internal(self) -> (D, Substitution) {
34 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::intern(self.vec);
37 (self.data, subst)
38 }
39
40 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
41 self.vec.push(arg.cast(&Interner));
42 self
43 }
44
45 pub fn remaining(&self) -> usize {
46 self.param_count - self.vec.len()
47 }
48
49 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
50 self.fill(
51 (starting_from..)
52 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
53 )
54 }
55
56 pub fn fill_with_unknown(self) -> Self {
57 self.fill(iter::repeat(TyKind::Error.intern(&Interner)))
58 }
59
60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
61 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
62 assert_eq!(self.remaining(), 0);
63 self
64 }
65
66 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
67 assert!(self.vec.is_empty());
68 assert!(parent_substs.len(&Interner) <= self.param_count);
69 self.vec.extend(parent_substs.iter(&Interner).cloned());
70 self
71 }
72}
73
74impl TyBuilder<()> {
75 pub fn unit() -> Ty {
76 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
77 }
78
79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer {
81 num_binders: 0,
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substitution: FnSubst(Substitution::from_iter(
84 &Interner,
85 sig.params_and_return.iter().cloned(),
86 )),
87 })
88 .intern(&Interner)
89 }
90
91 pub fn builtin(builtin: BuiltinType) -> Ty {
92 match builtin {
93 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
94 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
95 BuiltinType::Str => TyKind::Str.intern(&Interner),
96 BuiltinType::Int(t) => {
97 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
98 }
99 BuiltinType::Uint(t) => {
100 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
101 }
102 BuiltinType::Float(t) => {
103 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
104 }
105 }
106 }
107
108 pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
109 let params = generics(db.upcast(), def.into());
110 params.type_params_subst(db)
111 }
112
113 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
114 let def = def.into();
115 let params = generics(db.upcast(), def);
116 let param_count = params.len();
117 TyBuilder::new((), param_count)
118 }
119
120 pub fn build(self) -> Substitution {
121 let ((), subst) = self.build_internal();
122 subst
123 }
124}
125
126impl TyBuilder<hir_def::AdtId> {
127 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
128 let generics = generics(db.upcast(), adt.into());
129 let param_count = generics.len();
130 TyBuilder::new(adt, param_count)
131 }
132
133 pub fn fill_with_defaults(
134 mut self,
135 db: &dyn HirDatabase,
136 mut fallback: impl FnMut() -> Ty,
137 ) -> Self {
138 let defaults = db.generic_defaults(self.data.into());
139 for default_ty in defaults.iter().skip(self.vec.len()) {
140 if default_ty.skip_binders().is_unknown() {
141 self.vec.push(fallback().cast(&Interner));
142 } else {
143 // each default can depend on the previous parameters
144 let subst_so_far = Substitution::intern(self.vec.clone());
145 self.vec
146 .push(default_ty.clone().substitute(&Interner, &subst_so_far).cast(&Interner));
147 }
148 }
149 self
150 }
151
152 pub fn build(self) -> Ty {
153 let (adt, subst) = self.build_internal();
154 TyKind::Adt(AdtId(adt), subst).intern(&Interner)
155 }
156}
157
158pub struct Tuple(usize);
159impl TyBuilder<Tuple> {
160 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
161 TyBuilder::new(Tuple(size), size)
162 }
163
164 pub fn build(self) -> Ty {
165 let (Tuple(size), subst) = self.build_internal();
166 TyKind::Tuple(size, subst).intern(&Interner)
167 }
168}
169
170impl TyBuilder<TraitId> {
171 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
172 let generics = generics(db.upcast(), trait_id.into());
173 let param_count = generics.len();
174 TyBuilder::new(trait_id, param_count)
175 }
176
177 pub fn build(self) -> TraitRef {
178 let (trait_id, substitution) = self.build_internal();
179 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
180 }
181}
182
183impl TyBuilder<TypeAliasId> {
184 pub fn assoc_type_projection(
185 db: &dyn HirDatabase,
186 type_alias: TypeAliasId,
187 ) -> TyBuilder<TypeAliasId> {
188 let generics = generics(db.upcast(), type_alias.into());
189 let param_count = generics.len();
190 TyBuilder::new(type_alias, param_count)
191 }
192
193 pub fn build(self) -> ProjectionTy {
194 let (type_alias, substitution) = self.build_internal();
195 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
196 }
197}
198
199impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
200 fn subst_binders(b: Binders<T>) -> Self {
201 let param_count = b.binders.len(&Interner);
202 TyBuilder::new(b, param_count)
203 }
204
205 pub fn build(self) -> T {
206 let (b, subst) = self.build_internal();
207 b.substitute(&Interner, &subst)
208 }
209}
210
211impl TyBuilder<Binders<Ty>> {
212 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
213 TyBuilder::subst_binders(db.ty(def.into()))
214 }
215
216 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
217 TyBuilder::subst_binders(db.impl_self_ty(def))
218 }
219
220 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
221 TyBuilder::subst_binders(db.value_ty(def))
222 }
223}
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs
index bf884ae15..df6492113 100644
--- a/crates/hir_ty/src/chalk_cast.rs
+++ b/crates/hir_ty/src/chalk_cast.rs
@@ -5,7 +5,7 @@ use chalk_ir::{
5 interner::HasInterner, 5 interner::HasInterner,
6}; 6};
7 7
8use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; 8use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
9 9
10macro_rules! has_interner { 10macro_rules! has_interner {
11 ($t:ty) => { 11 ($t:ty) => {
@@ -17,6 +17,8 @@ macro_rules! has_interner {
17 17
18has_interner!(WhereClause); 18has_interner!(WhereClause);
19has_interner!(DomainGoal); 19has_interner!(DomainGoal);
20has_interner!(GenericArg);
21has_interner!(Ty);
20 22
21impl CastTo<WhereClause> for TraitRef { 23impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause { 24 fn cast_to(self, _interner: &Interner) -> WhereClause {
@@ -36,6 +38,12 @@ impl CastTo<DomainGoal> for WhereClause {
36 } 38 }
37} 39}
38 40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
39macro_rules! transitive_impl { 47macro_rules! transitive_impl {
40 ($a:ty, $b:ty, $c:ty) => { 48 ($a:ty, $b:ty, $c:ty) => {
41 impl CastTo<$c> for $a { 49 impl CastTo<$c> for $a {
@@ -51,3 +59,15 @@ macro_rules! transitive_impl {
51 59
52transitive_impl!(TraitRef, WhereClause, DomainGoal); 60transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_impl!(AliasEq, 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/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
new file mode 100644
index 000000000..28ed3aac6
--- /dev/null
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -0,0 +1,305 @@
1//! Various extensions traits for Chalk types.
2
3use chalk_ir::Mutability;
4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6};
7
8use crate::{
9 db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
10 from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
11 CallableSig, FnPointer, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
12 Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
13};
14
15pub trait TyExt {
16 fn is_unit(&self) -> bool;
17 fn is_never(&self) -> bool;
18 fn is_unknown(&self) -> bool;
19
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
21 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
24 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
25 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
26
27 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
28 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
29
30 fn strip_references(&self) -> &Ty;
31
32 /// If this is a `dyn Trait`, returns that trait.
33 fn dyn_trait(&self) -> Option<TraitId>;
34
35 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
36 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
37
38 /// FIXME: Get rid of this, it's not a good abstraction
39 fn equals_ctor(&self, other: &Ty) -> bool;
40}
41
42impl TyExt for Ty {
43 fn is_unit(&self) -> bool {
44 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
45 }
46
47 fn is_never(&self) -> bool {
48 matches!(self.kind(&Interner), TyKind::Never)
49 }
50
51 fn is_unknown(&self) -> bool {
52 matches!(self.kind(&Interner), TyKind::Error)
53 }
54
55 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
56 match self.kind(&Interner) {
57 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
58 _ => None,
59 }
60 }
61
62 fn as_tuple(&self) -> Option<&Substitution> {
63 match self.kind(&Interner) {
64 TyKind::Tuple(_, substs) => Some(substs),
65 _ => None,
66 }
67 }
68
69 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
70 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
71 Some(func)
72 } else {
73 None
74 }
75 }
76 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
77 match self.kind(&Interner) {
78 TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
79 _ => None,
80 }
81 }
82
83 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
84 match self.kind(&Interner) {
85 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
86 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
87 _ => None,
88 }
89 }
90
91 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
92 match *self.kind(&Interner) {
93 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
94 TyKind::FnDef(callable, ..) => {
95 Some(db.lookup_intern_callable_def(callable.into()).into())
96 }
97 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
98 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
99 _ => None,
100 }
101 }
102
103 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
104 match self.kind(&Interner) {
105 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
106 _ => None,
107 }
108 }
109
110 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
111 match self.kind(&Interner) {
112 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
113 TyKind::FnDef(def, parameters) => {
114 let callable_def = db.lookup_intern_callable_def((*def).into());
115 let sig = db.callable_item_signature(callable_def);
116 Some(sig.substitute(&Interner, &parameters))
117 }
118 TyKind::Closure(.., substs) => {
119 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
120 sig_param.callable_sig(db)
121 }
122 _ => None,
123 }
124 }
125
126 fn dyn_trait(&self) -> Option<TraitId> {
127 let trait_ref = match self.kind(&Interner) {
128 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
129 match b.skip_binders() {
130 WhereClause::Implemented(trait_ref) => Some(trait_ref),
131 _ => None,
132 }
133 }),
134 _ => None,
135 }?;
136 Some(from_chalk_trait_id(trait_ref.trait_id))
137 }
138
139 fn strip_references(&self) -> &Ty {
140 let mut t: &Ty = self;
141 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
142 t = ty;
143 }
144 t
145 }
146
147 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
148 match self.kind(&Interner) {
149 TyKind::OpaqueType(opaque_ty_id, ..) => {
150 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
151 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
152 let krate = def.module(db.upcast()).krate();
153 if let Some(future_trait) = db
154 .lang_item(krate, "future_trait".into())
155 .and_then(|item| item.as_trait())
156 {
157 // This is only used by type walking.
158 // Parameters will be walked outside, and projection predicate is not used.
159 // So just provide the Future trait.
160 let impl_bound = Binders::empty(
161 &Interner,
162 WhereClause::Implemented(TraitRef {
163 trait_id: to_chalk_trait_id(future_trait),
164 substitution: Substitution::empty(&Interner),
165 }),
166 );
167 Some(vec![impl_bound])
168 } else {
169 None
170 }
171 }
172 ImplTraitId::ReturnTypeImplTrait(..) => None,
173 }
174 }
175 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
176 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
177 {
178 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
179 db.return_type_impl_traits(func).map(|it| {
180 let data = (*it)
181 .as_ref()
182 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
183 data.substitute(&Interner, &opaque_ty.substitution)
184 })
185 }
186 // It always has an parameter for Future::Output type.
187 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
188 };
189
190 predicates.map(|it| it.into_value_and_skipped_binders().0)
191 }
192 TyKind::Placeholder(idx) => {
193 let id = from_placeholder_idx(db, *idx);
194 let generic_params = db.generic_params(id.parent);
195 let param_data = &generic_params.types[id.local_id];
196 match param_data.provenance {
197 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
198 let substs = TyBuilder::type_params_subst(db, id.parent);
199 let predicates = db
200 .generic_predicates(id.parent)
201 .into_iter()
202 .map(|pred| pred.clone().substitute(&Interner, &substs))
203 .filter(|wc| match &wc.skip_binders() {
204 WhereClause::Implemented(tr) => {
205 &tr.self_type_parameter(&Interner) == self
206 }
207 WhereClause::AliasEq(AliasEq {
208 alias: AliasTy::Projection(proj),
209 ty: _,
210 }) => &proj.self_type_parameter(&Interner) == self,
211 _ => false,
212 })
213 .collect::<Vec<_>>();
214
215 Some(predicates)
216 }
217 _ => None,
218 }
219 }
220 _ => None,
221 }
222 }
223
224 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
225 match self.kind(&Interner) {
226 TyKind::AssociatedType(id, ..) => {
227 match from_assoc_type_id(*id).lookup(db.upcast()).container {
228 AssocContainerId::TraitId(trait_id) => Some(trait_id),
229 _ => None,
230 }
231 }
232 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
233 match from_assoc_type_id(projection_ty.associated_ty_id)
234 .lookup(db.upcast())
235 .container
236 {
237 AssocContainerId::TraitId(trait_id) => Some(trait_id),
238 _ => None,
239 }
240 }
241 _ => None,
242 }
243 }
244
245 fn equals_ctor(&self, other: &Ty) -> bool {
246 match (self.kind(&Interner), other.kind(&Interner)) {
247 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
248 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
249 true
250 }
251 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
252 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
253 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
254 ty_id == ty_id2
255 }
256 (TyKind::Foreign(ty_id, ..), TyKind::Foreign(ty_id2, ..)) => ty_id == ty_id2,
257 (TyKind::Closure(id1, _), TyKind::Closure(id2, _)) => id1 == id2,
258 (TyKind::Ref(mutability, ..), TyKind::Ref(mutability2, ..))
259 | (TyKind::Raw(mutability, ..), TyKind::Raw(mutability2, ..)) => {
260 mutability == mutability2
261 }
262 (
263 TyKind::Function(FnPointer { num_binders, sig, .. }),
264 TyKind::Function(FnPointer { num_binders: num_binders2, sig: sig2, .. }),
265 ) => num_binders == num_binders2 && sig == sig2,
266 (TyKind::Tuple(cardinality, _), TyKind::Tuple(cardinality2, _)) => {
267 cardinality == cardinality2
268 }
269 (TyKind::Str, TyKind::Str) | (TyKind::Never, TyKind::Never) => true,
270 (TyKind::Scalar(scalar), TyKind::Scalar(scalar2)) => scalar == scalar2,
271 _ => false,
272 }
273 }
274}
275
276pub trait ProjectionTyExt {
277 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef;
278 fn trait_(&self, db: &dyn HirDatabase) -> TraitId;
279}
280
281impl ProjectionTyExt for ProjectionTy {
282 fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
283 TraitRef {
284 trait_id: to_chalk_trait_id(self.trait_(db)),
285 substitution: self.substitution.clone(),
286 }
287 }
288
289 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
290 match from_assoc_type_id(self.associated_ty_id).lookup(db.upcast()).container {
291 AssocContainerId::TraitId(it) => it,
292 _ => panic!("projection ty without parent trait"),
293 }
294 }
295}
296
297pub trait TraitRefExt {
298 fn hir_trait_id(&self) -> TraitId;
299}
300
301impl TraitRefExt for TraitRef {
302 fn hir_trait_id(&self) -> TraitId {
303 from_chalk_trait_id(self.trait_id)
304 }
305}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 58e4247c6..326c20240 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -5,7 +5,7 @@ use std::sync::Arc;
5use base_db::{impl_intern_key, salsa, CrateId, Upcast}; 5use base_db::{impl_intern_key, salsa, CrateId, Upcast};
6use hir_def::{ 6use hir_def::{
7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId, 7 db::DefDatabase, expr::ExprId, ConstParamId, DefWithBodyId, FunctionId, GenericDefId, ImplId,
8 LocalFieldId, TypeParamId, VariantId, 8 LifetimeParamId, LocalFieldId, TypeParamId, VariantId,
9}; 9};
10use la_arena::ArenaMap; 10use la_arena::ArenaMap;
11 11
@@ -86,6 +86,10 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
86 #[salsa::interned] 86 #[salsa::interned]
87 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId; 87 fn intern_type_param_id(&self, param_id: TypeParamId) -> InternedTypeParamId;
88 #[salsa::interned] 88 #[salsa::interned]
89 fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
90 #[salsa::interned]
91 fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId;
92 #[salsa::interned]
89 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; 93 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
90 #[salsa::interned] 94 #[salsa::interned]
91 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; 95 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
@@ -123,7 +127,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
123 &self, 127 &self,
124 krate: CrateId, 128 krate: CrateId,
125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 129 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
126 ) -> Option<crate::traits::Solution>; 130 ) -> Option<crate::Solution>;
127 131
128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 132 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
129 fn program_clauses_for_chalk_env( 133 fn program_clauses_for_chalk_env(
@@ -156,6 +160,14 @@ pub struct InternedTypeParamId(salsa::InternId);
156impl_intern_key!(InternedTypeParamId); 160impl_intern_key!(InternedTypeParamId);
157 161
158#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 162#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
163pub struct InternedLifetimeParamId(salsa::InternId);
164impl_intern_key!(InternedLifetimeParamId);
165
166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct InternedConstParamId(salsa::InternId);
168impl_intern_key!(InternedConstParamId);
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
159pub struct InternedOpaqueTyId(salsa::InternId); 171pub struct InternedOpaqueTyId(salsa::InternId);
160impl_intern_key!(InternedOpaqueTyId); 172impl_intern_key!(InternedOpaqueTyId);
161 173
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs
index 33a0f4d7d..1c9f9ede7 100644
--- a/crates/hir_ty/src/diagnostics/decl_check.rs
+++ b/crates/hir_ty/src/diagnostics/decl_check.rs
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
91 91
92 fn validate_func(&mut self, func: FunctionId) { 92 fn validate_func(&mut self, func: FunctionId) {
93 let data = self.db.function_data(func); 93 let data = self.db.function_data(func);
94 if data.is_in_extern_block { 94 if data.is_in_extern_block() {
95 cov_mark::hit!(extern_func_incorrect_case_ignored); 95 cov_mark::hit!(extern_func_incorrect_case_ignored);
96 return; 96 return;
97 } 97 }
@@ -99,8 +99,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
99 let body = self.db.body(func.into()); 99 let body = self.db.body(func.into());
100 100
101 // Recursively validate inner scope items, such as static variables and constants. 101 // Recursively validate inner scope items, such as static variables and constants.
102 let db = self.db; 102 for (_, block_def_map) in body.blocks(self.db.upcast()) {
103 for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) {
104 for (_, module) in block_def_map.modules() { 103 for (_, module) in block_def_map.modules() {
105 for def_id in module.scope.declarations() { 104 for def_id in module.scope.declarations() {
106 let mut validator = DeclValidator::new(self.db, self.krate, self.sink); 105 let mut validator = DeclValidator::new(self.db, self.krate, self.sink);
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs
index 3909ad354..79602c3dd 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -14,8 +14,7 @@ use crate::{
14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr, 14 MismatchedArgCount, MissingFields, MissingMatchArms, MissingOkOrSomeInTailExpr,
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data, 17 AdtId, InferenceResult, Interner, TyExt, TyKind,
18 AdtId, InferenceResult, Interner, Ty, TyKind,
19}; 18};
20 19
21pub(crate) use hir_def::{ 20pub(crate) use hir_def::{
@@ -104,7 +103,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
104 let root = source_ptr.file_syntax(db.upcast()); 103 let root = source_ptr.file_syntax(db.upcast());
105 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) { 104 if let ast::Expr::RecordExpr(record_expr) = &source_ptr.value.to_node(&root) {
106 if let Some(_) = record_expr.record_expr_field_list() { 105 if let Some(_) = record_expr.record_expr_field_list() {
107 let variant_data = variant_data(db.upcast(), variant_def); 106 let variant_data = variant_def.variant_data(db.upcast());
108 let missed_fields = missed_fields 107 let missed_fields = missed_fields
109 .into_iter() 108 .into_iter()
110 .map(|idx| variant_data.fields()[idx].name.clone()) 109 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -135,7 +134,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
135 let root = source_ptr.file_syntax(db.upcast()); 134 let root = source_ptr.file_syntax(db.upcast());
136 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) { 135 if let ast::Pat::RecordPat(record_pat) = expr.to_node(&root) {
137 if let Some(_) = record_pat.record_pat_field_list() { 136 if let Some(_) = record_pat.record_pat_field_list() {
138 let variant_data = variant_data(db.upcast(), variant_def); 137 let variant_data = variant_def.variant_data(db.upcast());
139 let missed_fields = missed_fields 138 let missed_fields = missed_fields
140 .into_iter() 139 .into_iter()
141 .map(|idx| variant_data.fields()[idx].name.clone()) 140 .map(|idx| variant_data.fields()[idx].name.clone())
@@ -245,7 +244,8 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
245 Some(callee) => callee, 244 Some(callee) => callee,
246 None => return, 245 None => return,
247 }; 246 };
248 let sig = db.callable_item_signature(callee.into()).value; 247 let sig =
248 db.callable_item_signature(callee.into()).into_value_and_skipped_binders().0;
249 249
250 (sig, args) 250 (sig, args)
251 } 251 }
@@ -314,7 +314,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
314 if pat_ty == match_expr_ty 314 if pat_ty == match_expr_ty
315 || match_expr_ty 315 || match_expr_ty
316 .as_reference() 316 .as_reference()
317 .map(|(match_expr_ty, _)| match_expr_ty == pat_ty) 317 .map(|(match_expr_ty, ..)| match_expr_ty == pat_ty)
318 .unwrap_or(false) 318 .unwrap_or(false)
319 { 319 {
320 // If we had a NotUsefulMatchArm diagnostic, we could 320 // If we had a NotUsefulMatchArm diagnostic, we could
@@ -378,7 +378,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
378 _ => return, 378 _ => return,
379 }; 379 };
380 380
381 let (params, required) = match mismatch.expected.interned(&Interner) { 381 let (params, required) = match mismatch.expected.kind(&Interner) {
382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) 382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
383 if *enum_id == core_result_enum => 383 if *enum_id == core_result_enum =>
384 { 384 {
@@ -392,7 +392,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
392 _ => return, 392 _ => return,
393 }; 393 };
394 394
395 if params.len() > 0 && params[0] == mismatch.actual { 395 if params.len(&Interner) > 0
396 && params.at(&Interner, 0).ty(&Interner) == Some(&mismatch.actual)
397 {
396 let (_, source_map) = db.body_with_source_map(self.owner); 398 let (_, source_map) = db.body_with_source_map(self.owner);
397 399
398 if let Ok(source_ptr) = source_map.expr_syntax(id) { 400 if let Ok(source_ptr) = source_map.expr_syntax(id) {
@@ -421,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
421 None => return, 423 None => return,
422 }; 424 };
423 425
424 if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { 426 if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty {
425 return; 427 return;
426 } 428 }
427 429
@@ -450,7 +452,7 @@ pub fn record_literal_missing_fields(
450 return None; 452 return None;
451 } 453 }
452 454
453 let variant_data = variant_data(db.upcast(), variant_def); 455 let variant_data = variant_def.variant_data(db.upcast());
454 456
455 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 457 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
456 let missed_fields: Vec<LocalFieldId> = variant_data 458 let missed_fields: Vec<LocalFieldId> = variant_data
@@ -480,7 +482,7 @@ pub fn record_pattern_missing_fields(
480 return None; 482 return None;
481 } 483 }
482 484
483 let variant_data = variant_data(db.upcast(), variant_def); 485 let variant_data = variant_def.variant_data(db.upcast());
484 486
485 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect(); 487 let specified_fields: FxHashSet<_> = fields.iter().map(|f| &f.name).collect();
486 let missed_fields: Vec<LocalFieldId> = variant_data 488 let missed_fields: Vec<LocalFieldId> = variant_data
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 5a5cdcbf3..e9762622f 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
@@ -539,7 +539,7 @@ impl Matrix {
539 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { 539 if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) {
540 // Or patterns are expanded here 540 // Or patterns are expanded here
541 for pat_id in pat_ids { 541 for pat_id in pat_ids {
542 self.0.push(PatStack::from_pattern(pat_id)); 542 self.0.push(row.replace_head_with([pat_id].iter()));
543 } 543 }
544 } else { 544 } else {
545 self.0.push(row); 545 self.0.push(row);
@@ -626,7 +626,7 @@ pub(super) fn is_useful(
626 // - enum with no variants 626 // - enum with no variants
627 // - `!` type 627 // - `!` type
628 // In those cases, no match arm is useful. 628 // In those cases, no match arm is useful.
629 match cx.infer[cx.match_expr].strip_references().interned(&Interner) { 629 match cx.infer[cx.match_expr].strip_references().kind(&Interner) {
630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { 630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
631 if cx.db.enum_data(*enum_id).variants.is_empty() { 631 if cx.db.enum_data(*enum_id).variants.is_empty() {
632 return Ok(Usefulness::NotUseful); 632 return Ok(Usefulness::NotUseful);
@@ -792,7 +792,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Opt
792 Pat::Tuple { .. } => { 792 Pat::Tuple { .. } => {
793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); 793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild");
794 Some(Constructor::Tuple { 794 Some(Constructor::Tuple {
795 arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), 795 arity: cx.infer.type_of_pat[pat_id]
796 .as_tuple()
797 .ok_or(MatchCheckErr::Unknown)?
798 .len(&Interner),
796 }) 799 })
797 } 800 }
798 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { 801 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] {
@@ -1085,6 +1088,20 @@ fn main() {
1085 } 1088 }
1086 1089
1087 #[test] 1090 #[test]
1091 fn or_pattern_no_diagnostic() {
1092 check_diagnostics(
1093 r#"
1094enum Either {A, B}
1095
1096fn main() {
1097 match (Either::A, Either::B) {
1098 (Either::A | Either::B, _) => (),
1099 }
1100}"#,
1101 )
1102 }
1103
1104 #[test]
1088 fn mismatched_types() { 1105 fn mismatched_types() {
1089 // Match statements with arms that don't match the 1106 // Match statements with arms that don't match the
1090 // expression pattern do not fire this diagnostic. 1107 // expression pattern do not fire this diagnostic.
@@ -1336,30 +1353,6 @@ fn bang(never: !) {
1336 } 1353 }
1337 1354
1338 #[test] 1355 #[test]
1339 fn or_pattern_panic() {
1340 check_diagnostics(
1341 r#"
1342pub enum Category { Infinity, Zero }
1343
1344fn panic(a: Category, b: Category) {
1345 match (a, b) {
1346 (Category::Zero | Category::Infinity, _) => (),
1347 (_, Category::Zero | Category::Infinity) => (),
1348 }
1349
1350 // FIXME: This is a false positive, but the code used to cause a panic in the match checker,
1351 // so this acts as a regression test for that.
1352 match (a, b) {
1353 //^^^^^^ Missing match arm
1354 (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (),
1355 (Category::Infinity | Category::Zero, _) => (),
1356 }
1357}
1358"#,
1359 );
1360 }
1361
1362 #[test]
1363 fn unknown_type() { 1356 fn unknown_type() {
1364 check_diagnostics( 1357 check_diagnostics(
1365 r#" 1358 r#"
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 1f49a4909..ed97dc0e3 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,9 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; 14use crate::{
15 db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind,
16};
15 17
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 19 owner: DefWithBodyId,
@@ -32,7 +34,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
32 let def = self.owner; 34 let def = self.owner;
33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 35 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
34 let is_unsafe = match self.owner { 36 let is_unsafe = match self.owner {
35 DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, 37 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, 38 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
37 }; 39 };
38 if is_unsafe 40 if is_unsafe
@@ -86,7 +88,7 @@ fn walk_unsafe(
86 match expr { 88 match expr {
87 &Expr::Call { callee, .. } => { 89 &Expr::Call { callee, .. } => {
88 if let Some(func) = infer[callee].as_fn_def(db) { 90 if let Some(func) = infer[callee].as_fn_def(db) {
89 if db.function_data(func).qualifier.is_unsafe { 91 if db.function_data(func).is_unsafe() {
90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 92 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
91 } 93 }
92 } 94 }
@@ -103,14 +105,14 @@ fn walk_unsafe(
103 Expr::MethodCall { .. } => { 105 Expr::MethodCall { .. } => {
104 if infer 106 if infer
105 .method_resolution(current) 107 .method_resolution(current)
106 .map(|func| db.function_data(func).qualifier.is_unsafe) 108 .map(|func| db.function_data(func).is_unsafe())
107 .unwrap_or(false) 109 .unwrap_or(false)
108 { 110 {
109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 111 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
110 } 112 }
111 } 113 }
112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => { 114 Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
113 if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) { 115 if let TyKind::Raw(..) = &infer[*expr].kind(&Interner) {
114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 116 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
115 } 117 }
116 } 118 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 51480304b..e0ca96c6d 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -1,14 +1,17 @@
1//! FIXME: write short doc here 1//! FIXME: write short doc here
2 2
3use std::{array, fmt}; 3use std::{
4 array,
5 fmt::{self, Debug},
6};
4 7
5use chalk_ir::Mutability; 8use chalk_ir::BoundVar;
6use hir_def::{ 9use hir_def::{
7 db::DefDatabase, 10 db::DefDatabase,
8 find_path, 11 find_path,
9 generics::TypeParamProvenance, 12 generics::TypeParamProvenance,
10 item_scope::ItemInNs, 13 item_scope::ItemInNs,
11 path::{GenericArg, Path, PathKind}, 14 path::{Path, PathKind},
12 type_ref::{TypeBound, TypeRef}, 15 type_ref::{TypeBound, TypeRef},
13 visibility::Visibility, 16 visibility::Visibility,
14 AssocContainerId, Lookup, ModuleId, TraitId, 17 AssocContainerId, Lookup, ModuleId, TraitId,
@@ -16,10 +19,12 @@ use hir_def::{
16use hir_expand::name::Name; 19use hir_expand::name::Name;
17 20
18use crate::{ 21use crate::{
19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 22 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, 23 from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id,
21 CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, 24 traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId,
22 ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, 25 CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime,
26 LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
27 QuantifiedWhereClause, Scalar, TraitRef, TraitRefExt, Ty, TyExt, TyKind, WhereClause,
23}; 28};
24 29
25pub struct HirFormatter<'a> { 30pub struct HirFormatter<'a> {
@@ -46,6 +51,10 @@ pub trait HirDisplay {
46 where 51 where
47 Self: Sized, 52 Self: Sized,
48 { 53 {
54 assert!(
55 !matches!(display_target, DisplayTarget::SourceCode { .. }),
56 "HirDisplayWrapper cannot fail with DisplaySourceCodeError, use HirDisplay::hir_fmt directly instead"
57 );
49 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target } 58 HirDisplayWrapper { db, t: self, max_size, omit_verbose_types, display_target }
50 } 59 }
51 60
@@ -230,7 +239,7 @@ where
230 Err(HirDisplayError::FmtError) => Err(fmt::Error), 239 Err(HirDisplayError::FmtError) => Err(fmt::Error),
231 Err(HirDisplayError::DisplaySourceCodeError(_)) => { 240 Err(HirDisplayError::DisplaySourceCodeError(_)) => {
232 // This should never happen 241 // This should never happen
233 panic!("HirDisplay failed when calling Display::fmt!") 242 panic!("HirDisplay::hir_fmt failed with DisplaySourceCodeError when calling Display::fmt!")
234 } 243 }
235 } 244 }
236 } 245 }
@@ -251,16 +260,12 @@ impl HirDisplay for ProjectionTy {
251 } 260 }
252 261
253 let trait_ = f.db.trait_data(self.trait_(f.db)); 262 let trait_ = f.db.trait_data(self.trait_(f.db));
254 let first_parameter = self.substitution[0].into_displayable( 263 write!(f, "<")?;
255 f.db, 264 self.self_type_parameter(&Interner).hir_fmt(f)?;
256 f.max_size, 265 write!(f, " as {}", trait_.name)?;
257 f.omit_verbose_types, 266 if self.substitution.len(&Interner) > 1 {
258 f.display_target,
259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len() > 1 {
262 write!(f, "<")?; 267 write!(f, "<")?;
263 f.write_joined(&self.substitution[1..], ", ")?; 268 f.write_joined(&self.substitution.interned()[1..], ", ")?;
264 write!(f, ">")?; 269 write!(f, ">")?;
265 } 270 }
266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 271 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -274,7 +279,38 @@ impl HirDisplay for OpaqueTy {
274 return write!(f, "{}", TYPE_HINT_TRUNCATION); 279 return write!(f, "{}", TYPE_HINT_TRUNCATION);
275 } 280 }
276 281
277 self.substitution[0].hir_fmt(f) 282 self.substitution.at(&Interner, 0).hir_fmt(f)
283 }
284}
285
286impl HirDisplay for GenericArg {
287 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
288 match self.interned() {
289 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
290 }
291 }
292}
293
294impl HirDisplay for Const {
295 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
296 let data = self.interned();
297 match data.value {
298 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
299 ConstValue::InferenceVar(..) => write!(f, "_"),
300 ConstValue::Placeholder(idx) => {
301 let id = const_from_placeholder_idx(f.db, idx);
302 let generics = generics(f.db.upcast(), id.parent);
303 let param_data = &generics.params.consts[id.local_id];
304 write!(f, "{}", param_data.name)
305 }
306 ConstValue::Concrete(_) => write!(f, "_"),
307 }
308 }
309}
310
311impl HirDisplay for BoundVar {
312 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
313 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
278 } 314 }
279} 315}
280 316
@@ -284,7 +320,7 @@ impl HirDisplay for Ty {
284 return write!(f, "{}", TYPE_HINT_TRUNCATION); 320 return write!(f, "{}", TYPE_HINT_TRUNCATION);
285 } 321 }
286 322
287 match self.interned(&Interner) { 323 match self.kind(&Interner) {
288 TyKind::Never => write!(f, "!")?, 324 TyKind::Never => write!(f, "!")?,
289 TyKind::Str => write!(f, "str")?, 325 TyKind::Str => write!(f, "str")?,
290 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, 326 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
@@ -297,16 +333,15 @@ impl HirDisplay for Ty {
297 t.hir_fmt(f)?; 333 t.hir_fmt(f)?;
298 write!(f, "]")?; 334 write!(f, "]")?;
299 } 335 }
300 TyKind::Array(t) => { 336 TyKind::Array(t, c) => {
301 write!(f, "[")?; 337 write!(f, "[")?;
302 t.hir_fmt(f)?; 338 t.hir_fmt(f)?;
303 write!(f, "; _]")?; 339 write!(f, "; ")?;
340 c.hir_fmt(f)?;
341 write!(f, "]")?;
304 } 342 }
305 TyKind::Raw(m, t) | TyKind::Ref(m, t) => { 343 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
306 let ty_display = 344 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
307 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
308
309 if matches!(self.interned(&Interner), TyKind::Raw(..)) {
310 write!( 345 write!(
311 f, 346 f,
312 "*{}", 347 "*{}",
@@ -328,7 +363,7 @@ impl HirDisplay for Ty {
328 363
329 // FIXME: all this just to decide whether to use parentheses... 364 // FIXME: all this just to decide whether to use parentheses...
330 let datas; 365 let datas;
331 let predicates: Vec<_> = match t.interned(&Interner) { 366 let predicates: Vec<_> = match t.kind(&Interner) {
332 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { 367 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
333 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() 368 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
334 } 369 }
@@ -344,8 +379,8 @@ impl HirDisplay for Ty {
344 let data = (*datas) 379 let data = (*datas)
345 .as_ref() 380 .as_ref()
346 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 381 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
347 let bounds = data.subst(parameters); 382 let bounds = data.substitute(&Interner, parameters);
348 bounds.value 383 bounds.into_value_and_skipped_binders().0
349 } else { 384 } else {
350 Vec::new() 385 Vec::new()
351 } 386 }
@@ -360,26 +395,26 @@ impl HirDisplay for Ty {
360 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_) 395 if fn_traits(f.db.upcast(), trait_).any(|it| it == trait_)
361 && predicates.len() <= 2 396 && predicates.len() <= 2
362 { 397 {
363 return write!(f, "{}", ty_display); 398 return t.hir_fmt(f);
364 } 399 }
365 } 400 }
366 401
367 if predicates.len() > 1 { 402 if predicates.len() > 1 {
368 write!(f, "(")?; 403 write!(f, "(")?;
369 write!(f, "{}", ty_display)?; 404 t.hir_fmt(f)?;
370 write!(f, ")")?; 405 write!(f, ")")?;
371 } else { 406 } else {
372 write!(f, "{}", ty_display)?; 407 t.hir_fmt(f)?;
373 } 408 }
374 } 409 }
375 TyKind::Tuple(_, substs) => { 410 TyKind::Tuple(_, substs) => {
376 if substs.len() == 1 { 411 if substs.len(&Interner) == 1 {
377 write!(f, "(")?; 412 write!(f, "(")?;
378 substs[0].hir_fmt(f)?; 413 substs.at(&Interner, 0).hir_fmt(f)?;
379 write!(f, ",)")?; 414 write!(f, ",)")?;
380 } else { 415 } else {
381 write!(f, "(")?; 416 write!(f, "(")?;
382 f.write_joined(&*substs.0, ", ")?; 417 f.write_joined(&*substs.interned(), ", ")?;
383 write!(f, ")")?; 418 write!(f, ")")?;
384 } 419 }
385 } 420 }
@@ -389,7 +424,7 @@ impl HirDisplay for Ty {
389 } 424 }
390 TyKind::FnDef(def, parameters) => { 425 TyKind::FnDef(def, parameters) => {
391 let def = from_chalk(f.db, *def); 426 let def = from_chalk(f.db, *def);
392 let sig = f.db.callable_item_signature(def).subst(parameters); 427 let sig = f.db.callable_item_signature(def).substitute(&Interner, parameters);
393 match def { 428 match def {
394 CallableDefId::FunctionId(ff) => { 429 CallableDefId::FunctionId(ff) => {
395 write!(f, "fn {}", f.db.function_data(ff).name)? 430 write!(f, "fn {}", f.db.function_data(ff).name)?
@@ -399,7 +434,7 @@ impl HirDisplay for Ty {
399 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 434 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
400 } 435 }
401 }; 436 };
402 if parameters.len() > 0 { 437 if parameters.len(&Interner) > 0 {
403 let generics = generics(f.db.upcast(), def.into()); 438 let generics = generics(f.db.upcast(), def.into());
404 let (parent_params, self_param, type_params, _impl_trait_params) = 439 let (parent_params, self_param, type_params, _impl_trait_params) =
405 generics.provenance_split(); 440 generics.provenance_split();
@@ -407,7 +442,7 @@ impl HirDisplay for Ty {
407 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 442 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
408 if total_len > 0 { 443 if total_len > 0 {
409 write!(f, "<")?; 444 write!(f, "<")?;
410 f.write_joined(&parameters.0[..total_len], ", ")?; 445 f.write_joined(&parameters.interned()[..total_len], ", ")?;
411 write!(f, ">")?; 446 write!(f, ">")?;
412 } 447 }
413 } 448 }
@@ -415,15 +450,9 @@ impl HirDisplay for Ty {
415 f.write_joined(sig.params(), ", ")?; 450 f.write_joined(sig.params(), ", ")?;
416 write!(f, ")")?; 451 write!(f, ")")?;
417 let ret = sig.ret(); 452 let ret = sig.ret();
418 if *ret != Ty::unit() { 453 if !ret.is_unit() {
419 let ret_display = ret.into_displayable( 454 write!(f, " -> ")?;
420 f.db, 455 ret.hir_fmt(f)?;
421 f.max_size,
422 f.omit_verbose_types,
423 f.display_target,
424 );
425
426 write!(f, " -> {}", ret_display)?;
427 } 456 }
428 } 457 }
429 TyKind::Adt(AdtId(def_id), parameters) => { 458 TyKind::Adt(AdtId(def_id), parameters) => {
@@ -451,7 +480,7 @@ impl HirDisplay for Ty {
451 } 480 }
452 } 481 }
453 482
454 if parameters.len() > 0 { 483 if parameters.len(&Interner) > 0 {
455 let parameters_to_write = if f.display_target.is_source_code() 484 let parameters_to_write = if f.display_target.is_source_code()
456 || f.omit_verbose_types() 485 || f.omit_verbose_types()
457 { 486 {
@@ -460,30 +489,35 @@ impl HirDisplay for Ty {
460 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 489 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
461 .filter(|defaults| !defaults.is_empty()) 490 .filter(|defaults| !defaults.is_empty())
462 { 491 {
463 None => parameters.0.as_ref(), 492 None => parameters.interned().as_ref(),
464 Some(default_parameters) => { 493 Some(default_parameters) => {
465 let mut default_from = 0; 494 let mut default_from = 0;
466 for (i, parameter) in parameters.iter().enumerate() { 495 for (i, parameter) in parameters.iter(&Interner).enumerate() {
467 match (parameter.interned(&Interner), default_parameters.get(i)) 496 match (
468 { 497 parameter.assert_ty_ref(&Interner).kind(&Interner),
469 (&TyKind::Unknown, _) | (_, None) => { 498 default_parameters.get(i),
499 ) {
500 (&TyKind::Error, _) | (_, None) => {
470 default_from = i + 1; 501 default_from = i + 1;
471 } 502 }
472 (_, Some(default_parameter)) => { 503 (_, Some(default_parameter)) => {
473 let actual_default = default_parameter 504 let actual_default =
474 .clone() 505 default_parameter.clone().substitute(
475 .subst(&parameters.prefix(i)); 506 &Interner,
476 if parameter != &actual_default { 507 &subst_prefix(parameters, i),
508 );
509 if parameter.assert_ty_ref(&Interner) != &actual_default
510 {
477 default_from = i + 1; 511 default_from = i + 1;
478 } 512 }
479 } 513 }
480 } 514 }
481 } 515 }
482 &parameters.0[0..default_from] 516 &parameters.interned()[0..default_from]
483 } 517 }
484 } 518 }
485 } else { 519 } else {
486 parameters.0.as_ref() 520 parameters.interned().as_ref()
487 }; 521 };
488 if !parameters_to_write.is_empty() { 522 if !parameters_to_write.is_empty() {
489 write!(f, "<")?; 523 write!(f, "<")?;
@@ -504,9 +538,9 @@ impl HirDisplay for Ty {
504 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 538 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
505 if f.display_target.is_test() { 539 if f.display_target.is_test() {
506 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 540 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
507 if parameters.len() > 0 { 541 if parameters.len(&Interner) > 0 {
508 write!(f, "<")?; 542 write!(f, "<")?;
509 f.write_joined(&*parameters.0, ", ")?; 543 f.write_joined(&*parameters.interned(), ", ")?;
510 write!(f, ">")?; 544 write!(f, ">")?;
511 } 545 }
512 } else { 546 } else {
@@ -518,7 +552,7 @@ impl HirDisplay for Ty {
518 projection_ty.hir_fmt(f)?; 552 projection_ty.hir_fmt(f)?;
519 } 553 }
520 } 554 }
521 TyKind::ForeignType(type_alias) => { 555 TyKind::Foreign(type_alias) => {
522 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias)); 556 let type_alias = f.db.type_alias_data(from_foreign_def_id(*type_alias));
523 write!(f, "{}", type_alias.name)?; 557 write!(f, "{}", type_alias.name)?;
524 } 558 }
@@ -531,13 +565,13 @@ impl HirDisplay for Ty {
531 let data = (*datas) 565 let data = (*datas)
532 .as_ref() 566 .as_ref()
533 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 567 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
534 let bounds = data.subst(&parameters); 568 let bounds = data.substitute(&Interner, &parameters);
535 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 569 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
536 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution 570 // FIXME: it would maybe be good to distinguish this from the alias type (when debug printing), and to show the substitution
537 } 571 }
538 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 572 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
539 write!(f, "impl Future<Output = ")?; 573 write!(f, "impl Future<Output = ")?;
540 parameters[0].hir_fmt(f)?; 574 parameters.at(&Interner, 0).hir_fmt(f)?;
541 write!(f, ">")?; 575 write!(f, ">")?;
542 } 576 }
543 } 577 }
@@ -548,7 +582,7 @@ impl HirDisplay for Ty {
548 DisplaySourceCodeError::Closure, 582 DisplaySourceCodeError::Closure,
549 )); 583 ));
550 } 584 }
551 let sig = substs[0].callable_sig(f.db); 585 let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db);
552 if let Some(sig) = sig { 586 if let Some(sig) = sig {
553 if sig.params().is_empty() { 587 if sig.params().is_empty() {
554 write!(f, "||")?; 588 write!(f, "||")?;
@@ -560,13 +594,8 @@ impl HirDisplay for Ty {
560 write!(f, "|")?; 594 write!(f, "|")?;
561 }; 595 };
562 596
563 let ret_display = sig.ret().into_displayable( 597 write!(f, " -> ")?;
564 f.db, 598 sig.ret().hir_fmt(f)?;
565 f.max_size,
566 f.omit_verbose_types,
567 f.display_target,
568 );
569 write!(f, " -> {}", ret_display)?;
570 } else { 599 } else {
571 write!(f, "{{closure}}")?; 600 write!(f, "{{closure}}")?;
572 } 601 }
@@ -580,26 +609,27 @@ impl HirDisplay for Ty {
580 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 609 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
581 } 610 }
582 TypeParamProvenance::ArgumentImplTrait => { 611 TypeParamProvenance::ArgumentImplTrait => {
583 let substs = Substitution::type_params_for_generics(f.db, &generics); 612 let substs = generics.type_params_subst(f.db);
584 let bounds = f 613 let bounds =
585 .db 614 f.db.generic_predicates(id.parent)
586 .generic_predicates(id.parent) 615 .into_iter()
587 .into_iter() 616 .map(|pred| pred.clone().substitute(&Interner, &substs))
588 .map(|pred| pred.clone().subst(&substs)) 617 .filter(|wc| match &wc.skip_binders() {
589 .filter(|wc| match &wc.skip_binders() { 618 WhereClause::Implemented(tr) => {
590 WhereClause::Implemented(tr) => tr.self_type_parameter() == self, 619 &tr.self_type_parameter(&Interner) == self
591 WhereClause::AliasEq(AliasEq { 620 }
592 alias: AliasTy::Projection(proj), 621 WhereClause::AliasEq(AliasEq {
593 ty: _, 622 alias: AliasTy::Projection(proj),
594 }) => proj.self_type_parameter() == self, 623 ty: _,
595 _ => false, 624 }) => &proj.self_type_parameter(&Interner) == self,
596 }) 625 _ => false,
597 .collect::<Vec<_>>(); 626 })
627 .collect::<Vec<_>>();
598 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?; 628 write_bounds_like_dyn_trait_with_prefix("impl", &bounds, f)?;
599 } 629 }
600 } 630 }
601 } 631 }
602 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 632 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
603 TyKind::Dyn(dyn_ty) => { 633 TyKind::Dyn(dyn_ty) => {
604 write_bounds_like_dyn_trait_with_prefix( 634 write_bounds_like_dyn_trait_with_prefix(
605 "dyn", 635 "dyn",
@@ -617,15 +647,15 @@ impl HirDisplay for Ty {
617 let data = (*datas) 647 let data = (*datas)
618 .as_ref() 648 .as_ref()
619 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone()); 649 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
620 let bounds = data.subst(&opaque_ty.substitution); 650 let bounds = data.substitute(&Interner, &opaque_ty.substitution);
621 write_bounds_like_dyn_trait_with_prefix("impl", &bounds.value, f)?; 651 write_bounds_like_dyn_trait_with_prefix("impl", bounds.skip_binders(), f)?;
622 } 652 }
623 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 653 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
624 write!(f, "{{async block}}")?; 654 write!(f, "{{async block}}")?;
625 } 655 }
626 }; 656 };
627 } 657 }
628 TyKind::Unknown => { 658 TyKind::Error => {
629 if f.display_target.is_source_code() { 659 if f.display_target.is_source_code() {
630 return Err(HirDisplayError::DisplaySourceCodeError( 660 return Err(HirDisplayError::DisplaySourceCodeError(
631 DisplaySourceCodeError::UnknownType, 661 DisplaySourceCodeError::UnknownType,
@@ -652,10 +682,9 @@ impl HirDisplay for CallableSig {
652 } 682 }
653 write!(f, ")")?; 683 write!(f, ")")?;
654 let ret = self.ret(); 684 let ret = self.ret();
655 if *ret != Ty::unit() { 685 if !ret.is_unit() {
656 let ret_display = 686 write!(f, " -> ")?;
657 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 687 ret.hir_fmt(f)?;
658 write!(f, " -> {}", ret_display)?;
659 } 688 }
660 Ok(()) 689 Ok(())
661 } 690 }
@@ -716,11 +745,13 @@ fn write_bounds_like_dyn_trait(
716 // existential) here, which is the only thing that's 745 // existential) here, which is the only thing that's
717 // possible in actual Rust, and hence don't print it 746 // possible in actual Rust, and hence don't print it
718 write!(f, "{}", f.db.trait_data(trait_).name)?; 747 write!(f, "{}", f.db.trait_data(trait_).name)?;
719 if let [_, params @ ..] = &*trait_ref.substitution.0 { 748 if let [_, params @ ..] = &*trait_ref.substitution.interned().as_slice() {
720 if is_fn_trait { 749 if is_fn_trait {
721 if let Some(args) = params.first().and_then(|it| it.as_tuple()) { 750 if let Some(args) =
751 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
752 {
722 write!(f, "(")?; 753 write!(f, "(")?;
723 f.write_joined(&*args.0, ", ")?; 754 f.write_joined(&*args.interned(), ", ")?;
724 write!(f, ")")?; 755 write!(f, ")")?;
725 } 756 }
726 } else if !params.is_empty() { 757 } else if !params.is_empty() {
@@ -761,31 +792,29 @@ fn write_bounds_like_dyn_trait(
761 Ok(()) 792 Ok(())
762} 793}
763 794
764impl TraitRef { 795fn fmt_trait_ref(tr: &TraitRef, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> {
765 fn hir_fmt_ext(&self, f: &mut HirFormatter, use_as: bool) -> Result<(), HirDisplayError> { 796 if f.should_truncate() {
766 if f.should_truncate() { 797 return write!(f, "{}", TYPE_HINT_TRUNCATION);
767 return write!(f, "{}", TYPE_HINT_TRUNCATION); 798 }
768 }
769 799
770 self.substitution[0].hir_fmt(f)?; 800 tr.self_type_parameter(&Interner).hir_fmt(f)?;
771 if use_as { 801 if use_as {
772 write!(f, " as ")?; 802 write!(f, " as ")?;
773 } else { 803 } else {
774 write!(f, ": ")?; 804 write!(f, ": ")?;
775 }
776 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
777 if self.substitution.len() > 1 {
778 write!(f, "<")?;
779 f.write_joined(&self.substitution[1..], ", ")?;
780 write!(f, ">")?;
781 }
782 Ok(())
783 } 805 }
806 write!(f, "{}", f.db.trait_data(tr.hir_trait_id()).name)?;
807 if tr.substitution.len(&Interner) > 1 {
808 write!(f, "<")?;
809 f.write_joined(&tr.substitution.interned()[1..], ", ")?;
810 write!(f, ">")?;
811 }
812 Ok(())
784} 813}
785 814
786impl HirDisplay for TraitRef { 815impl HirDisplay for TraitRef {
787 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 816 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
788 self.hir_fmt_ext(f, false) 817 fmt_trait_ref(self, f, false)
789 } 818 }
790} 819}
791 820
@@ -799,7 +828,7 @@ impl HirDisplay for WhereClause {
799 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?, 828 WhereClause::Implemented(trait_ref) => trait_ref.hir_fmt(f)?,
800 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => { 829 WhereClause::AliasEq(AliasEq { alias: AliasTy::Projection(projection_ty), ty }) => {
801 write!(f, "<")?; 830 write!(f, "<")?;
802 projection_ty.trait_ref(f.db).hir_fmt_ext(f, true)?; 831 fmt_trait_ref(&projection_ty.trait_ref(f.db), f, true)?;
803 write!( 832 write!(
804 f, 833 f,
805 ">::{} = ", 834 ">::{} = ",
@@ -813,15 +842,35 @@ impl HirDisplay for WhereClause {
813 } 842 }
814} 843}
815 844
845impl HirDisplay for LifetimeOutlives {
846 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
847 self.a.hir_fmt(f)?;
848 write!(f, ": ")?;
849 self.b.hir_fmt(f)
850 }
851}
852
816impl HirDisplay for Lifetime { 853impl HirDisplay for Lifetime {
817 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 854 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
855 self.interned().hir_fmt(f)
856 }
857}
858
859impl HirDisplay for LifetimeData {
860 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
818 match self { 861 match self {
819 Lifetime::Parameter(id) => { 862 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
863 LifetimeData::InferenceVar(_) => write!(f, "_"),
864 LifetimeData::Placeholder(idx) => {
865 let id = lt_from_placeholder_idx(f.db, *idx);
820 let generics = generics(f.db.upcast(), id.parent); 866 let generics = generics(f.db.upcast(), id.parent);
821 let param_data = &generics.params.lifetimes[id.local_id]; 867 let param_data = &generics.params.lifetimes[id.local_id];
822 write!(f, "{}", &param_data.name) 868 write!(f, "{}", param_data.name)
823 } 869 }
824 Lifetime::Static => write!(f, "'static"), 870 LifetimeData::Static => write!(f, "'static"),
871 LifetimeData::Empty(_) => Ok(()),
872 LifetimeData::Erased => Ok(()),
873 LifetimeData::Phantom(_, _) => Ok(()),
825 } 874 }
826 } 875 }
827} 876}
@@ -1016,11 +1065,11 @@ impl HirDisplay for Path {
1016 } 1065 }
1017} 1066}
1018 1067
1019impl HirDisplay for GenericArg { 1068impl HirDisplay for hir_def::path::GenericArg {
1020 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 1069 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1021 match self { 1070 match self {
1022 GenericArg::Type(ty) => ty.hir_fmt(f), 1071 hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1023 GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), 1072 hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1024 } 1073 }
1025 } 1074 }
1026} 1075}
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 8f9cf7480..531159e54 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -37,14 +37,19 @@ use stdx::impl_from;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{DomainGoal, Guidance, Solution}, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Canonical, Interner, TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details.
49//
50// https://github.com/rust-lang/rust/issues/57411
51#[allow(unreachable_pub)]
52pub use unify::could_unify;
48pub(crate) use unify::unify; 53pub(crate) use unify::unify;
49 54
50mod unify; 55mod unify;
@@ -115,7 +120,7 @@ struct InternedStandardTypes {
115 120
116impl Default for InternedStandardTypes { 121impl Default for InternedStandardTypes {
117 fn default() -> Self { 122 fn default() -> Self {
118 InternedStandardTypes { unknown: TyKind::Unknown.intern(&Interner) } 123 InternedStandardTypes { unknown: TyKind::Error.intern(&Interner) }
119 } 124 }
120} 125}
121 126
@@ -126,10 +131,7 @@ pub struct InferenceResult {
126 method_resolutions: FxHashMap<ExprId, FunctionId>, 131 method_resolutions: FxHashMap<ExprId, FunctionId>,
127 /// For each field access expr, records the field it resolves to. 132 /// For each field access expr, records the field it resolves to.
128 field_resolutions: FxHashMap<ExprId, FieldId>, 133 field_resolutions: FxHashMap<ExprId, FieldId>,
129 /// 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.
130 record_field_resolutions: FxHashMap<ExprId, FieldId>,
131 record_pat_field_resolutions: FxHashMap<PatId, FieldId>,
132 /// For each struct literal, records the variant it resolves to.
133 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>, 135 variant_resolutions: FxHashMap<ExprOrPatId, VariantId>,
134 /// For each associated item record what it resolves to 136 /// For each associated item record what it resolves to
135 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>, 137 assoc_resolutions: FxHashMap<ExprOrPatId, AssocItemId>,
@@ -148,12 +150,6 @@ impl InferenceResult {
148 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> { 150 pub fn field_resolution(&self, expr: ExprId) -> Option<FieldId> {
149 self.field_resolutions.get(&expr).copied() 151 self.field_resolutions.get(&expr).copied()
150 } 152 }
151 pub fn record_field_resolution(&self, expr: ExprId) -> Option<FieldId> {
152 self.record_field_resolutions.get(&expr).copied()
153 }
154 pub fn record_pat_field_resolution(&self, pat: PatId) -> Option<FieldId> {
155 self.record_pat_field_resolutions.get(&pat).copied()
156 }
157 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> { 153 pub fn variant_resolution_for_expr(&self, id: ExprId) -> Option<VariantId> {
158 self.variant_resolutions.get(&id.into()).copied() 154 self.variant_resolutions.get(&id.into()).copied()
159 } 155 }
@@ -205,6 +201,7 @@ struct InferenceContext<'a> {
205 table: unify::InferenceTable, 201 table: unify::InferenceTable,
206 trait_env: Arc<TraitEnvironment>, 202 trait_env: Arc<TraitEnvironment>,
207 obligations: Vec<DomainGoal>, 203 obligations: Vec<DomainGoal>,
204 last_obligations_check: Option<u32>,
208 result: InferenceResult, 205 result: InferenceResult,
209 /// The return type of the function being inferred, or the closure if we're 206 /// The return type of the function being inferred, or the closure if we're
210 /// currently within one. 207 /// currently within one.
@@ -240,7 +237,8 @@ impl<'a> InferenceContext<'a> {
240 result: InferenceResult::default(), 237 result: InferenceResult::default(),
241 table: unify::InferenceTable::new(), 238 table: unify::InferenceTable::new(),
242 obligations: Vec::default(), 239 obligations: Vec::default(),
243 return_ty: TyKind::Unknown.intern(&Interner), // set in collect_fn_signature 240 last_obligations_check: None,
241 return_ty: TyKind::Error.intern(&Interner), // set in collect_fn_signature
244 trait_env: owner 242 trait_env: owner
245 .as_generic_def_id() 243 .as_generic_def_id()
246 .map_or_else(Default::default, |d| db.trait_environment(d)), 244 .map_or_else(Default::default, |d| db.trait_environment(d)),
@@ -254,7 +252,7 @@ impl<'a> InferenceContext<'a> {
254 } 252 }
255 253
256 fn err_ty(&self) -> Ty { 254 fn err_ty(&self) -> Ty {
257 TyKind::Unknown.intern(&Interner) 255 TyKind::Error.intern(&Interner)
258 } 256 }
259 257
260 fn resolve_all(mut self) -> InferenceResult { 258 fn resolve_all(mut self) -> InferenceResult {
@@ -318,8 +316,8 @@ impl<'a> InferenceContext<'a> {
318 316
319 /// 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.
320 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 318 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
321 match ty.interned(&Interner) { 319 match ty.kind(&Interner) {
322 TyKind::Unknown => self.table.new_type_var(), 320 TyKind::Error => self.table.new_type_var(),
323 _ => ty, 321 _ => ty,
324 } 322 }
325 } 323 }
@@ -329,19 +327,33 @@ impl<'a> InferenceContext<'a> {
329 } 327 }
330 328
331 fn resolve_obligations_as_possible(&mut self) { 329 fn resolve_obligations_as_possible(&mut self) {
330 if self.last_obligations_check == Some(self.table.revision) {
331 // no change
332 return;
333 }
334 let _span = profile::span("resolve_obligations_as_possible");
335
336 self.last_obligations_check = Some(self.table.revision);
332 let obligations = mem::replace(&mut self.obligations, Vec::new()); 337 let obligations = mem::replace(&mut self.obligations, Vec::new());
333 for obligation in obligations { 338 for obligation in obligations {
334 let in_env = InEnvironment::new(self.trait_env.env.clone(), obligation.clone()); 339 let in_env = InEnvironment::new(&self.trait_env.env, obligation.clone());
335 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env); 340 let canonicalized = self.canonicalizer().canonicalize_obligation(in_env);
336 let solution = 341 let solution =
337 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone()); 342 self.db.trait_solve(self.resolver.krate().unwrap(), canonicalized.value.clone());
338 343
339 match solution { 344 match solution {
340 Some(Solution::Unique(substs)) => { 345 Some(Solution::Unique(canonical_subst)) => {
341 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 );
342 } 354 }
343 Some(Solution::Ambig(Guidance::Definite(substs))) => { 355 Some(Solution::Ambig(Guidance::Definite(substs))) => {
344 canonicalized.apply_solution(self, substs.0); 356 canonicalized.apply_solution(self, substs);
345 self.obligations.push(obligation); 357 self.obligations.push(obligation);
346 } 358 }
347 Some(_) => { 359 Some(_) => {
@@ -355,6 +367,11 @@ impl<'a> InferenceContext<'a> {
355 } 367 }
356 } 368 }
357 369
370 fn push_obligation(&mut self, o: DomainGoal) {
371 self.obligations.push(o);
372 self.last_obligations_check = None;
373 }
374
358 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool { 375 fn unify(&mut self, ty1: &Ty, ty2: &Ty) -> bool {
359 self.table.unify(ty1, ty2) 376 self.table.unify(ty1, ty2)
360 } 377 }
@@ -390,21 +407,19 @@ impl<'a> InferenceContext<'a> {
390 _ => panic!("resolve_associated_type called with non-associated type"), 407 _ => panic!("resolve_associated_type called with non-associated type"),
391 }; 408 };
392 let ty = self.table.new_type_var(); 409 let ty = self.table.new_type_var();
393 let substs = Substitution::build_for_def(self.db, res_assoc_ty) 410 let trait_ref = TyBuilder::trait_ref(self.db, trait_)
394 .push(inner_ty) 411 .push(inner_ty)
395 .fill(params.iter().cloned()) 412 .fill(params.iter().cloned())
396 .build(); 413 .build();
397 let trait_ref =
398 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
399 let alias_eq = AliasEq { 414 let alias_eq = AliasEq {
400 alias: AliasTy::Projection(ProjectionTy { 415 alias: AliasTy::Projection(ProjectionTy {
401 associated_ty_id: to_assoc_type_id(res_assoc_ty), 416 associated_ty_id: to_assoc_type_id(res_assoc_ty),
402 substitution: substs, 417 substitution: trait_ref.substitution.clone(),
403 }), 418 }),
404 ty: ty.clone(), 419 ty: ty.clone(),
405 }; 420 };
406 self.obligations.push(trait_ref.cast(&Interner)); 421 self.push_obligation(trait_ref.cast(&Interner));
407 self.obligations.push(alias_eq.cast(&Interner)); 422 self.push_obligation(alias_eq.cast(&Interner));
408 self.resolve_ty_as_possible(ty) 423 self.resolve_ty_as_possible(ty)
409 } 424 }
410 None => self.err_ty(), 425 None => self.err_ty(),
@@ -419,7 +434,7 @@ impl<'a> InferenceContext<'a> {
419 /// to do it as well. 434 /// to do it as well.
420 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty { 435 fn normalize_associated_types_in(&mut self, ty: Ty) -> Ty {
421 let ty = self.resolve_ty_as_possible(ty); 436 let ty = self.resolve_ty_as_possible(ty);
422 ty.fold(&mut |ty| match ty.interned(&Interner) { 437 ty.fold(&mut |ty| match ty.kind(&Interner) {
423 TyKind::Alias(AliasTy::Projection(proj_ty)) => { 438 TyKind::Alias(AliasTy::Projection(proj_ty)) => {
424 self.normalize_projection_ty(proj_ty.clone()) 439 self.normalize_projection_ty(proj_ty.clone())
425 } 440 }
@@ -431,7 +446,7 @@ impl<'a> InferenceContext<'a> {
431 let var = self.table.new_type_var(); 446 let var = self.table.new_type_var();
432 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() }; 447 let alias_eq = AliasEq { alias: AliasTy::Projection(proj_ty), ty: var.clone() };
433 let obligation = alias_eq.cast(&Interner); 448 let obligation = alias_eq.cast(&Interner);
434 self.obligations.push(obligation); 449 self.push_obligation(obligation);
435 var 450 var
436 } 451 }
437 452
@@ -453,56 +468,32 @@ impl<'a> InferenceContext<'a> {
453 TypeNs::AdtId(AdtId::StructId(strukt)) => { 468 TypeNs::AdtId(AdtId::StructId(strukt)) => {
454 let substs = ctx.substs_from_path(path, strukt.into(), true); 469 let substs = ctx.substs_from_path(path, strukt.into(), true);
455 let ty = self.db.ty(strukt.into()); 470 let ty = self.db.ty(strukt.into());
456 let ty = self.insert_type_vars(ty.subst(&substs)); 471 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
457 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved) 472 forbid_unresolved_segments((ty, Some(strukt.into())), unresolved)
458 } 473 }
459 TypeNs::AdtId(AdtId::UnionId(u)) => { 474 TypeNs::AdtId(AdtId::UnionId(u)) => {
460 let substs = ctx.substs_from_path(path, u.into(), true); 475 let substs = ctx.substs_from_path(path, u.into(), true);
461 let ty = self.db.ty(u.into()); 476 let ty = self.db.ty(u.into());
462 let ty = self.insert_type_vars(ty.subst(&substs)); 477 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
463 forbid_unresolved_segments((ty, Some(u.into())), unresolved) 478 forbid_unresolved_segments((ty, Some(u.into())), unresolved)
464 } 479 }
465 TypeNs::EnumVariantId(var) => { 480 TypeNs::EnumVariantId(var) => {
466 let substs = ctx.substs_from_path(path, var.into(), true); 481 let substs = ctx.substs_from_path(path, var.into(), true);
467 let ty = self.db.ty(var.parent.into()); 482 let ty = self.db.ty(var.parent.into());
468 let ty = self.insert_type_vars(ty.subst(&substs)); 483 let ty = self.insert_type_vars(ty.substitute(&Interner, &substs));
469 forbid_unresolved_segments((ty, Some(var.into())), unresolved) 484 forbid_unresolved_segments((ty, Some(var.into())), unresolved)
470 } 485 }
471 TypeNs::SelfType(impl_id) => { 486 TypeNs::SelfType(impl_id) => {
472 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 487 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
473 let substs = Substitution::type_params_for_generics(self.db, &generics); 488 let substs = generics.type_params_subst(self.db);
474 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 489 let ty = self.db.impl_self_ty(impl_id).substitute(&Interner, &substs);
475 match unresolved { 490 self.resolve_variant_on_alias(ty, unresolved, path)
476 None => {
477 let variant = ty_variant(&ty);
478 (ty, variant)
479 }
480 Some(1) => {
481 let segment = path.mod_path().segments().last().unwrap();
482 // this could be an enum variant or associated type
483 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
484 let enum_data = self.db.enum_data(enum_id);
485 if let Some(local_id) = enum_data.variant(segment) {
486 let variant = EnumVariantId { parent: enum_id, local_id };
487 return (ty, Some(variant.into()));
488 }
489 }
490 // FIXME potentially resolve assoc type
491 (self.err_ty(), None)
492 }
493 Some(_) => {
494 // FIXME diagnostic
495 (self.err_ty(), None)
496 }
497 }
498 } 491 }
499 TypeNs::TypeAliasId(it) => { 492 TypeNs::TypeAliasId(it) => {
500 let substs = Substitution::build_for_def(self.db, it) 493 let ty = TyBuilder::def_ty(self.db, it.into())
501 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 494 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
502 .build(); 495 .build();
503 let ty = self.db.ty(it.into()).subst(&substs); 496 self.resolve_variant_on_alias(ty, unresolved, path)
504 let variant = ty_variant(&ty);
505 forbid_unresolved_segments((ty, variant), unresolved)
506 } 497 }
507 TypeNs::AdtSelfType(_) => { 498 TypeNs::AdtSelfType(_) => {
508 // FIXME this could happen in array size expressions, once we're checking them 499 // FIXME this could happen in array size expressions, once we're checking them
@@ -526,19 +517,46 @@ impl<'a> InferenceContext<'a> {
526 result 517 result
527 } else { 518 } else {
528 // FIXME diagnostic 519 // FIXME diagnostic
529 (TyKind::Unknown.intern(&Interner), None) 520 (TyKind::Error.intern(&Interner), None)
530 } 521 }
531 } 522 }
523 }
532 524
533 fn ty_variant(ty: &Ty) -> Option<VariantId> { 525 fn resolve_variant_on_alias(
534 ty.as_adt().and_then(|(adt_id, _)| match adt_id { 526 &mut self,
535 AdtId::StructId(s) => Some(VariantId::StructId(s)), 527 ty: Ty,
536 AdtId::UnionId(u) => Some(VariantId::UnionId(u)), 528 unresolved: Option<usize>,
537 AdtId::EnumId(_) => { 529 path: &Path,
538 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo` 530 ) -> (Ty, Option<VariantId>) {
539 None 531 match unresolved {
532 None => {
533 let variant = ty.as_adt().and_then(|(adt_id, _)| match adt_id {
534 AdtId::StructId(s) => Some(VariantId::StructId(s)),
535 AdtId::UnionId(u) => Some(VariantId::UnionId(u)),
536 AdtId::EnumId(_) => {
537 // FIXME Error E0071, expected struct, variant or union type, found enum `Foo`
538 None
539 }
540 });
541 (ty, variant)
542 }
543 Some(1) => {
544 let segment = path.mod_path().segments().last().unwrap();
545 // this could be an enum variant or associated type
546 if let Some((AdtId::EnumId(enum_id), _)) = ty.as_adt() {
547 let enum_data = self.db.enum_data(enum_id);
548 if let Some(local_id) = enum_data.variant(segment) {
549 let variant = EnumVariantId { parent: enum_id, local_id };
550 return (ty, Some(variant.into()));
551 }
540 } 552 }
541 }) 553 // FIXME potentially resolve assoc type
554 (self.err_ty(), None)
555 }
556 Some(_) => {
557 // FIXME diagnostic
558 (self.err_ty(), None)
559 }
542 } 560 }
543 } 561 }
544 562
@@ -676,25 +694,6 @@ impl<'a> InferenceContext<'a> {
676 } 694 }
677} 695}
678 696
679/// The kinds of placeholders we need during type inference. There's separate
680/// values for general types, and for integer and float variables. The latter
681/// two are used for inference of literal values (e.g. `100` could be one of
682/// several integer types).
683#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
684pub struct InferenceVar {
685 index: u32,
686}
687
688impl InferenceVar {
689 fn to_inner(self) -> unify::TypeVarId {
690 unify::TypeVarId(self.index)
691 }
692
693 fn from_inner(unify::TypeVarId(index): unify::TypeVarId) -> Self {
694 InferenceVar { index }
695 }
696}
697
698/// When inferring an expression, we propagate downward whatever type hint we 697/// When inferring an expression, we propagate downward whatever type hint we
699/// are able in the form of an `Expectation`. 698/// are able in the form of an `Expectation`.
700#[derive(Clone, PartialEq, Eq, Debug)] 699#[derive(Clone, PartialEq, Eq, Debug)]
@@ -739,7 +738,7 @@ impl Expectation {
739 fn none() -> Self { 738 fn none() -> Self {
740 Expectation { 739 Expectation {
741 // FIXME 740 // FIXME
742 ty: TyKind::Unknown.intern(&Interner), 741 ty: TyKind::Error.intern(&Interner),
743 rvalue_hint: false, 742 rvalue_hint: false,
744 } 743 }
745 } 744 }
@@ -747,7 +746,7 @@ impl Expectation {
747 fn coercion_target(&self) -> Ty { 746 fn coercion_target(&self) -> Ty {
748 if self.rvalue_hint { 747 if self.rvalue_hint {
749 // FIXME 748 // FIXME
750 TyKind::Unknown.intern(&Interner) 749 TyKind::Error.intern(&Interner)
751 } else { 750 } else {
752 self.ty.clone() 751 self.ty.clone()
753 } 752 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index 9c62932b1..fd679f444 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,9 +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::{ 10use crate::{autoderef, Canonical, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
12};
13 11
14use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
15 13
@@ -36,7 +34,7 @@ impl<'a> InferenceContext<'a> {
36 ty1.clone() 34 ty1.clone()
37 } else { 35 } else {
38 if let (TyKind::FnDef(..), TyKind::FnDef(..)) = 36 if let (TyKind::FnDef(..), TyKind::FnDef(..)) =
39 (ty1.interned(&Interner), ty2.interned(&Interner)) 37 (ty1.kind(&Interner), ty2.kind(&Interner))
40 { 38 {
41 cov_mark::hit!(coerce_fn_reification); 39 cov_mark::hit!(coerce_fn_reification);
42 // Special case: two function types. Try to coerce both to 40 // Special case: two function types. Try to coerce both to
@@ -44,8 +42,8 @@ impl<'a> InferenceContext<'a> {
44 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 42 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
45 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); 43 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig");
46 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); 44 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig");
47 let ptr_ty1 = Ty::fn_ptr(sig1); 45 let ptr_ty1 = TyBuilder::fn_ptr(sig1);
48 let ptr_ty2 = Ty::fn_ptr(sig2); 46 let ptr_ty2 = TyBuilder::fn_ptr(sig2);
49 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) 47 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
50 } else { 48 } else {
51 cov_mark::hit!(coerce_merge_fail_fallback); 49 cov_mark::hit!(coerce_merge_fail_fallback);
@@ -55,7 +53,7 @@ impl<'a> InferenceContext<'a> {
55 } 53 }
56 54
57 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool { 55 fn coerce_inner(&mut self, mut from_ty: Ty, to_ty: &Ty) -> bool {
58 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { 56 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
59 // Never type will make type variable to fallback to Never Type instead of Unknown. 57 // Never type will make type variable to fallback to Never Type instead of Unknown.
60 (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => { 58 (TyKind::Never, TyKind::InferenceVar(tv, TyVariableKind::General)) => {
61 self.table.type_variable_table.set_diverging(*tv, true); 59 self.table.type_variable_table.set_diverging(*tv, true);
@@ -73,7 +71,7 @@ impl<'a> InferenceContext<'a> {
73 } 71 }
74 72
75 // Pointer weakening and function to pointer 73 // Pointer weakening and function to pointer
76 match (from_ty.interned_mut(), to_ty.interned(&Interner)) { 74 match (from_ty.interned_mut(), to_ty.kind(&Interner)) {
77 // `*mut T` -> `*const T` 75 // `*mut T` -> `*const T`
78 // `&mut T` -> `&T` 76 // `&mut T` -> `&T`
79 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..)) 77 (TyKind::Raw(m1, ..), TyKind::Raw(m2 @ Mutability::Not, ..))
@@ -83,7 +81,7 @@ impl<'a> InferenceContext<'a> {
83 // `&T` -> `*const T` 81 // `&T` -> `*const T`
84 // `&mut T` -> `*mut T`/`*const T` 82 // `&mut T` -> `*mut T`/`*const T`
85 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..)) 83 (TyKind::Ref(.., substs), &TyKind::Raw(m2 @ Mutability::Not, ..))
86 | (TyKind::Ref(Mutability::Mut, substs), &TyKind::Raw(m2, ..)) => { 84 | (TyKind::Ref(Mutability::Mut, _, substs), &TyKind::Raw(m2, ..)) => {
87 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner); 85 from_ty = TyKind::Raw(m2, substs.clone()).intern(&Interner);
88 } 86 }
89 87
@@ -95,12 +93,12 @@ impl<'a> InferenceContext<'a> {
95 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { 93 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) {
96 None => return false, 94 None => return false,
97 Some(sig) => { 95 Some(sig) => {
98 from_ty = Ty::fn_ptr(sig); 96 from_ty = TyBuilder::fn_ptr(sig);
99 } 97 }
100 }, 98 },
101 99
102 (TyKind::Closure(.., substs), TyKind::Function { .. }) => { 100 (TyKind::Closure(.., substs), TyKind::Function { .. }) => {
103 from_ty = substs[0].clone(); 101 from_ty = substs.at(&Interner, 0).assert_ty_ref(&Interner).clone();
104 } 102 }
105 103
106 _ => {} 104 _ => {}
@@ -111,9 +109,11 @@ impl<'a> InferenceContext<'a> {
111 } 109 }
112 110
113 // Auto Deref if cannot coerce 111 // Auto Deref if cannot coerce
114 match (from_ty.interned(&Interner), to_ty.interned(&Interner)) { 112 match (from_ty.kind(&Interner), to_ty.kind(&Interner)) {
115 // FIXME: DerefMut 113 // FIXME: DerefMut
116 (TyKind::Ref(_, st1), TyKind::Ref(_, st2)) => self.unify_autoderef_behind_ref(st1, st2), 114 (TyKind::Ref(.., st1), TyKind::Ref(.., st2)) => {
115 self.unify_autoderef_behind_ref(st1, st2)
116 }
117 117
118 // Otherwise, normal unify 118 // Otherwise, normal unify
119 _ => self.unify(&from_ty, to_ty), 119 _ => self.unify(&from_ty, to_ty),
@@ -130,19 +130,16 @@ impl<'a> InferenceContext<'a> {
130 _ => return None, 130 _ => return None,
131 }; 131 };
132 132
133 let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); 133 let trait_ref = {
134 if generic_params.len() != 2 { 134 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
135 // The CoerceUnsized trait should have two generic params: Self and T. 135 if b.remaining() != 2 {
136 return None; 136 // The CoerceUnsized trait should have two generic params: Self and T.
137 } 137 return None;
138 }
139 b.push(from_ty.clone()).push(to_ty.clone()).build()
140 };
138 141
139 let substs = Substitution::build_for_generics(&generic_params) 142 let goal = InEnvironment::new(&self.trait_env.env, trait_ref.cast(&Interner));
140 .push(from_ty.clone())
141 .push(to_ty.clone())
142 .build();
143 let trait_ref =
144 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
145 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner));
146 143
147 let canonicalizer = self.canonicalizer(); 144 let canonicalizer = self.canonicalizer();
148 let canonicalized = canonicalizer.canonicalize_obligation(goal); 145 let canonicalized = canonicalizer.canonicalize_obligation(goal);
@@ -151,7 +148,14 @@ impl<'a> InferenceContext<'a> {
151 148
152 match solution { 149 match solution {
153 Solution::Unique(v) => { 150 Solution::Unique(v) => {
154 canonicalized.apply_solution(self, v.0); 151 canonicalized.apply_solution(
152 self,
153 Canonical {
154 binders: v.binders,
155 // FIXME handle constraints
156 value: v.value.subst,
157 },
158 );
155 } 159 }
156 _ => return None, 160 _ => return None,
157 }; 161 };
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 3f3187ea2..9841988c5 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -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 method_resolution, op, 20 method_resolution, op,
21 primitive::{self, UintTy}, 21 primitive::{self, UintTy},
22 to_assoc_type_id, to_chalk_trait_id, 22 static_lifetime, to_chalk_trait_id,
23 traits::{chalk::from_chalk, FnTrait, InEnvironment}, 23 traits::{chalk::from_chalk, FnTrait},
24 utils::{generics, variant_data, Generics}, 24 utils::{generics, Generics},
25 AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, 25 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 Substitution, TraitRef, Ty, TyKind, 26 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27 TypeWalk,
27}; 28};
28 29
29use super::{ 30use super::{
@@ -73,38 +74,33 @@ impl<'a> InferenceContext<'a> {
73 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; 74 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
74 let output_assoc_type = 75 let output_assoc_type =
75 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; 76 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
76 let generic_params = generics(self.db.upcast(), fn_once_trait.into());
77 if generic_params.len() != 2 {
78 return None;
79 }
80 77
81 let mut param_builder = Substitution::builder(num_args);
82 let mut arg_tys = vec![]; 78 let mut arg_tys = vec![];
83 for _ in 0..num_args { 79 let arg_ty = TyBuilder::tuple(num_args)
84 let arg = self.table.new_type_var(); 80 .fill(repeat_with(|| {
85 param_builder = param_builder.push(arg.clone()); 81 let arg = self.table.new_type_var();
86 arg_tys.push(arg); 82 arg_tys.push(arg.clone());
87 } 83 arg
88 let parameters = param_builder.build(); 84 }))
89 let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); 85 .build();
90 let substs = 86
91 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 87 let projection = {
88 let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type);
89 if b.remaining() != 2 {
90 return None;
91 }
92 b.push(ty.clone()).push(arg_ty).build()
93 };
92 94
93 let trait_env = self.trait_env.env.clone(); 95 let trait_env = self.trait_env.env.clone();
94 let implements_fn_trait: DomainGoal = 96 let obligation = InEnvironment {
95 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } 97 goal: projection.trait_ref(self.db).cast(&Interner),
96 .cast(&Interner);
97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
98 goal: implements_fn_trait.clone(),
99 environment: trait_env, 98 environment: trait_env,
100 }); 99 };
101 if self.db.trait_solve(krate, goal.value).is_some() { 100 let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone());
102 self.obligations.push(implements_fn_trait); 101 if self.db.trait_solve(krate, canonical.value).is_some() {
103 let output_proj_ty = crate::ProjectionTy { 102 self.push_obligation(obligation.goal);
104 associated_ty_id: to_assoc_type_id(output_assoc_type), 103 let return_ty = self.normalize_projection_ty(projection);
105 substitution: substs,
106 };
107 let return_ty = self.normalize_projection_ty(output_proj_ty);
108 Some((arg_tys, return_ty)) 104 Some((arg_tys, return_ty))
109 } else { 105 } else {
110 None 106 None
@@ -119,6 +115,8 @@ impl<'a> InferenceContext<'a> {
119 } 115 }
120 116
121 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty { 117 fn infer_expr_inner(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
118 self.db.check_canceled();
119
122 let body = Arc::clone(&self.body); // avoid borrow checker problem 120 let body = Arc::clone(&self.body); // avoid borrow checker problem
123 let ty = match &body[tgt_expr] { 121 let ty = match &body[tgt_expr] {
124 Expr::Missing => self.err_ty(), 122 Expr::Missing => self.err_ty(),
@@ -136,7 +134,7 @@ impl<'a> InferenceContext<'a> {
136 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); 134 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
137 let else_ty = match else_branch { 135 let else_ty = match else_branch {
138 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 136 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
139 None => Ty::unit(), 137 None => TyBuilder::unit(),
140 }; 138 };
141 both_arms_diverge &= self.diverges; 139 both_arms_diverge &= self.diverges;
142 140
@@ -183,7 +181,8 @@ impl<'a> InferenceContext<'a> {
183 let inner_ty = self.infer_expr(*body, &Expectation::none()); 181 let inner_ty = self.infer_expr(*body, &Expectation::none());
184 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body); 182 let impl_trait_id = crate::ImplTraitId::AsyncBlockTypeImplTrait(self.owner, *body);
185 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();
186 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)
187 } 186 }
188 Expr::Loop { body, label } => { 187 Expr::Loop { body, label } => {
189 self.breakables.push(BreakableContext { 188 self.breakables.push(BreakableContext {
@@ -191,7 +190,7 @@ impl<'a> InferenceContext<'a> {
191 break_ty: self.table.new_type_var(), 190 break_ty: self.table.new_type_var(),
192 label: label.map(|label| self.body[label].name.clone()), 191 label: label.map(|label| self.body[label].name.clone()),
193 }); 192 });
194 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 193 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
195 194
196 let ctxt = self.breakables.pop().expect("breakable stack broken"); 195 let ctxt = self.breakables.pop().expect("breakable stack broken");
197 if ctxt.may_break { 196 if ctxt.may_break {
@@ -215,11 +214,11 @@ impl<'a> InferenceContext<'a> {
215 *condition, 214 *condition,
216 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), 215 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
217 ); 216 );
218 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 217 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
219 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 218 let _ctxt = self.breakables.pop().expect("breakable stack broken");
220 // the body may not run, so it diverging doesn't mean we diverge 219 // the body may not run, so it diverging doesn't mean we diverge
221 self.diverges = Diverges::Maybe; 220 self.diverges = Diverges::Maybe;
222 Ty::unit() 221 TyBuilder::unit()
223 } 222 }
224 Expr::For { iterable, body, pat, label } => { 223 Expr::For { iterable, body, pat, label } => {
225 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 224 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
@@ -234,11 +233,11 @@ impl<'a> InferenceContext<'a> {
234 233
235 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 234 self.infer_pat(*pat, &pat_ty, BindingMode::default());
236 235
237 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 236 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
238 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 237 let _ctxt = self.breakables.pop().expect("breakable stack broken");
239 // the body may not run, so it diverging doesn't mean we diverge 238 // the body may not run, so it diverging doesn't mean we diverge
240 self.diverges = Diverges::Maybe; 239 self.diverges = Diverges::Maybe;
241 Ty::unit() 240 TyBuilder::unit()
242 } 241 }
243 Expr::Lambda { body, args, ret_type, arg_types } => { 242 Expr::Lambda { body, args, ret_type, arg_types } => {
244 assert_eq!(args.len(), arg_types.len()); 243 assert_eq!(args.len(), arg_types.len());
@@ -262,14 +261,17 @@ impl<'a> InferenceContext<'a> {
262 }; 261 };
263 sig_tys.push(ret_ty.clone()); 262 sig_tys.push(ret_ty.clone());
264 let sig_ty = TyKind::Function(FnPointer { 263 let sig_ty = TyKind::Function(FnPointer {
265 num_args: sig_tys.len() - 1, 264 num_binders: 0,
266 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false }, 265 sig: FnSig { abi: (), safety: chalk_ir::Safety::Safe, variadic: false },
267 substs: Substitution(sig_tys.clone().into()), 266 substitution: FnSubst(
267 Substitution::from_iter(&Interner, sig_tys.clone()).shifted_in(&Interner),
268 ),
268 }) 269 })
269 .intern(&Interner); 270 .intern(&Interner);
270 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();
271 let closure_ty = 272 let closure_ty =
272 TyKind::Closure(closure_id, Substitution::single(sig_ty)).intern(&Interner); 273 TyKind::Closure(closure_id, Substitution::from1(&Interner, sig_ty))
274 .intern(&Interner);
273 275
274 // Eagerly try to relate the closure type with the expected 276 // Eagerly try to relate the closure type with the expected
275 // type, otherwise we often won't have enough information to 277 // type, otherwise we often won't have enough information to
@@ -316,7 +318,13 @@ impl<'a> InferenceContext<'a> {
316 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
317 } 319 }
318 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
319 .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 ),
320 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
321 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
322 330
@@ -358,7 +366,7 @@ impl<'a> InferenceContext<'a> {
358 let val_ty = if let Some(expr) = expr { 366 let val_ty = if let Some(expr) = expr {
359 self.infer_expr(*expr, &Expectation::none()) 367 self.infer_expr(*expr, &Expectation::none())
360 } else { 368 } else {
361 Ty::unit() 369 TyBuilder::unit()
362 }; 370 };
363 371
364 let last_ty = 372 let last_ty =
@@ -384,7 +392,7 @@ impl<'a> InferenceContext<'a> {
384 if let Some(expr) = expr { 392 if let Some(expr) = expr {
385 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); 393 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
386 } else { 394 } else {
387 let unit = Ty::unit(); 395 let unit = TyBuilder::unit();
388 self.coerce(&unit, &self.return_ty.clone()); 396 self.coerce(&unit, &self.return_ty.clone());
389 } 397 }
390 TyKind::Never.intern(&Interner) 398 TyKind::Never.intern(&Interner)
@@ -397,16 +405,19 @@ impl<'a> InferenceContext<'a> {
397 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
398 } 406 }
399 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
400 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
401 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
402 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
403 } 411 }
404 412
405 self.unify(&ty, &expected.ty); 413 self.unify(&ty, &expected.ty);
406 414
407 let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); 415 let substs = ty
416 .as_adt()
417 .map(|(_, s)| s.clone())
418 .unwrap_or_else(|| Substitution::empty(&Interner));
408 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();
409 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()));
410 for field in fields.iter() { 421 for field in fields.iter() {
411 let field_def = 422 let field_def =
412 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) {
@@ -418,11 +429,8 @@ impl<'a> InferenceContext<'a> {
418 None 429 None
419 } 430 }
420 }); 431 });
421 if let Some(field_def) = field_def {
422 self.result.record_field_resolutions.insert(field.expr, field_def);
423 }
424 let field_ty = field_def.map_or(self.err_ty(), |it| { 432 let field_ty = field_def.map_or(self.err_ty(), |it| {
425 field_types[it.local_id].clone().subst(&substs) 433 field_types[it.local_id].clone().substitute(&Interner, &substs)
426 }); 434 });
427 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty)); 435 self.infer_expr_coerce(field.expr, &Expectation::has_type(field_ty));
428 } 436 }
@@ -453,10 +461,10 @@ impl<'a> InferenceContext<'a> {
453 }) 461 })
454 .unwrap_or(true) 462 .unwrap_or(true)
455 }; 463 };
456 match canonicalized.decanonicalize_ty(derefed_ty.value).interned(&Interner) { 464 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
457 TyKind::Tuple(_, substs) => { 465 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
458 name.as_tuple_index().and_then(|idx| substs.0.get(idx).cloned()) 466 substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
459 } 467 }),
460 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 468 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
461 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 469 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
462 let field = FieldId { parent: (*s).into(), local_id }; 470 let field = FieldId { parent: (*s).into(), local_id };
@@ -465,7 +473,7 @@ impl<'a> InferenceContext<'a> {
465 Some( 473 Some(
466 self.db.field_types((*s).into())[field.local_id] 474 self.db.field_types((*s).into())[field.local_id]
467 .clone() 475 .clone()
468 .subst(&parameters), 476 .substitute(&Interner, &parameters),
469 ) 477 )
470 } else { 478 } else {
471 None 479 None
@@ -479,7 +487,7 @@ impl<'a> InferenceContext<'a> {
479 Some( 487 Some(
480 self.db.field_types((*u).into())[field.local_id] 488 self.db.field_types((*u).into())[field.local_id]
481 .clone() 489 .clone()
482 .subst(&parameters), 490 .substitute(&Interner, &parameters),
483 ) 491 )
484 } else { 492 } else {
485 None 493 None
@@ -526,24 +534,17 @@ impl<'a> InferenceContext<'a> {
526 let inner_ty = self.infer_expr_inner(*expr, &expectation); 534 let inner_ty = self.infer_expr_inner(*expr, &expectation);
527 match rawness { 535 match rawness {
528 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty), 536 Rawness::RawPtr => TyKind::Raw(mutability, inner_ty),
529 Rawness::Ref => TyKind::Ref(mutability, inner_ty), 537 Rawness::Ref => TyKind::Ref(mutability, static_lifetime(), inner_ty),
530 } 538 }
531 .intern(&Interner) 539 .intern(&Interner)
532 } 540 }
533 Expr::Box { expr } => { 541 Expr::Box { expr } => {
534 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 542 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
535 if let Some(box_) = self.resolve_boxed_box() { 543 if let Some(box_) = self.resolve_boxed_box() {
536 let mut sb = 544 TyBuilder::adt(self.db, box_)
537 Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); 545 .push(inner_ty)
538 sb = sb.push(inner_ty); 546 .fill_with_defaults(self.db, || self.table.new_type_var())
539 match self.db.generic_defaults(box_.into()).get(1) { 547 .build()
540 Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
541 sb = sb.push(alloc_ty.value.clone());
542 }
543 _ => (),
544 }
545 sb = sb.fill(repeat_with(|| self.table.new_type_var()));
546 Ty::adt_ty(box_, sb.build())
547 } else { 548 } else {
548 self.err_ty() 549 self.err_ty()
549 } 550 }
@@ -571,7 +572,7 @@ impl<'a> InferenceContext<'a> {
571 None => self.err_ty(), 572 None => self.err_ty(),
572 }, 573 },
573 UnaryOp::Neg => { 574 UnaryOp::Neg => {
574 match inner_ty.interned(&Interner) { 575 match inner_ty.kind(&Interner) {
575 // Fast path for builtins 576 // Fast path for builtins
576 TyKind::Scalar(Scalar::Int(_)) 577 TyKind::Scalar(Scalar::Int(_))
577 | TyKind::Scalar(Scalar::Uint(_)) 578 | TyKind::Scalar(Scalar::Uint(_))
@@ -584,7 +585,7 @@ impl<'a> InferenceContext<'a> {
584 } 585 }
585 } 586 }
586 UnaryOp::Not => { 587 UnaryOp::Not => {
587 match inner_ty.interned(&Interner) { 588 match inner_ty.kind(&Interner) {
588 // Fast path for builtins 589 // Fast path for builtins
589 TyKind::Scalar(Scalar::Bool) 590 TyKind::Scalar(Scalar::Bool)
590 | TyKind::Scalar(Scalar::Int(_)) 591 | TyKind::Scalar(Scalar::Int(_))
@@ -633,31 +634,31 @@ impl<'a> InferenceContext<'a> {
633 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); 634 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
634 match (range_type, lhs_ty, rhs_ty) { 635 match (range_type, lhs_ty, rhs_ty) {
635 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { 636 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
636 Some(adt) => Ty::adt_ty(adt, Substitution::empty()), 637 Some(adt) => TyBuilder::adt(self.db, adt).build(),
637 None => self.err_ty(), 638 None => self.err_ty(),
638 }, 639 },
639 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { 640 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
640 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 641 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
641 None => self.err_ty(), 642 None => self.err_ty(),
642 }, 643 },
643 (RangeOp::Inclusive, None, Some(ty)) => { 644 (RangeOp::Inclusive, None, Some(ty)) => {
644 match self.resolve_range_to_inclusive() { 645 match self.resolve_range_to_inclusive() {
645 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 646 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
646 None => self.err_ty(), 647 None => self.err_ty(),
647 } 648 }
648 } 649 }
649 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { 650 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
650 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 651 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
651 None => self.err_ty(), 652 None => self.err_ty(),
652 }, 653 },
653 (RangeOp::Inclusive, Some(_), Some(ty)) => { 654 (RangeOp::Inclusive, Some(_), Some(ty)) => {
654 match self.resolve_range_inclusive() { 655 match self.resolve_range_inclusive() {
655 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 656 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
656 None => self.err_ty(), 657 None => self.err_ty(),
657 } 658 }
658 } 659 }
659 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { 660 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
660 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 661 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
661 None => self.err_ty(), 662 None => self.err_ty(),
662 }, 663 },
663 (RangeOp::Inclusive, _, None) => self.err_ty(), 664 (RangeOp::Inclusive, _, None) => self.err_ty(),
@@ -690,10 +691,10 @@ impl<'a> InferenceContext<'a> {
690 } 691 }
691 } 692 }
692 Expr::Tuple { exprs } => { 693 Expr::Tuple { exprs } => {
693 let mut tys = match expected.ty.interned(&Interner) { 694 let mut tys = match expected.ty.kind(&Interner) {
694 TyKind::Tuple(_, substs) => substs 695 TyKind::Tuple(_, substs) => substs
695 .iter() 696 .iter(&Interner)
696 .cloned() 697 .map(|a| a.assert_ty_ref(&Interner).clone())
697 .chain(repeat_with(|| self.table.new_type_var())) 698 .chain(repeat_with(|| self.table.new_type_var()))
698 .take(exprs.len()) 699 .take(exprs.len())
699 .collect::<Vec<_>>(), 700 .collect::<Vec<_>>(),
@@ -704,11 +705,11 @@ impl<'a> InferenceContext<'a> {
704 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone())); 705 self.infer_expr_coerce(*expr, &Expectation::has_type(ty.clone()));
705 } 706 }
706 707
707 TyKind::Tuple(tys.len(), Substitution(tys.into())).intern(&Interner) 708 TyKind::Tuple(tys.len(), Substitution::from_iter(&Interner, tys)).intern(&Interner)
708 } 709 }
709 Expr::Array(array) => { 710 Expr::Array(array) => {
710 let elem_ty = match expected.ty.interned(&Interner) { 711 let elem_ty = match expected.ty.kind(&Interner) {
711 TyKind::Array(st) | TyKind::Slice(st) => st.clone(), 712 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
712 _ => self.table.new_type_var(), 713 _ => self.table.new_type_var(),
713 }; 714 };
714 715
@@ -732,17 +733,19 @@ impl<'a> InferenceContext<'a> {
732 } 733 }
733 } 734 }
734 735
735 TyKind::Array(elem_ty).intern(&Interner) 736 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
736 } 737 }
737 Expr::Literal(lit) => match lit { 738 Expr::Literal(lit) => match lit {
738 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 739 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
739 Literal::String(..) => { 740 Literal::String(..) => {
740 TyKind::Ref(Mutability::Not, TyKind::Str.intern(&Interner)).intern(&Interner) 741 TyKind::Ref(Mutability::Not, static_lifetime(), TyKind::Str.intern(&Interner))
742 .intern(&Interner)
741 } 743 }
742 Literal::ByteString(..) => { 744 Literal::ByteString(..) => {
743 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 745 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
744 let array_type = TyKind::Array(byte_type).intern(&Interner); 746 let array_type =
745 TyKind::Ref(Mutability::Not, array_type).intern(&Interner) 747 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
748 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
746 } 749 }
747 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 750 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
748 Literal::Int(_v, ty) => match ty { 751 Literal::Int(_v, ty) => match ty {
@@ -767,6 +770,7 @@ impl<'a> InferenceContext<'a> {
767 None => self.table.new_float_var(), 770 None => self.table.new_float_var(),
768 }, 771 },
769 }, 772 },
773 Expr::MacroStmts { tail } => self.infer_expr(*tail, expected),
770 }; 774 };
771 // use a new type variable if we got unknown here 775 // use a new type variable if we got unknown here
772 let ty = self.insert_type_vars_shallow(ty); 776 let ty = self.insert_type_vars_shallow(ty);
@@ -821,8 +825,8 @@ impl<'a> InferenceContext<'a> {
821 // we don't even make an attempt at coercion 825 // we don't even make an attempt at coercion
822 self.table.new_maybe_never_var() 826 self.table.new_maybe_never_var()
823 } else { 827 } else {
824 self.coerce(&Ty::unit(), &expected.coercion_target()); 828 self.coerce(&TyBuilder::unit(), &expected.coercion_target());
825 Ty::unit() 829 TyBuilder::unit()
826 } 830 }
827 }; 831 };
828 ty 832 ty
@@ -858,10 +862,10 @@ impl<'a> InferenceContext<'a> {
858 self.write_method_resolution(tgt_expr, func); 862 self.write_method_resolution(tgt_expr, func);
859 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into()))) 863 (ty, self.db.value_ty(func.into()), Some(generics(self.db.upcast(), func.into())))
860 } 864 }
861 None => (receiver_ty, Binders::new(0, self.err_ty()), None), 865 None => (receiver_ty, Binders::empty(&Interner, self.err_ty()), None),
862 }; 866 };
863 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty); 867 let substs = self.substs_for_method_call(def_generics, generic_args, &derefed_receiver_ty);
864 let method_ty = method_ty.subst(&substs); 868 let method_ty = method_ty.substitute(&Interner, &substs);
865 let method_ty = self.insert_type_vars(method_ty); 869 let method_ty = self.insert_type_vars(method_ty);
866 self.register_obligations_for_call(&method_ty); 870 self.register_obligations_for_call(&method_ty);
867 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) { 871 let (expected_receiver_ty, param_tys, ret_ty) = match method_ty.callable_sig(self.db) {
@@ -877,7 +881,9 @@ impl<'a> InferenceContext<'a> {
877 // Apply autoref so the below unification works correctly 881 // Apply autoref so the below unification works correctly
878 // FIXME: return correct autorefs from lookup_method 882 // FIXME: return correct autorefs from lookup_method
879 let actual_receiver_ty = match expected_receiver_ty.as_reference() { 883 let actual_receiver_ty = match expected_receiver_ty.as_reference() {
880 Some((_, mutability)) => TyKind::Ref(mutability, derefed_receiver_ty).intern(&Interner), 884 Some((_, lifetime, mutability)) => {
885 TyKind::Ref(mutability, lifetime, derefed_receiver_ty).intern(&Interner)
886 }
881 _ => derefed_receiver_ty, 887 _ => derefed_receiver_ty,
882 }; 888 };
883 self.unify(&expected_receiver_ty, &actual_receiver_ty); 889 self.unify(&expected_receiver_ty, &actual_receiver_ty);
@@ -950,18 +956,20 @@ impl<'a> InferenceContext<'a> {
950 substs.push(self.err_ty()); 956 substs.push(self.err_ty());
951 } 957 }
952 assert_eq!(substs.len(), total_len); 958 assert_eq!(substs.len(), total_len);
953 Substitution(substs.into()) 959 Substitution::from_iter(&Interner, substs)
954 } 960 }
955 961
956 fn register_obligations_for_call(&mut self, callable_ty: &Ty) { 962 fn register_obligations_for_call(&mut self, callable_ty: &Ty) {
957 if let TyKind::FnDef(fn_def, parameters) = callable_ty.interned(&Interner) { 963 if let TyKind::FnDef(fn_def, parameters) = callable_ty.kind(&Interner) {
958 let def: CallableDefId = from_chalk(self.db, *fn_def); 964 let def: CallableDefId = from_chalk(self.db, *fn_def);
959 let generic_predicates = self.db.generic_predicates(def.into()); 965 let generic_predicates = self.db.generic_predicates(def.into());
960 for predicate in generic_predicates.iter() { 966 for predicate in generic_predicates.iter() {
961 let (predicate, binders) = 967 let (predicate, binders) = predicate
962 predicate.clone().subst(parameters).into_value_and_skipped_binders(); 968 .clone()
963 always!(binders == 0); // quantified where clauses not yet handled 969 .substitute(&Interner, parameters)
964 self.obligations.push(predicate.cast(&Interner)); 970 .into_value_and_skipped_binders();
971 always!(binders.len(&Interner) == 0); // quantified where clauses not yet handled
972 self.push_obligation(predicate.cast(&Interner));
965 } 973 }
966 // add obligation for trait implementation, if this is a trait method 974 // add obligation for trait implementation, if this is a trait method
967 match def { 975 match def {
@@ -969,9 +977,11 @@ impl<'a> InferenceContext<'a> {
969 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container 977 if let AssocContainerId::TraitId(trait_) = f.lookup(self.db.upcast()).container
970 { 978 {
971 // construct a TraitRef 979 // construct a TraitRef
972 let substs = 980 let substs = crate::subst_prefix(
973 parameters.prefix(generics(self.db.upcast(), trait_.into()).len()); 981 &*parameters,
974 self.obligations.push( 982 generics(self.db.upcast(), trait_.into()).len(),
983 );
984 self.push_obligation(
975 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs } 985 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }
976 .cast(&Interner), 986 .cast(&Interner),
977 ); 987 );
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 474363709..a41e8e116 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -7,15 +7,13 @@ use chalk_ir::Mutability;
7use hir_def::{ 7use hir_def::{
8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat}, 8 expr::{BindingAnnotation, Expr, Literal, Pat, PatId, RecordFieldPat},
9 path::Path, 9 path::Path,
10 FieldId,
11}; 10};
12use hir_expand::name::Name; 11use hir_expand::name::Name;
13 12
14use super::{BindingMode, Expectation, InferenceContext}; 13use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 14use crate::{
16 lower::lower_to_chalk_mutability, 15 lower::lower_to_chalk_mutability, static_lifetime, Interner, Substitution, Ty, TyBuilder,
17 utils::{generics, variant_data}, 16 TyExt, TyKind,
18 Interner, Substitution, Ty, TyKind,
19}; 17};
20 18
21impl<'a> InferenceContext<'a> { 19impl<'a> InferenceContext<'a> {
@@ -29,13 +27,14 @@ impl<'a> InferenceContext<'a> {
29 ellipsis: Option<usize>, 27 ellipsis: Option<usize>,
30 ) -> Ty { 28 ) -> Ty {
31 let (ty, def) = self.resolve_variant(path); 29 let (ty, def) = self.resolve_variant(path);
32 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 30 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
33 if let Some(variant) = def { 31 if let Some(variant) = def {
34 self.write_variant_resolution(id.into(), variant); 32 self.write_variant_resolution(id.into(), variant);
35 } 33 }
36 self.unify(&ty, expected); 34 self.unify(&ty, expected);
37 35
38 let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); 36 let substs =
37 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
39 38
40 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 39 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
41 let (pre, post) = match ellipsis { 40 let (pre, post) = match ellipsis {
@@ -50,7 +49,9 @@ impl<'a> InferenceContext<'a> {
50 let expected_ty = var_data 49 let expected_ty = var_data
51 .as_ref() 50 .as_ref()
52 .and_then(|d| d.field(&Name::new_tuple_field(i))) 51 .and_then(|d| d.field(&Name::new_tuple_field(i)))
53 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs)); 52 .map_or(self.err_ty(), |field| {
53 field_tys[field].clone().substitute(&Interner, &substs)
54 });
54 let expected_ty = self.normalize_associated_types_in(expected_ty); 55 let expected_ty = self.normalize_associated_types_in(expected_ty);
55 self.infer_pat(subpat, &expected_ty, default_bm); 56 self.infer_pat(subpat, &expected_ty, default_bm);
56 } 57 }
@@ -67,25 +68,22 @@ impl<'a> InferenceContext<'a> {
67 id: PatId, 68 id: PatId,
68 ) -> Ty { 69 ) -> Ty {
69 let (ty, def) = self.resolve_variant(path); 70 let (ty, def) = self.resolve_variant(path);
70 let var_data = def.map(|it| variant_data(self.db.upcast(), it)); 71 let var_data = def.map(|it| it.variant_data(self.db.upcast()));
71 if let Some(variant) = def { 72 if let Some(variant) = def {
72 self.write_variant_resolution(id.into(), variant); 73 self.write_variant_resolution(id.into(), variant);
73 } 74 }
74 75
75 self.unify(&ty, expected); 76 self.unify(&ty, expected);
76 77
77 let substs = ty.substs().cloned().unwrap_or_else(Substitution::empty); 78 let substs =
79 ty.as_adt().map(|(_, s)| s.clone()).unwrap_or_else(|| Substitution::empty(&Interner));
78 80
79 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default(); 81 let field_tys = def.map(|it| self.db.field_types(it)).unwrap_or_default();
80 for subpat in subpats { 82 for subpat in subpats {
81 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name)); 83 let matching_field = var_data.as_ref().and_then(|it| it.field(&subpat.name));
82 if let Some(local_id) = matching_field { 84 let expected_ty = matching_field.map_or(self.err_ty(), |field| {
83 let field_def = FieldId { parent: def.unwrap(), local_id }; 85 field_tys[field].clone().substitute(&Interner, &substs)
84 self.result.record_pat_field_resolutions.insert(subpat.pat, field_def); 86 });
85 }
86
87 let expected_ty = matching_field
88 .map_or(self.err_ty(), |field| field_tys[field].clone().subst(&substs));
89 let expected_ty = self.normalize_associated_types_in(expected_ty); 87 let expected_ty = self.normalize_associated_types_in(expected_ty);
90 self.infer_pat(subpat.pat, &expected_ty, default_bm); 88 self.infer_pat(subpat.pat, &expected_ty, default_bm);
91 } 89 }
@@ -102,7 +100,7 @@ impl<'a> InferenceContext<'a> {
102 let body = Arc::clone(&self.body); // avoid borrow checker problem 100 let body = Arc::clone(&self.body); // avoid borrow checker problem
103 101
104 if is_non_ref_pat(&body, pat) { 102 if is_non_ref_pat(&body, pat) {
105 while let Some((inner, mutability)) = expected.as_reference() { 103 while let Some((inner, _lifetime, mutability)) = expected.as_reference() {
106 expected = inner; 104 expected = inner;
107 default_bm = match default_bm { 105 default_bm = match default_bm {
108 BindingMode::Move => BindingMode::Ref(mutability), 106 BindingMode::Move => BindingMode::Ref(mutability),
@@ -124,7 +122,7 @@ impl<'a> InferenceContext<'a> {
124 let ty = match &body[pat] { 122 let ty = match &body[pat] {
125 &Pat::Tuple { ref args, ellipsis } => { 123 &Pat::Tuple { ref args, ellipsis } => {
126 let expectations = match expected.as_tuple() { 124 let expectations = match expected.as_tuple() {
127 Some(parameters) => &*parameters.0, 125 Some(parameters) => &*parameters.interned().as_slice(),
128 _ => &[], 126 _ => &[],
129 }; 127 };
130 128
@@ -134,7 +132,8 @@ impl<'a> InferenceContext<'a> {
134 }; 132 };
135 let n_uncovered_patterns = expectations.len().saturating_sub(args.len()); 133 let n_uncovered_patterns = expectations.len().saturating_sub(args.len());
136 let err_ty = self.err_ty(); 134 let err_ty = self.err_ty();
137 let mut expectations_iter = expectations.iter().chain(repeat(&err_ty)); 135 let mut expectations_iter =
136 expectations.iter().map(|a| a.assert_ty_ref(&Interner)).chain(repeat(&err_ty));
138 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm); 137 let mut infer_pat = |(&pat, ty)| self.infer_pat(pat, ty, default_bm);
139 138
140 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len()); 139 let mut inner_tys = Vec::with_capacity(n_uncovered_patterns + args.len());
@@ -142,7 +141,8 @@ impl<'a> InferenceContext<'a> {
142 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned()); 141 inner_tys.extend(expectations_iter.by_ref().take(n_uncovered_patterns).cloned());
143 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat)); 142 inner_tys.extend(post.iter().zip(expectations_iter).map(infer_pat));
144 143
145 TyKind::Tuple(inner_tys.len(), Substitution(inner_tys.into())).intern(&Interner) 144 TyKind::Tuple(inner_tys.len(), Substitution::from_iter(&Interner, inner_tys))
145 .intern(&Interner)
146 } 146 }
147 Pat::Or(ref pats) => { 147 Pat::Or(ref pats) => {
148 if let Some((first_pat, rest)) = pats.split_first() { 148 if let Some((first_pat, rest)) = pats.split_first() {
@@ -158,7 +158,7 @@ impl<'a> InferenceContext<'a> {
158 Pat::Ref { pat, mutability } => { 158 Pat::Ref { pat, mutability } => {
159 let mutability = lower_to_chalk_mutability(*mutability); 159 let mutability = lower_to_chalk_mutability(*mutability);
160 let expectation = match expected.as_reference() { 160 let expectation = match expected.as_reference() {
161 Some((inner_ty, exp_mut)) => { 161 Some((inner_ty, _lifetime, exp_mut)) => {
162 if mutability != exp_mut { 162 if mutability != exp_mut {
163 // FIXME: emit type error? 163 // FIXME: emit type error?
164 } 164 }
@@ -167,10 +167,10 @@ impl<'a> InferenceContext<'a> {
167 _ => self.result.standard_types.unknown.clone(), 167 _ => self.result.standard_types.unknown.clone(),
168 }; 168 };
169 let subty = self.infer_pat(*pat, &expectation, default_bm); 169 let subty = self.infer_pat(*pat, &expectation, default_bm);
170 TyKind::Ref(mutability, subty).intern(&Interner) 170 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
171 } 171 }
172 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 172 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
173 p.as_ref(), 173 p.as_deref(),
174 subpats, 174 subpats,
175 expected, 175 expected,
176 default_bm, 176 default_bm,
@@ -178,7 +178,7 @@ impl<'a> InferenceContext<'a> {
178 *ellipsis, 178 *ellipsis,
179 ), 179 ),
180 Pat::Record { path: p, args: fields, ellipsis: _ } => { 180