diff options
Diffstat (limited to 'crates/hir_ty/src')
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; | |||
12 | use log::{info, warn}; | 12 | use log::{info, warn}; |
13 | 13 | ||
14 | use crate::{ | 14 | use 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 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 19 | const 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 | ||
45 | fn 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 | |||
49 | fn deref_by_trait( | 53 | fn 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 | |||
3 | use std::iter; | ||
4 | |||
5 | use chalk_ir::{ | ||
6 | cast::{Cast, CastTo, Caster}, | ||
7 | interner::HasInterner, | ||
8 | AdtId, BoundVar, DebruijnIndex, Safety, Scalar, | ||
9 | }; | ||
10 | use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId}; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use 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`. | ||
20 | pub 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 | |||
28 | impl<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 | |||
74 | impl 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 | |||
126 | impl 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 | |||
158 | pub struct Tuple(usize); | ||
159 | impl 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 | |||
170 | impl 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 | |||
183 | impl 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 | |||
199 | impl<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 | |||
211 | impl 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 | ||
8 | use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; | 8 | use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause}; |
9 | 9 | ||
10 | macro_rules! has_interner { | 10 | macro_rules! has_interner { |
11 | ($t:ty) => { | 11 | ($t:ty) => { |
@@ -17,6 +17,8 @@ macro_rules! has_interner { | |||
17 | 17 | ||
18 | has_interner!(WhereClause); | 18 | has_interner!(WhereClause); |
19 | has_interner!(DomainGoal); | 19 | has_interner!(DomainGoal); |
20 | has_interner!(GenericArg); | ||
21 | has_interner!(Ty); | ||
20 | 22 | ||
21 | impl CastTo<WhereClause> for TraitRef { | 23 | impl 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 | ||
41 | impl CastTo<GenericArg> for Ty { | ||
42 | fn cast_to(self, interner: &Interner) -> GenericArg { | ||
43 | GenericArg::new(interner, GenericArgData::Ty(self)) | ||
44 | } | ||
45 | } | ||
46 | |||
39 | macro_rules! transitive_impl { | 47 | macro_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 | ||
52 | transitive_impl!(TraitRef, WhereClause, DomainGoal); | 60 | transitive_impl!(TraitRef, WhereClause, DomainGoal); |
53 | transitive_impl!(AliasEq, WhereClause, DomainGoal); | 61 | transitive_impl!(AliasEq, WhereClause, DomainGoal); |
62 | |||
63 | macro_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 | |||
73 | reflexive_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 | |||
3 | use chalk_ir::Mutability; | ||
4 | use hir_def::{ | ||
5 | type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId, | ||
6 | }; | ||
7 | |||
8 | use 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 | |||
15 | pub 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 | |||
42 | impl 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, ¶meters)) | ||
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 | |||
276 | pub trait ProjectionTyExt { | ||
277 | fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef; | ||
278 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId; | ||
279 | } | ||
280 | |||
281 | impl 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 | |||
297 | pub trait TraitRefExt { | ||
298 | fn hir_trait_id(&self) -> TraitId; | ||
299 | } | ||
300 | |||
301 | impl 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; | |||
5 | use base_db::{impl_intern_key, salsa, CrateId, Upcast}; | 5 | use base_db::{impl_intern_key, salsa, CrateId, Upcast}; |
6 | use hir_def::{ | 6 | use 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 | }; |
10 | use la_arena::ArenaMap; | 10 | use 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); | |||
156 | impl_intern_key!(InternedTypeParamId); | 160 | impl_intern_key!(InternedTypeParamId); |
157 | 161 | ||
158 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 162 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
163 | pub struct InternedLifetimeParamId(salsa::InternId); | ||
164 | impl_intern_key!(InternedLifetimeParamId); | ||
165 | |||
166 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
167 | pub struct InternedConstParamId(salsa::InternId); | ||
168 | impl_intern_key!(InternedConstParamId); | ||
169 | |||
170 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
159 | pub struct InternedOpaqueTyId(salsa::InternId); | 171 | pub struct InternedOpaqueTyId(salsa::InternId); |
160 | impl_intern_key!(InternedOpaqueTyId); | 172 | impl_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 | ||
21 | pub(crate) use hir_def::{ | 20 | pub(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::{ | |||
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; | 230 | use 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#" | ||
1094 | enum Either {A, B} | ||
1095 | |||
1096 | fn 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#" | ||
1342 | pub enum Category { Infinity, Zero } | ||
1343 | |||
1344 | fn 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 | }; |
12 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
13 | 13 | ||
14 | use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; | 14 | use crate::{ |
15 | db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind, | ||
16 | }; | ||
15 | 17 | ||
16 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { | 18 | pub(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 | ||
3 | use std::{array, fmt}; | 3 | use std::{ |
4 | array, | ||
5 | fmt::{self, Debug}, | ||
6 | }; | ||
4 | 7 | ||
5 | use chalk_ir::Mutability; | 8 | use chalk_ir::BoundVar; |
6 | use hir_def::{ | 9 | use 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::{ | |||
16 | use hir_expand::name::Name; | 19 | use hir_expand::name::Name; |
17 | 20 | ||
18 | use crate::{ | 21 | use 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 | ||
25 | pub struct HirFormatter<'a> { | 30 | pub 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 | |||
286 | impl 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 | |||
294 | impl 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 | |||
311 | impl 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(¶meters.0[..total_len], ", ")?; | 445 | f.write_joined(¶meters.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(¶meters.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 | ¶meters.0[0..default_from] | 516 | ¶meters.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(¶meters); | 568 | let bounds = data.substitute(&Interner, ¶meters); |
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 | ||
764 | impl TraitRef { | 795 | fn 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 | ||
786 | impl HirDisplay for TraitRef { | 815 | impl 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 | ||
845 | impl 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 | |||
816 | impl HirDisplay for Lifetime { | 853 | impl 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 | |||
859 | impl 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, "{}", ¶m_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 | ||
1019 | impl HirDisplay for GenericArg { | 1068 | impl 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; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use 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 | }; |
43 | use crate::{ | 43 | use 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)] | ||
52 | pub use unify::could_unify; | ||
48 | pub(crate) use unify::unify; | 53 | pub(crate) use unify::unify; |
49 | 54 | ||
50 | mod unify; | 55 | mod unify; |
@@ -115,7 +120,7 @@ struct InternedStandardTypes { | |||
115 | 120 | ||
116 | impl Default for InternedStandardTypes { | 121 | impl 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)] | ||
684 | pub struct InferenceVar { | ||
685 | index: u32, | ||
686 | } | ||
687 | |||
688 | impl 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 @@ | |||
7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{ | 10 | use 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 | ||
14 | use super::{InEnvironment, InferenceContext}; | 12 | use 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; | |||
15 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
16 | 16 | ||
17 | use crate::{ | 17 | use 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 | ||
29 | use super::{ | 30 | use 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(¶meters), | 476 | .substitute(&Interner, ¶meters), |
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(¶meters), | 490 | .substitute(&Interner, ¶meters), |
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; | |||
7 | use hir_def::{ | 7 | use 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 | }; |
12 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
13 | 12 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 13 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 14 | use 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 | ||
21 | impl<'a> InferenceContext<'a> { | 19 | impl<'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 |