aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty')
-rw-r--r--crates/hir_ty/src/autoderef.rs40
-rw-r--r--crates/hir_ty/src/builder.rs219
-rw-r--r--crates/hir_ty/src/chalk_ext.rs13
-rw-r--r--crates/hir_ty/src/db.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs5
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs4
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs6
-rw-r--r--crates/hir_ty/src/display.rs28
-rw-r--r--crates/hir_ty/src/infer.rs17
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs110
-rw-r--r--crates/hir_ty/src/infer/pat.rs30
-rw-r--r--crates/hir_ty/src/infer/path.rs27
-rw-r--r--crates/hir_ty/src/infer/unify.rs15
-rw-r--r--crates/hir_ty/src/lib.rs843
-rw-r--r--crates/hir_ty/src/lower.rs51
-rw-r--r--crates/hir_ty/src/method_resolution.rs18
-rw-r--r--crates/hir_ty/src/op.rs4
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/traits.rs88
-rw-r--r--crates/hir_ty/src/traits/chalk.rs14
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs18
-rw-r--r--crates/hir_ty/src/types.rs416
-rw-r--r--crates/hir_ty/src/utils.rs36
-rw-r--r--crates/hir_ty/src/walk.rs381
25 files changed, 1257 insertions, 1159 deletions
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index c859f9491..7ca4af80e 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,12 +12,8 @@ use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
16 to_assoc_type_id, to_chalk_trait_id, 16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind,
17 traits::{InEnvironment, Solution},
18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 17};
22 18
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +53,20 @@ fn deref_by_trait(
57 }; 53 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 54 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 55
60 let generic_params = generics(db.upcast(), target.into()); 56 let projection = {
61 if generic_params.len() != 1 { 57 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 58 if b.remaining() != 1 {
63 // namely Deref's Self type 59 // the Target type + Deref trait should only have one generic parameter,
64 return None; 60 // namely Deref's Self type
65 } 61 return None;
62 }
63 b.push(ty.goal.value.clone()).build()
64 };
66 65
67 // FIXME make the Canonical / bound var handling nicer 66 // FIXME make the Canonical / bound var handling nicer
68 67
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 68 // Check that the type implements Deref at all
73 let trait_ref = 69 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 { 70 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 71 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 72 value: InEnvironment {
@@ -84,11 +79,8 @@ fn deref_by_trait(
84 } 79 }
85 80
86 // Now do the assoc type projection 81 // Now do the assoc type projection
87 let projection = AliasEq { 82 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 83 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 84 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 85 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 86 ty.goal.binders.len(&Interner),
@@ -96,9 +88,7 @@ fn deref_by_trait(
96 .intern(&Interner), 88 .intern(&Interner),
97 }; 89 };
98 90
99 let obligation = projection.cast(&Interner); 91 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 92
103 let canonical = Canonical { 93 let canonical = Canonical {
104 value: in_env, 94 value: in_env,
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
new file mode 100644
index 000000000..0bac31e4c
--- /dev/null
+++ b/crates/hir_ty/src/builder.rs
@@ -0,0 +1,219 @@
1//! `TyBuilder`, a helper for building instances of `Ty` and related types.
2
3use std::iter;
4
5use chalk_ir::{
6 cast::{Cast, CastTo, Caster},
7 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9};
10use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
11use smallvec::SmallVec;
12
13use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId,
17};
18
19/// This is a builder for `Ty` or anything that needs a `Substitution`.
20pub struct TyBuilder<D> {
21 /// The `data` field is used to keep track of what we're building (e.g. an
22 /// ADT, a `TraitRef`, ...).
23 data: D,
24 vec: SmallVec<[GenericArg; 2]>,
25 param_count: usize,
26}
27
28impl<D> TyBuilder<D> {
29 fn new(data: D, param_count: usize) -> TyBuilder<D> {
30 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
31 }
32
33 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
36 let subst = Substitution::intern(self.vec);
37 (self.data, subst)
38 }
39
40 pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self {
41 self.vec.push(arg.cast(&Interner));
42 self
43 }
44
45 pub fn remaining(&self) -> usize {
46 self.param_count - self.vec.len()
47 }
48
49 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
50 self.fill(
51 (starting_from..)
52 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
53 )
54 }
55
56 pub fn fill_with_unknown(self) -> Self {
57 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
58 }
59
60 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
61 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
62 assert_eq!(self.remaining(), 0);
63 self
64 }
65
66 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
67 assert!(self.vec.is_empty());
68 assert!(parent_substs.len(&Interner) <= self.param_count);
69 self.vec.extend(parent_substs.iter(&Interner).cloned());
70 self
71 }
72}
73
74impl TyBuilder<()> {
75 pub fn unit() -> Ty {
76 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
77 }
78
79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer {
81 num_args: sig.params().len(),
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()),
84 })
85 .intern(&Interner)
86 }
87
88 pub fn builtin(builtin: BuiltinType) -> Ty {
89 match builtin {
90 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
91 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
92 BuiltinType::Str => TyKind::Str.intern(&Interner),
93 BuiltinType::Int(t) => {
94 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
95 }
96 BuiltinType::Uint(t) => {
97 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
98 }
99 BuiltinType::Float(t) => {
100 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
101 }
102 }
103 }
104
105 pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
106 let params = generics(db.upcast(), def.into());
107 params.type_params_subst(db)
108 }
109
110 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
111 let def = def.into();
112 let params = generics(db.upcast(), def);
113 let param_count = params.len();
114 TyBuilder::new((), param_count)
115 }
116
117 pub fn build(self) -> Substitution {
118 let ((), subst) = self.build_internal();
119 subst
120 }
121}
122
123impl TyBuilder<hir_def::AdtId> {
124 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
125 let generics = generics(db.upcast(), adt.into());
126 let param_count = generics.len();
127 TyBuilder::new(adt, param_count)
128 }
129
130 pub fn fill_with_defaults(
131 mut self,
132 db: &dyn HirDatabase,
133 mut fallback: impl FnMut() -> Ty,
134 ) -> Self {
135 let defaults = db.generic_defaults(self.data.into());
136 for default_ty in defaults.iter().skip(self.vec.len()) {
137 if default_ty.skip_binders().is_unknown() {
138 self.vec.push(fallback().cast(&Interner));
139 } else {
140 // each default can depend on the previous parameters
141 let subst_so_far = Substitution::intern(self.vec.clone());
142 self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner));
143 }
144 }
145 self
146 }
147
148 pub fn build(self) -> Ty {
149 let (adt, subst) = self.build_internal();
150 TyKind::Adt(AdtId(adt), subst).intern(&Interner)
151 }
152}
153
154pub struct Tuple(usize);
155impl TyBuilder<Tuple> {
156 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
157 TyBuilder::new(Tuple(size), size)
158 }
159
160 pub fn build(self) -> Ty {
161 let (Tuple(size), subst) = self.build_internal();
162 TyKind::Tuple(size, subst).intern(&Interner)
163 }
164}
165
166impl TyBuilder<TraitId> {
167 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
168 let generics = generics(db.upcast(), trait_id.into());
169 let param_count = generics.len();
170 TyBuilder::new(trait_id, param_count)
171 }
172
173 pub fn build(self) -> TraitRef {
174 let (trait_id, substitution) = self.build_internal();
175 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
176 }
177}
178
179impl TyBuilder<TypeAliasId> {
180 pub fn assoc_type_projection(
181 db: &dyn HirDatabase,
182 type_alias: TypeAliasId,
183 ) -> TyBuilder<TypeAliasId> {
184 let generics = generics(db.upcast(), type_alias.into());
185 let param_count = generics.len();
186 TyBuilder::new(type_alias, param_count)
187 }
188
189 pub fn build(self) -> ProjectionTy {
190 let (type_alias, substitution) = self.build_internal();
191 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
192 }
193}
194
195impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
196 fn subst_binders(b: Binders<T>) -> Self {
197 let param_count = b.num_binders;
198 TyBuilder::new(b, param_count)
199 }
200
201 pub fn build(self) -> T {
202 let (b, subst) = self.build_internal();
203 b.subst(&subst)
204 }
205}
206
207impl TyBuilder<Binders<Ty>> {
208 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
209 TyBuilder::subst_binders(db.ty(def.into()))
210 }
211
212 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
213 TyBuilder::subst_binders(db.impl_self_ty(def))
214 }
215
216 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
217 TyBuilder::subst_binders(db.value_ty(def))
218 }
219}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
new file mode 100644
index 000000000..b7463366b
--- /dev/null
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -0,0 +1,13 @@
1//! Various extensions traits for Chalk types.
2
3use crate::{Interner, Ty, TyKind};
4
5pub trait TyExt {
6 fn is_unit(&self) -> bool;
7}
8
9impl TyExt for Ty {
10 fn is_unit(&self) -> bool {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 }
13}
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 58e4247c6..4300680d9 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -123,7 +123,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
123 &self, 123 &self,
124 krate: CrateId, 124 krate: CrateId,
125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, 125 goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>,
126 ) -> Option<crate::traits::Solution>; 126 ) -> Option<crate::Solution>;
127 127
128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] 128 #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)]
129 fn program_clauses_for_chalk_env( 129 fn program_clauses_for_chalk_env(
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 ad1259b34..8169b759f 100644
--- a/crates/hir_ty/src/diagnostics/expr.rs
+++ b/crates/hir_ty/src/diagnostics/expr.rs
@@ -15,7 +15,7 @@ use crate::{
15 MissingPatFields, RemoveThisSemicolon, 15 MissingPatFields, RemoveThisSemicolon,
16 }, 16 },
17 utils::variant_data, 17 utils::variant_data,
18 AdtId, InferenceResult, Interner, Ty, TyKind, 18 AdtId, InferenceResult, Interner, TyExt, TyKind,
19}; 19};
20 20
21pub(crate) use hir_def::{ 21pub(crate) use hir_def::{
@@ -423,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
423 None => return, 423 None => return,
424 }; 424 };
425 425
426 if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { 426 if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty {
427 return; 427 return;
428 } 428 }
429 429
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index a71eebc6f..b5efe9df5 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
32 let def = self.owner; 32 let def = self.owner;
33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); 33 let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
34 let is_unsafe = match self.owner { 34 let is_unsafe = match self.owner {
35 DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, 35 DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(),
36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, 36 DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
37 }; 37 };
38 if is_unsafe 38 if is_unsafe
@@ -86,7 +86,7 @@ fn walk_unsafe(
86 match expr { 86 match expr {
87 &Expr::Call { callee, .. } => { 87 &Expr::Call { callee, .. } => {
88 if let Some(func) = infer[callee].as_fn_def(db) { 88 if let Some(func) = infer[callee].as_fn_def(db) {
89 if db.function_data(func).qualifier.is_unsafe { 89 if db.function_data(func).is_unsafe() {
90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 90 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
91 } 91 }
92 } 92 }
@@ -103,7 +103,7 @@ fn walk_unsafe(
103 Expr::MethodCall { .. } => { 103 Expr::MethodCall { .. } => {
104 if infer 104 if infer
105 .method_resolution(current) 105 .method_resolution(current)
106 .map(|func| db.function_data(func).qualifier.is_unsafe) 106 .map(|func| db.function_data(func).is_unsafe())
107 .unwrap_or(false) 107 .unwrap_or(false)
108 { 108 {
109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 109 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 97f1092c6..148eb7506 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -19,7 +19,7 @@ use crate::{
19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, 19 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive,
20 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, 20 to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy,
21 CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, 21 CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy,
22 ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, 22 ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause,
23}; 23};
24 24
25pub struct HirFormatter<'a> { 25pub struct HirFormatter<'a> {
@@ -260,7 +260,7 @@ impl HirDisplay for ProjectionTy {
260 write!(f, "<{} as {}", first_parameter, trait_.name)?; 260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len(&Interner) > 1 { 261 if self.substitution.len(&Interner) > 1 {
262 write!(f, "<")?; 262 write!(f, "<")?;
263 f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; 263 f.write_joined(&self.substitution.interned()[1..], ", ")?;
264 write!(f, ">")?; 264 write!(f, ">")?;
265 } 265 }
266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; 266 write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?;
@@ -387,7 +387,7 @@ impl HirDisplay for Ty {
387 write!(f, ",)")?; 387 write!(f, ",)")?;
388 } else { 388 } else {
389 write!(f, "(")?; 389 write!(f, "(")?;
390 f.write_joined(&*substs.0, ", ")?; 390 f.write_joined(&*substs.interned(), ", ")?;
391 write!(f, ")")?; 391 write!(f, ")")?;
392 } 392 }
393 } 393 }
@@ -415,7 +415,7 @@ impl HirDisplay for Ty {
415 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? 415 // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self?
416 if total_len > 0 { 416 if total_len > 0 {
417 write!(f, "<")?; 417 write!(f, "<")?;
418 f.write_joined(&parameters.0[..total_len], ", ")?; 418 f.write_joined(&parameters.interned()[..total_len], ", ")?;
419 write!(f, ">")?; 419 write!(f, ">")?;
420 } 420 }
421 } 421 }
@@ -423,7 +423,7 @@ impl HirDisplay for Ty {
423 f.write_joined(sig.params(), ", ")?; 423 f.write_joined(sig.params(), ", ")?;
424 write!(f, ")")?; 424 write!(f, ")")?;
425 let ret = sig.ret(); 425 let ret = sig.ret();
426 if *ret != Ty::unit() { 426 if !ret.is_unit() {
427 let ret_display = ret.into_displayable( 427 let ret_display = ret.into_displayable(
428 f.db, 428 f.db,
429 f.max_size, 429 f.max_size,
@@ -468,7 +468,7 @@ impl HirDisplay for Ty {
468 .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) 468 .map(|generic_def_id| f.db.generic_defaults(generic_def_id))
469 .filter(|defaults| !defaults.is_empty()) 469 .filter(|defaults| !defaults.is_empty())
470 { 470 {
471 None => parameters.0.as_ref(), 471 None => parameters.interned().as_ref(),
472 Some(default_parameters) => { 472 Some(default_parameters) => {
473 let mut default_from = 0; 473 let mut default_from = 0;
474 for (i, parameter) in parameters.iter(&Interner).enumerate() { 474 for (i, parameter) in parameters.iter(&Interner).enumerate() {
@@ -490,11 +490,11 @@ impl HirDisplay for Ty {
490 } 490 }
491 } 491 }
492 } 492 }
493 &parameters.0[0..default_from] 493 &parameters.interned()[0..default_from]
494 } 494 }
495 } 495 }
496 } else { 496 } else {
497 parameters.0.as_ref() 497 parameters.interned().as_ref()
498 }; 498 };
499 if !parameters_to_write.is_empty() { 499 if !parameters_to_write.is_empty() {
500 write!(f, "<")?; 500 write!(f, "<")?;
@@ -517,7 +517,7 @@ impl HirDisplay for Ty {
517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
518 if parameters.len(&Interner) > 0 { 518 if parameters.len(&Interner) > 0 {
519 write!(f, "<")?; 519 write!(f, "<")?;
520 f.write_joined(&*parameters.0, ", ")?; 520 f.write_joined(&*parameters.interned(), ", ")?;
521 write!(f, ">")?; 521 write!(f, ">")?;
522 } 522 }
523 } else { 523 } else {
@@ -591,7 +591,7 @@ impl HirDisplay for Ty {
591 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 591 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
592 } 592 }
593 TypeParamProvenance::ArgumentImplTrait => { 593 TypeParamProvenance::ArgumentImplTrait => {
594 let substs = Substitution::type_params_for_generics(f.db, &generics); 594 let substs = generics.type_params_subst(f.db);
595 let bounds = f 595 let bounds = f
596 .db 596 .db
597 .generic_predicates(id.parent) 597 .generic_predicates(id.parent)
@@ -663,7 +663,7 @@ impl HirDisplay for CallableSig {
663 } 663 }
664 write!(f, ")")?; 664 write!(f, ")")?;
665 let ret = self.ret(); 665 let ret = self.ret();
666 if *ret != Ty::unit() { 666 if !ret.is_unit() {
667 let ret_display = 667 let ret_display =
668 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 668 ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
669 write!(f, " -> {}", ret_display)?; 669 write!(f, " -> {}", ret_display)?;
@@ -727,13 +727,13 @@ fn write_bounds_like_dyn_trait(
727 // existential) here, which is the only thing that's 727 // existential) here, which is the only thing that's
728 // possible in actual Rust, and hence don't print it 728 // possible in actual Rust, and hence don't print it
729 write!(f, "{}", f.db.trait_data(trait_).name)?; 729 write!(f, "{}", f.db.trait_data(trait_).name)?;
730 if let [_, params @ ..] = &*trait_ref.substitution.0 { 730 if let [_, params @ ..] = &*trait_ref.substitution.interned() {
731 if is_fn_trait { 731 if is_fn_trait {
732 if let Some(args) = 732 if let Some(args) =
733 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) 733 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
734 { 734 {
735 write!(f, "(")?; 735 write!(f, "(")?;
736 f.write_joined(&*args.0, ", ")?; 736 f.write_joined(&*args.interned(), ", ")?;
737 write!(f, ")")?; 737 write!(f, ")")?;
738 } 738 }
739 } else if !params.is_empty() { 739 } else if !params.is_empty() {
@@ -789,7 +789,7 @@ impl TraitRef {
789 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; 789 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
790 if self.substitution.len(&Interner) > 1 { 790 if self.substitution.len(&Interner) > 1 {
791 write!(f, "<")?; 791 write!(f, "<")?;
792 f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; 792 f.write_joined(&self.substitution.interned()[1..], ", ")?;
793 write!(f, ">")?; 793 write!(f, ">")?;
794 } 794 }
795 Ok(()) 795 Ok(())
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b871594bd..bb885db35 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -37,12 +37,12 @@ use stdx::impl_from;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{DomainGoal, Guidance, Solution}, 40 DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty,
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 TypeWalk,
42}; 42};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -409,16 +409,14 @@ impl<'a> InferenceContext<'a> {
409 _ => panic!("resolve_associated_type called with non-associated type"), 409 _ => panic!("resolve_associated_type called with non-associated type"),
410 }; 410 };
411 let ty = self.table.new_type_var(); 411 let ty = self.table.new_type_var();
412 let substs = Substitution::build_for_def(self.db, res_assoc_ty) 412 let trait_ref = TyBuilder::trait_ref(self.db, trait_)
413 .push(inner_ty) 413 .push(inner_ty)
414 .fill(params.iter().cloned()) 414 .fill(params.iter().cloned())
415 .build(); 415 .build();
416 let trait_ref =
417 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
418 let alias_eq = AliasEq { 416 let alias_eq = AliasEq {
419 alias: AliasTy::Projection(ProjectionTy { 417 alias: AliasTy::Projection(ProjectionTy {
420 associated_ty_id: to_assoc_type_id(res_assoc_ty), 418 associated_ty_id: to_assoc_type_id(res_assoc_ty),
421 substitution: substs, 419 substitution: trait_ref.substitution.clone(),
422 }), 420 }),
423 ty: ty.clone(), 421 ty: ty.clone(),
424 }; 422 };
@@ -489,7 +487,7 @@ impl<'a> InferenceContext<'a> {
489 } 487 }
490 TypeNs::SelfType(impl_id) => { 488 TypeNs::SelfType(impl_id) => {
491 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
492 let substs = Substitution::type_params_for_generics(self.db, &generics); 490 let substs = generics.type_params_subst(self.db);
493 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 491 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
494 match unresolved { 492 match unresolved {
495 None => { 493 None => {
@@ -516,10 +514,9 @@ impl<'a> InferenceContext<'a> {
516 } 514 }
517 } 515 }
518 TypeNs::TypeAliasId(it) => { 516 TypeNs::TypeAliasId(it) => {
519 let substs = Substitution::build_for_def(self.db, it) 517 let ty = TyBuilder::def_ty(self.db, it.into())
520 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 518 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
521 .build(); 519 .build();
522 let ty = self.db.ty(it.into()).subst(&substs);
523 let variant = ty_variant(&ty); 520 let variant = ty_variant(&ty);
524 forbid_unresolved_segments((ty, variant), unresolved) 521 forbid_unresolved_segments((ty, variant), unresolved)
525 } 522 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index d887e21a2..32c273afc 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,9 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{ 10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind};
11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
12};
13 11
14use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
15 13
@@ -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);
@@ -95,7 +93,7 @@ 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
@@ -130,18 +128,15 @@ impl<'a> InferenceContext<'a> {
130 _ => return None, 128 _ => return None,
131 }; 129 };
132 130
133 let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); 131 let trait_ref = {
134 if generic_params.len() != 2 { 132 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
135 // The CoerceUnsized trait should have two generic params: Self and T. 133 if b.remaining() != 2 {
136 return None; 134 // The CoerceUnsized trait should have two generic params: Self and T.
137 } 135 return None;
136 }
137 b.push(from_ty.clone()).push(to_ty.clone()).build()
138 };
138 139
139 let substs = Substitution::build_for_generics(&generic_params)
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)); 140 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner));
146 141
147 let canonicalizer = self.canonicalizer(); 142 let canonicalizer = self.canonicalizer();
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index dd3914ec3..ccaae53e9 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -19,11 +19,11 @@ use crate::{
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 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, variant_data, Generics},
25 AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, 25 AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar,
26 Substitution, TraitRef, Ty, TyKind, 26 Substitution, TraitRef, Ty, TyBuilder, TyKind,
27}; 27};
28 28
29use super::{ 29use super::{
@@ -73,38 +73,33 @@ impl<'a> InferenceContext<'a> {
73 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; 73 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
74 let output_assoc_type = 74 let output_assoc_type =
75 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; 75 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 76
81 let mut param_builder = Substitution::builder(num_args);
82 let mut arg_tys = vec![]; 77 let mut arg_tys = vec![];
83 for _ in 0..num_args { 78 let arg_ty = TyBuilder::tuple(num_args)
84 let arg = self.table.new_type_var(); 79 .fill(repeat_with(|| {
85 param_builder = param_builder.push(arg.clone()); 80 let arg = self.table.new_type_var();
86 arg_tys.push(arg); 81 arg_tys.push(arg.clone());
87 } 82 arg
88 let parameters = param_builder.build(); 83 }))
89 let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); 84 .build();
90 let substs = 85
91 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 86 let projection = {
87 let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type);
88 if b.remaining() != 2 {
89 return None;
90 }
91 b.push(ty.clone()).push(arg_ty).build()
92 };
92 93
93 let trait_env = self.trait_env.env.clone(); 94 let trait_env = self.trait_env.env.clone();
94 let implements_fn_trait: DomainGoal = 95 let obligation = InEnvironment {
95 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } 96 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, 97 environment: trait_env,
100 }); 98 };
101 if self.db.trait_solve(krate, goal.value).is_some() { 99 let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone());
102 self.push_obligation(implements_fn_trait); 100 if self.db.trait_solve(krate, canonical.value).is_some() {
103 let output_proj_ty = crate::ProjectionTy { 101 self.push_obligation(obligation.goal);
104 associated_ty_id: to_assoc_type_id(output_assoc_type), 102 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)) 103 Some((arg_tys, return_ty))
109 } else { 104 } else {
110 None 105 None
@@ -138,7 +133,7 @@ impl<'a> InferenceContext<'a> {
138 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); 133 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
139 let else_ty = match else_branch { 134 let else_ty = match else_branch {
140 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 135 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
141 None => Ty::unit(), 136 None => TyBuilder::unit(),
142 }; 137 };
143 both_arms_diverge &= self.diverges; 138 both_arms_diverge &= self.diverges;
144 139
@@ -193,7 +188,7 @@ impl<'a> InferenceContext<'a> {
193 break_ty: self.table.new_type_var(), 188 break_ty: self.table.new_type_var(),
194 label: label.map(|label| self.body[label].name.clone()), 189 label: label.map(|label| self.body[label].name.clone()),
195 }); 190 });
196 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 191 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
197 192
198 let ctxt = self.breakables.pop().expect("breakable stack broken"); 193 let ctxt = self.breakables.pop().expect("breakable stack broken");
199 if ctxt.may_break { 194 if ctxt.may_break {
@@ -217,11 +212,11 @@ impl<'a> InferenceContext<'a> {
217 *condition, 212 *condition,
218 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), 213 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
219 ); 214 );
220 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 215 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
221 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 216 let _ctxt = self.breakables.pop().expect("breakable stack broken");
222 // the body may not run, so it diverging doesn't mean we diverge 217 // the body may not run, so it diverging doesn't mean we diverge
223 self.diverges = Diverges::Maybe; 218 self.diverges = Diverges::Maybe;
224 Ty::unit() 219 TyBuilder::unit()
225 } 220 }
226 Expr::For { iterable, body, pat, label } => { 221 Expr::For { iterable, body, pat, label } => {
227 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 222 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
@@ -236,11 +231,11 @@ impl<'a> InferenceContext<'a> {
236 231
237 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 232 self.infer_pat(*pat, &pat_ty, BindingMode::default());
238 233
239 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 234 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
240 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 235 let _ctxt = self.breakables.pop().expect("breakable stack broken");
241 // the body may not run, so it diverging doesn't mean we diverge 236 // the body may not run, so it diverging doesn't mean we diverge
242 self.diverges = Diverges::Maybe; 237 self.diverges = Diverges::Maybe;
243 Ty::unit() 238 TyBuilder::unit()
244 } 239 }
245 Expr::Lambda { body, args, ret_type, arg_types } => { 240 Expr::Lambda { body, args, ret_type, arg_types } => {
246 assert_eq!(args.len(), arg_types.len()); 241 assert_eq!(args.len(), arg_types.len());
@@ -360,7 +355,7 @@ impl<'a> InferenceContext<'a> {
360 let val_ty = if let Some(expr) = expr { 355 let val_ty = if let Some(expr) = expr {
361 self.infer_expr(*expr, &Expectation::none()) 356 self.infer_expr(*expr, &Expectation::none())
362 } else { 357 } else {
363 Ty::unit() 358 TyBuilder::unit()
364 }; 359 };
365 360
366 let last_ty = 361 let last_ty =
@@ -386,7 +381,7 @@ impl<'a> InferenceContext<'a> {
386 if let Some(expr) = expr { 381 if let Some(expr) = expr {
387 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); 382 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
388 } else { 383 } else {
389 let unit = Ty::unit(); 384 let unit = TyBuilder::unit();
390 self.coerce(&unit, &self.return_ty.clone()); 385 self.coerce(&unit, &self.return_ty.clone());
391 } 386 }
392 TyKind::Never.intern(&Interner) 387 TyKind::Never.intern(&Interner)
@@ -457,11 +452,7 @@ impl<'a> InferenceContext<'a> {
457 }; 452 };
458 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { 453 match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) {
459 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { 454 TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| {
460 substs 455 substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned()
461 .interned(&Interner)
462 .get(idx)
463 .map(|a| a.assert_ty_ref(&Interner))
464 .cloned()
465 }), 456 }),
466 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { 457 TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => {
467 let local_id = self.db.struct_data(*s).variant_data.field(name)?; 458 let local_id = self.db.struct_data(*s).variant_data.field(name)?;
@@ -539,17 +530,10 @@ impl<'a> InferenceContext<'a> {
539 Expr::Box { expr } => { 530 Expr::Box { expr } => {
540 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 531 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
541 if let Some(box_) = self.resolve_boxed_box() { 532 if let Some(box_) = self.resolve_boxed_box() {
542 let mut sb = 533 TyBuilder::adt(self.db, box_)
543 Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); 534 .push(inner_ty)
544 sb = sb.push(inner_ty); 535 .fill_with_defaults(self.db, || self.table.new_type_var())
545 match self.db.generic_defaults(box_.into()).get(1) { 536 .build()
546 Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => {
547 sb = sb.push(alloc_ty.value.clone());
548 }
549 _ => (),
550 }
551 sb = sb.fill(repeat_with(|| self.table.new_type_var()));
552 Ty::adt_ty(box_, sb.build())
553 } else { 537 } else {
554 self.err_ty() 538 self.err_ty()
555 } 539 }
@@ -639,31 +623,31 @@ impl<'a> InferenceContext<'a> {
639 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); 623 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
640 match (range_type, lhs_ty, rhs_ty) { 624 match (range_type, lhs_ty, rhs_ty) {
641 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { 625 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
642 Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), 626 Some(adt) => TyBuilder::adt(self.db, adt).build(),
643 None => self.err_ty(), 627 None => self.err_ty(),
644 }, 628 },
645 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { 629 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
646 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 630 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
647 None => self.err_ty(), 631 None => self.err_ty(),
648 }, 632 },
649 (RangeOp::Inclusive, None, Some(ty)) => { 633 (RangeOp::Inclusive, None, Some(ty)) => {
650 match self.resolve_range_to_inclusive() { 634 match self.resolve_range_to_inclusive() {
651 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 635 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
652 None => self.err_ty(), 636 None => self.err_ty(),
653 } 637 }
654 } 638 }
655 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { 639 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
656 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 640 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
657 None => self.err_ty(), 641 None => self.err_ty(),
658 }, 642 },
659 (RangeOp::Inclusive, Some(_), Some(ty)) => { 643 (RangeOp::Inclusive, Some(_), Some(ty)) => {
660 match self.resolve_range_inclusive() { 644 match self.resolve_range_inclusive() {
661 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 645 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
662 None => self.err_ty(), 646 None => self.err_ty(),
663 } 647 }
664 } 648 }
665 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { 649 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
666 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 650 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
667 None => self.err_ty(), 651 None => self.err_ty(),
668 }, 652 },
669 (RangeOp::Inclusive, _, None) => self.err_ty(), 653 (RangeOp::Inclusive, _, None) => self.err_ty(),
@@ -828,8 +812,8 @@ impl<'a> InferenceContext<'a> {
828 // we don't even make an attempt at coercion 812 // we don't even make an attempt at coercion
829 self.table.new_maybe_never_var() 813 self.table.new_maybe_never_var()
830 } else { 814 } else {
831 self.coerce(&Ty::unit(), &expected.coercion_target()); 815 self.coerce(&TyBuilder::unit(), &expected.coercion_target());
832 Ty::unit() 816 TyBuilder::unit()
833 } 817 }
834 }; 818 };
835 ty 819 ty
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 10df8d8cb..469f37dd9 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -13,9 +13,8 @@ use hir_expand::name::Name;
13 13
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 15use crate::{
16 lower::lower_to_chalk_mutability, 16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder,
17 utils::{generics, variant_data}, 17 TyKind,
18 Interner, Substitution, Ty, TyKind,
19}; 18};
20 19
21impl<'a> InferenceContext<'a> { 20impl<'a> InferenceContext<'a> {
@@ -124,7 +123,7 @@ impl<'a> InferenceContext<'a> {
124 let ty = match &body[pat] { 123 let ty = match &body[pat] {
125 &Pat::Tuple { ref args, ellipsis } => { 124 &Pat::Tuple { ref args, ellipsis } => {
126 let expectations = match expected.as_tuple() { 125 let expectations = match expected.as_tuple() {
127 Some(parameters) => &*parameters.0, 126 Some(parameters) => &*parameters.interned(),
128 _ => &[], 127 _ => &[],
129 }; 128 };
130 129
@@ -240,29 +239,18 @@ impl<'a> InferenceContext<'a> {
240 let (inner_ty, alloc_ty) = match expected.as_adt() { 239 let (inner_ty, alloc_ty) = match expected.as_adt() {
241 Some((adt, subst)) if adt == box_adt => ( 240 Some((adt, subst)) if adt == box_adt => (
242 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), 241 subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(),
243 subst.interned(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), 242 subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()),
244 ), 243 ),
245 _ => (self.result.standard_types.unknown.clone(), None), 244 _ => (self.result.standard_types.unknown.clone(), None),
246 }; 245 };
247 246
248 let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); 247 let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm);
249 let mut sb = Substitution::build_for_generics(&generics( 248 let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty);
250 self.db.upcast(), 249
251 box_adt.into(), 250 if let Some(alloc_ty) = alloc_ty {
252 )); 251 b = b.push(alloc_ty);
253 sb = sb.push(inner_ty);
254 if sb.remaining() == 1 {
255 sb = sb.push(match alloc_ty {
256 Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty,
257 _ => match self.db.generic_defaults(box_adt.into()).get(1) {
258 Some(alloc_ty) if !alloc_ty.value.is_unknown() => {
259 alloc_ty.value.clone()
260 }
261 _ => self.table.new_type_var(),
262 },
263 });
264 } 252 }
265 Ty::adt_ty(box_adt, sb.build()) 253 b.fill_with_defaults(self.db, || self.table.new_type_var()).build()
266 } 254 }
267 None => self.err_ty(), 255 None => self.err_ty(),
268 }, 256 },
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 1ba15f737..637341b53 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -10,9 +10,7 @@ use hir_def::{
10}; 10};
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{ 13use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId};
14 method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId,
15};
16 14
17use super::{ExprOrPatId, InferenceContext, TraitRef}; 15use super::{ExprOrPatId, InferenceContext, TraitRef};
18 16
@@ -82,7 +80,7 @@ impl<'a> InferenceContext<'a> {
82 } 80 }
83 ValueNs::ImplSelf(impl_id) => { 81 ValueNs::ImplSelf(impl_id) => {
84 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 82 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
85 let substs = Substitution::type_params_for_generics(self.db, &generics); 83 let substs = generics.type_params_subst(self.db);
86 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 84 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
87 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { 85 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
88 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 86 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
@@ -95,16 +93,13 @@ impl<'a> InferenceContext<'a> {
95 ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), 93 ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)),
96 }; 94 };
97 95
98 let ty = self.db.value_ty(typable);
99 // self_subst is just for the parent
100 let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); 96 let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner));
101 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 97 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
102 let substs = ctx.substs_from_path(path, typable, true); 98 let substs = ctx.substs_from_path(path, typable, true);
103 let full_substs = Substitution::builder(substs.len(&Interner)) 99 let ty = TyBuilder::value_ty(self.db, typable)
104 .use_parent_substs(&parent_substs) 100 .use_parent_substs(&parent_substs)
105 .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) 101 .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned())
106 .build(); 102 .build();
107 let ty = ty.subst(&full_substs);
108 Some(ty) 103 Some(ty)
109 } 104 }
110 105
@@ -245,7 +240,7 @@ impl<'a> InferenceContext<'a> {
245 }; 240 };
246 let substs = match container { 241 let substs = match container {
247 AssocContainerId::ImplId(impl_id) => { 242 AssocContainerId::ImplId(impl_id) => {
248 let impl_substs = Substitution::build_for_def(self.db, impl_id) 243 let impl_substs = TyBuilder::subst_for_def(self.db, impl_id)
249 .fill(iter::repeat_with(|| self.table.new_type_var())) 244 .fill(iter::repeat_with(|| self.table.new_type_var()))
250 .build(); 245 .build();
251 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); 246 let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs);
@@ -254,18 +249,12 @@ impl<'a> InferenceContext<'a> {
254 } 249 }
255 AssocContainerId::TraitId(trait_) => { 250 AssocContainerId::TraitId(trait_) => {
256 // we're picking this method 251 // we're picking this method
257 let trait_substs = Substitution::build_for_def(self.db, trait_) 252 let trait_ref = TyBuilder::trait_ref(self.db, trait_)
258 .push(ty.clone()) 253 .push(ty.clone())
259 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 254 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
260 .build(); 255 .build();
261 self.push_obligation( 256 self.push_obligation(trait_ref.clone().cast(&Interner));
262 TraitRef { 257 Some(trait_ref.substitution)
263 trait_id: to_chalk_trait_id(trait_),
264 substitution: trait_substs.clone(),
265 }
266 .cast(&Interner),
267 );
268 Some(trait_substs)
269 } 258 }
270 AssocContainerId::ModuleId(_) => None, 259 AssocContainerId::ModuleId(_) => None,
271 }; 260 };
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index d2496db3b..b7bc48569 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -186,14 +186,11 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> {
186 ); 186 );
187 } 187 }
188 } 188 }
189 Some( 189 Some(Substitution::from_iter(
190 Substitution::builder(tys.binders.len(&Interner)) 190 &Interner,
191 .fill( 191 vars.iter(&Interner)
192 vars.iter(&Interner) 192 .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())),
193 .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), 193 ))
194 )
195 .build(),
196 )
197} 194}
198 195
199#[derive(Clone, Debug)] 196#[derive(Clone, Debug)]
@@ -287,7 +284,7 @@ impl InferenceTable {
287 substs2: &Substitution, 284 substs2: &Substitution,
288 depth: usize, 285 depth: usize,
289 ) -> bool { 286 ) -> bool {
290 substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { 287 substs1.iter(&Interner).zip(substs2.iter(&Interner)).all(|(t1, t2)| {
291 self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) 288 self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth)
292 }) 289 })
293 } 290 }
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 4c3d904bf..76609e2df 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -14,6 +14,10 @@ mod lower;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast; 16mod chalk_cast;
17mod chalk_ext;
18mod builder;
19mod walk;
20mod types;
17 21
18pub mod display; 22pub mod display;
19pub mod db; 23pub mod db;
@@ -24,30 +28,30 @@ mod tests;
24#[cfg(test)] 28#[cfg(test)]
25mod test_db; 29mod test_db;
26 30
27use std::{iter, mem, sync::Arc}; 31use std::sync::Arc;
28 32
29use base_db::salsa;
30use chalk_ir::cast::{CastTo, Caster};
31use hir_def::{
32 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId,
33 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
34};
35use itertools::Itertools; 33use itertools::Itertools;
36use smallvec::SmallVec; 34use smallvec::SmallVec;
37 35
38use crate::{ 36use base_db::salsa;
39 db::HirDatabase, 37use hir_def::{
40 display::HirDisplay, 38 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup,
41 utils::{generics, make_mut_slice, Generics}, 39 TraitId, TypeAliasId, TypeParamId,
42}; 40};
43 41
42use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43
44pub use autoderef::autoderef; 44pub use autoderef::autoderef;
45pub use builder::TyBuilder;
46pub use chalk_ext::TyExt;
45pub use infer::{could_unify, InferenceResult, InferenceVar}; 47pub use infer::{could_unify, InferenceResult, InferenceVar};
46pub use lower::{ 48pub use lower::{
47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 49 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
48 TyDefId, TyLoweringContext, ValueTyDefId, 50 TyDefId, TyLoweringContext, ValueTyDefId,
49}; 51};
50pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; 52pub use traits::TraitEnvironment;
53pub use types::*;
54pub use walk::TypeWalk;
51 55
52pub use chalk_ir::{ 56pub use chalk_ir::{
53 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, 57 cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind,
@@ -66,41 +70,6 @@ pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>;
66 70
67pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 71pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
68 72
69#[derive(Clone, PartialEq, Eq, Debug, Hash)]
70pub enum Lifetime {
71 Parameter(LifetimeParamId),
72 Static,
73}
74
75#[derive(Clone, PartialEq, Eq, Debug, Hash)]
76pub struct OpaqueTy {
77 pub opaque_ty_id: OpaqueTyId,
78 pub substitution: Substitution,
79}
80
81impl TypeWalk for OpaqueTy {
82 fn walk(&self, f: &mut impl FnMut(&Ty)) {
83 self.substitution.walk(f);
84 }
85
86 fn walk_mut_binders(
87 &mut self,
88 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
89 binders: DebruijnIndex,
90 ) {
91 self.substitution.walk_mut_binders(f, binders);
92 }
93}
94
95/// A "projection" type corresponds to an (unnormalized)
96/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
97/// trait and all its parameters are fully known.
98#[derive(Clone, PartialEq, Eq, Debug, Hash)]
99pub struct ProjectionTy {
100 pub associated_ty_id: AssocTypeId,
101 pub substitution: Substitution,
102}
103
104impl ProjectionTy { 73impl ProjectionTy {
105 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { 74 pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef {
106 TraitRef { 75 TraitRef {
@@ -110,7 +79,7 @@ impl ProjectionTy {
110 } 79 }
111 80
112 pub fn self_type_parameter(&self) -> &Ty { 81 pub fn self_type_parameter(&self) -> &Ty {
113 &self.substitution.interned(&Interner)[0].assert_ty_ref(&Interner) 82 &self.substitution.interned()[0].assert_ty_ref(&Interner)
114 } 83 }
115 84
116 fn trait_(&self, db: &dyn HirDatabase) -> TraitId { 85 fn trait_(&self, db: &dyn HirDatabase) -> TraitId {
@@ -121,322 +90,11 @@ impl ProjectionTy {
121 } 90 }
122} 91}
123 92
124impl TypeWalk for ProjectionTy {
125 fn walk(&self, f: &mut impl FnMut(&Ty)) {
126 self.substitution.walk(f);
127 }
128
129 fn walk_mut_binders(
130 &mut self,
131 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
132 binders: DebruijnIndex,
133 ) {
134 self.substitution.walk_mut_binders(f, binders);
135 }
136}
137
138#[derive(Clone, PartialEq, Eq, Debug, Hash)]
139pub struct DynTy {
140 /// The unknown self type.
141 pub bounds: Binders<QuantifiedWhereClauses>,
142}
143
144pub type FnSig = chalk_ir::FnSig<Interner>; 93pub type FnSig = chalk_ir::FnSig<Interner>;
145 94
146#[derive(Clone, PartialEq, Eq, Debug, Hash)]
147pub struct FnPointer {
148 pub num_args: usize,
149 pub sig: FnSig,
150 pub substs: Substitution,
151}
152
153#[derive(Clone, PartialEq, Eq, Debug, Hash)]
154pub enum AliasTy {
155 /// A "projection" type corresponds to an (unnormalized)
156 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
157 /// trait and all its parameters are fully known.
158 Projection(ProjectionTy),
159 /// An opaque type (`impl Trait`).
160 ///
161 /// This is currently only used for return type impl trait; each instance of
162 /// `impl Trait` in a return type gets its own ID.
163 Opaque(OpaqueTy),
164}
165
166impl TypeWalk for AliasTy {
167 fn walk(&self, f: &mut impl FnMut(&Ty)) {
168 match self {
169 AliasTy::Projection(it) => it.walk(f),
170 AliasTy::Opaque(it) => it.walk(f),
171 }
172 }
173
174 fn walk_mut_binders(
175 &mut self,
176 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
177 binders: DebruijnIndex,
178 ) {
179 match self {
180 AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
181 AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
182 }
183 }
184}
185/// A type.
186///
187/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
188/// the same thing (but in a different way).
189///
190/// This should be cheap to clone.
191#[derive(Clone, PartialEq, Eq, Debug, Hash)]
192pub enum TyKind {
193 /// Structures, enumerations and unions.
194 Adt(AdtId<Interner>, Substitution),
195
196 /// Represents an associated item like `Iterator::Item`. This is used
197 /// when we have tried to normalize a projection like `T::Item` but
198 /// couldn't find a better representation. In that case, we generate
199 /// an **application type** like `(Iterator::Item)<T>`.
200 AssociatedType(AssocTypeId, Substitution),
201
202 /// a scalar type like `bool` or `u32`
203 Scalar(Scalar),
204
205 /// A tuple type. For example, `(i32, bool)`.
206 Tuple(usize, Substitution),
207
208 /// An array with the given length. Written as `[T; n]`.
209 Array(Ty),
210
211 /// The pointee of an array slice. Written as `[T]`.
212 Slice(Ty),
213
214 /// A raw pointer. Written as `*mut T` or `*const T`
215 Raw(Mutability, Ty),
216
217 /// A reference; a pointer with an associated lifetime. Written as
218 /// `&'a mut T` or `&'a T`.
219 Ref(Mutability, Ty),
220
221 /// This represents a placeholder for an opaque type in situations where we
222 /// don't know the hidden type (i.e. currently almost always). This is
223 /// analogous to the `AssociatedType` type constructor.
224 /// It is also used as the type of async block, with one type parameter
225 /// representing the Future::Output type.
226 OpaqueType(OpaqueTyId, Substitution),
227
228 /// The anonymous type of a function declaration/definition. Each
229 /// function has a unique type, which is output (for a function
230 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
231 ///
232 /// This includes tuple struct / enum variant constructors as well.
233 ///
234 /// For example the type of `bar` here:
235 ///
236 /// ```
237 /// fn foo() -> i32 { 1 }
238 /// let bar = foo; // bar: fn() -> i32 {foo}
239 /// ```
240 FnDef(FnDefId, Substitution),
241
242 /// The pointee of a string slice. Written as `str`.
243 Str,
244
245 /// The never type `!`.
246 Never,
247
248 /// The type of a specific closure.
249 ///
250 /// The closure signature is stored in a `FnPtr` type in the first type
251 /// parameter.
252 Closure(ClosureId, Substitution),
253
254 /// Represents a foreign type declared in external blocks.
255 ForeignType(ForeignDefId),
256
257 /// A pointer to a function. Written as `fn() -> i32`.
258 ///
259 /// For example the type of `bar` here:
260 ///
261 /// ```
262 /// fn foo() -> i32 { 1 }
263 /// let bar: fn() -> i32 = foo;
264 /// ```
265 Function(FnPointer),
266
267 /// An "alias" type represents some form of type alias, such as:
268 /// - An associated type projection like `<T as Iterator>::Item`
269 /// - `impl Trait` types
270 /// - Named type aliases like `type Foo<X> = Vec<X>`
271 Alias(AliasTy),
272
273 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
274 /// {}` when we're type-checking the body of that function. In this
275 /// situation, we know this stands for *some* type, but don't know the exact
276 /// type.
277 Placeholder(PlaceholderIndex),
278
279 /// A bound type variable. This is used in various places: when representing
280 /// some polymorphic type like the type of function `fn f<T>`, the type
281 /// parameters get turned into variables; during trait resolution, inference
282 /// variables get turned into bound variables and back; and in `Dyn` the
283 /// `Self` type is represented with a bound variable as well.
284 BoundVar(BoundVar),
285
286 /// A type variable used during type checking.
287 InferenceVar(InferenceVar, TyVariableKind),
288
289 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
290 ///
291 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
292 /// represents the `Self` type inside the bounds. This is currently
293 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
294 /// didn't seem worth the overhead yet.
295 Dyn(DynTy),
296
297 /// A placeholder for a type which could not be computed; this is propagated
298 /// to avoid useless error messages. Doubles as a placeholder where type
299 /// variables are inserted before type checking, since we want to try to
300 /// infer a better type here anyway -- for the IDE use case, we want to try
301 /// to infer as much as possible even in the presence of type errors.
302 Unknown,
303}
304
305#[derive(Clone, PartialEq, Eq, Debug, Hash)]
306pub struct Ty(Arc<TyKind>);
307
308impl TyKind {
309 pub fn intern(self, _interner: &Interner) -> Ty {
310 Ty(Arc::new(self))
311 }
312}
313
314impl Ty {
315 pub fn kind(&self, _interner: &Interner) -> &TyKind {
316 &self.0
317 }
318
319 pub fn interned_mut(&mut self) -> &mut TyKind {
320 Arc::make_mut(&mut self.0)
321 }
322
323 pub fn into_inner(self) -> TyKind {
324 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
325 }
326}
327
328#[derive(Clone, PartialEq, Eq, Debug, Hash)]
329pub struct GenericArg {
330 interned: GenericArgData,
331}
332
333#[derive(Clone, PartialEq, Eq, Debug, Hash)]
334pub enum GenericArgData {
335 Ty(Ty),
336}
337
338impl GenericArg {
339 /// Constructs a generic argument using `GenericArgData`.
340 pub fn new(_interner: &Interner, data: GenericArgData) -> Self {
341 GenericArg { interned: data }
342 }
343
344 /// Gets the interned value.
345 pub fn interned(&self) -> &GenericArgData {
346 &self.interned
347 }
348
349 /// Asserts that this is a type argument.
350 pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty {
351 self.ty(interner).unwrap()
352 }
353
354 /// Checks whether the generic argument is a type.
355 pub fn is_ty(&self, _interner: &Interner) -> bool {
356 match self.interned() {
357 GenericArgData::Ty(_) => true,
358 }
359 }
360
361 /// Returns the type if it is one, `None` otherwise.
362 pub fn ty(&self, _interner: &Interner) -> Option<&Ty> {
363 match self.interned() {
364 GenericArgData::Ty(t) => Some(t),
365 }
366 }
367}
368
369impl TypeWalk for GenericArg {
370 fn walk(&self, f: &mut impl FnMut(&Ty)) {
371 match &self.interned {
372 GenericArgData::Ty(ty) => {
373 ty.walk(f);
374 }
375 }
376 }
377
378 fn walk_mut_binders(
379 &mut self,
380 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
381 binders: DebruijnIndex,
382 ) {
383 match &mut self.interned {
384 GenericArgData::Ty(ty) => {
385 ty.walk_mut_binders(f, binders);
386 }
387 }
388 }
389}
390
391/// A list of substitutions for generic parameters.
392#[derive(Clone, PartialEq, Eq, Debug, Hash)]
393pub struct Substitution(SmallVec<[GenericArg; 2]>);
394
395impl TypeWalk for Substitution {
396 fn walk(&self, f: &mut impl FnMut(&Ty)) {
397 for t in self.0.iter() {
398 t.walk(f);
399 }
400 }
401
402 fn walk_mut_binders(
403 &mut self,
404 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
405 binders: DebruijnIndex,
406 ) {
407 for t in &mut self.0 {
408 t.walk_mut_binders(f, binders);
409 }
410 }
411}
412
413impl Substitution { 95impl Substitution {
414 pub fn interned(&self, _: &Interner) -> &[GenericArg] {
415 &self.0
416 }
417
418 pub fn len(&self, _: &Interner) -> usize {
419 self.0.len()
420 }
421
422 pub fn is_empty(&self, _: &Interner) -> bool {
423 self.0.is_empty()
424 }
425
426 pub fn at(&self, _: &Interner, i: usize) -> &GenericArg {
427 &self.0[i]
428 }
429
430 pub fn empty(_: &Interner) -> Substitution {
431 Substitution(SmallVec::new())
432 }
433
434 pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> {
435 self.0.iter()
436 }
437
438 pub fn single(ty: Ty) -> Substitution { 96 pub fn single(ty: Ty) -> Substitution {
439 Substitution({ 97 Substitution::intern({
440 let mut v = SmallVec::new(); 98 let mut v = SmallVec::new();
441 v.push(ty.cast(&Interner)); 99 v.push(ty.cast(&Interner));
442 v 100 v
@@ -444,64 +102,14 @@ impl Substitution {
444 } 102 }
445 103
446 pub fn prefix(&self, n: usize) -> Substitution { 104 pub fn prefix(&self, n: usize) -> Substitution {
447 Substitution(self.0[..std::cmp::min(self.0.len(), n)].into()) 105 Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into())
448 } 106 }
449 107
450 pub fn suffix(&self, n: usize) -> Substitution { 108 pub fn suffix(&self, n: usize) -> Substitution {
451 Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) 109 Substitution::intern(
452 } 110 self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(),
453
454 pub fn from_iter(
455 interner: &Interner,
456 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
457 ) -> Self {
458 Substitution(elements.into_iter().casted(interner).collect())
459 }
460
461 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
462 pub(crate) fn type_params_for_generics(
463 db: &dyn HirDatabase,
464 generic_params: &Generics,
465 ) -> Substitution {
466 Substitution::from_iter(
467 &Interner,
468 generic_params
469 .iter()
470 .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)),
471 )
472 }
473
474 /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`).
475 pub fn type_params(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
476 let params = generics(db.upcast(), def.into());
477 Substitution::type_params_for_generics(db, &params)
478 }
479
480 /// Return Substs that replace each parameter by a bound variable.
481 pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution {
482 Substitution::from_iter(
483 &Interner,
484 generic_params
485 .iter()
486 .enumerate()
487 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
488 ) 111 )
489 } 112 }
490
491 pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder {
492 let def = def.into();
493 let params = generics(db.upcast(), def);
494 let param_count = params.len();
495 Substitution::builder(param_count)
496 }
497
498 pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder {
499 Substitution::builder(generic_params.len())
500 }
501
502 fn builder(param_count: usize) -> SubstsBuilder {
503 SubstsBuilder { vec: Vec::with_capacity(param_count), param_count }
504 }
505} 113}
506 114
507/// Return an index of a parameter in the generic type parameter list by it's id. 115/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -509,58 +117,6 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
509 generics(db.upcast(), id.parent).param_idx(id) 117 generics(db.upcast(), id.parent).param_idx(id)
510} 118}
511 119
512#[derive(Debug, Clone)]
513pub struct SubstsBuilder {
514 vec: Vec<GenericArg>,
515 param_count: usize,
516}
517
518impl SubstsBuilder {
519 pub fn build(self) -> Substitution {
520 assert_eq!(self.vec.len(), self.param_count);
521 Substitution::from_iter(&Interner, self.vec)
522 }
523
524 pub fn push(mut self, ty: impl CastTo<GenericArg>) -> Self {
525 self.vec.push(ty.cast(&Interner));
526 self
527 }
528
529 fn remaining(&self) -> usize {
530 self.param_count - self.vec.len()
531 }
532
533 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
534 self.fill(
535 (starting_from..)
536 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
537 )
538 }
539
540 pub fn fill_with_unknown(self) -> Self {
541 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
542 }
543
544 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
545 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
546 assert_eq!(self.remaining(), 0);
547 self
548 }
549
550 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
551 assert!(self.vec.is_empty());
552 assert!(parent_substs.len(&Interner) <= self.param_count);
553 self.vec.extend(parent_substs.iter(&Interner).cloned());
554 self
555 }
556}
557
558#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
559pub struct Binders<T> {
560 pub num_binders: usize,
561 pub value: T,
562}
563
564impl<T> Binders<T> { 120impl<T> Binders<T> {
565 pub fn new(num_binders: usize, value: T) -> Self { 121 pub fn new(num_binders: usize, value: T) -> Self {
566 Self { num_binders, value } 122 Self { num_binders, value }
@@ -608,27 +164,6 @@ impl<T: TypeWalk> Binders<T> {
608 } 164 }
609} 165}
610 166
611impl<T: TypeWalk> TypeWalk for Binders<T> {
612 fn walk(&self, f: &mut impl FnMut(&Ty)) {
613 self.value.walk(f);
614 }
615
616 fn walk_mut_binders(
617 &mut self,
618 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
619 binders: DebruijnIndex,
620 ) {
621 self.value.walk_mut_binders(f, binders.shifted_in())
622 }
623}
624
625/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
626#[derive(Clone, PartialEq, Eq, Debug, Hash)]
627pub struct TraitRef {
628 pub trait_id: ChalkTraitId,
629 pub substitution: Substitution,
630}
631
632impl TraitRef { 167impl TraitRef {
633 pub fn self_type_parameter(&self) -> &Ty { 168 pub fn self_type_parameter(&self) -> &Ty {
634 &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) 169 &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner)
@@ -639,30 +174,6 @@ impl TraitRef {
639 } 174 }
640} 175}
641 176
642impl TypeWalk for TraitRef {
643 fn walk(&self, f: &mut impl FnMut(&Ty)) {
644 self.substitution.walk(f);
645 }
646
647 fn walk_mut_binders(
648 &mut self,
649 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
650 binders: DebruijnIndex,
651 ) {
652 self.substitution.walk_mut_binders(f, binders);
653 }
654}
655
656/// Like `generics::WherePredicate`, but with resolved types: A condition on the
657/// parameters of a generic item.
658#[derive(Debug, Clone, PartialEq, Eq, Hash)]
659pub enum WhereClause {
660 /// The given trait needs to be implemented for its type parameters.
661 Implemented(TraitRef),
662 /// An associated type bindings like in `Iterator<Item = T>`.
663 AliasEq(AliasEq),
664}
665
666impl WhereClause { 177impl WhereClause {
667 pub fn is_implemented(&self) -> bool { 178 pub fn is_implemented(&self) -> bool {
668 matches!(self, WhereClause::Implemented(_)) 179 matches!(self, WhereClause::Implemented(_))
@@ -679,56 +190,6 @@ impl WhereClause {
679 } 190 }
680} 191}
681 192
682impl TypeWalk for WhereClause {
683 fn walk(&self, f: &mut impl FnMut(&Ty)) {
684 match self {
685 WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
686 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
687 }
688 }
689
690 fn walk_mut_binders(
691 &mut self,
692 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
693 binders: DebruijnIndex,
694 ) {
695 match self {
696 WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
697 WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
698 }
699 }
700}
701
702pub type QuantifiedWhereClause = Binders<WhereClause>;
703
704#[derive(Debug, Clone, PartialEq, Eq, Hash)]
705pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
706
707impl QuantifiedWhereClauses {
708 pub fn from_iter(
709 _interner: &Interner,
710 elements: impl IntoIterator<Item = QuantifiedWhereClause>,
711 ) -> Self {
712 QuantifiedWhereClauses(elements.into_iter().collect())
713 }
714
715 pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
716 &self.0
717 }
718}
719
720/// Basically a claim (currently not validated / checked) that the contained
721/// type / trait ref contains no inference variables; any inference variables it
722/// contained have been replaced by bound variables, and `kinds` tells us how
723/// many there are and whether they were normal or float/int variables. This is
724/// used to erase irrelevant differences between types before using them in
725/// queries.
726#[derive(Debug, Clone, PartialEq, Eq, Hash)]
727pub struct Canonical<T> {
728 pub value: T,
729 pub binders: CanonicalVarKinds,
730}
731
732impl<T> Canonical<T> { 193impl<T> Canonical<T> {
733 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { 194 pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self {
734 let kinds = kinds.into_iter().map(|tk| { 195 let kinds = kinds.into_iter().map(|tk| {
@@ -760,12 +221,12 @@ impl CallableSig {
760 221
761 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { 222 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
762 CallableSig { 223 CallableSig {
763 // FIXME: what to do about lifetime params? 224 // FIXME: what to do about lifetime params? -> return PolyFnSig
764 params_and_return: fn_ptr 225 params_and_return: fn_ptr
765 .substs 226 .substs
766 .clone() 227 .clone()
767 .shift_bound_vars_out(DebruijnIndex::ONE) 228 .shift_bound_vars_out(DebruijnIndex::ONE)
768 .interned(&Interner) 229 .interned()
769 .iter() 230 .iter()
770 .map(|arg| arg.assert_ty_ref(&Interner).clone()) 231 .map(|arg| arg.assert_ty_ref(&Interner).clone())
771 .collect(), 232 .collect(),
@@ -773,16 +234,6 @@ impl CallableSig {
773 } 234 }
774 } 235 }
775 236
776 pub fn from_substs(substs: &Substitution) -> CallableSig {
777 CallableSig {
778 params_and_return: substs
779 .iter(&Interner)
780 .map(|arg| arg.assert_ty_ref(&Interner).clone())
781 .collect(),
782 is_varargs: false,
783 }
784 }
785
786 pub fn params(&self) -> &[Ty] { 237 pub fn params(&self) -> &[Ty] {
787 &self.params_and_return[0..self.params_and_return.len() - 1] 238 &self.params_and_return[0..self.params_and_return.len() - 1]
788 } 239 }
@@ -792,59 +243,7 @@ impl CallableSig {
792 } 243 }
793} 244}
794 245
795impl TypeWalk for CallableSig {
796 fn walk(&self, f: &mut impl FnMut(&Ty)) {
797 for t in self.params_and_return.iter() {
798 t.walk(f);
799 }
800 }
801
802 fn walk_mut_binders(
803 &mut self,
804 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
805 binders: DebruijnIndex,
806 ) {
807 for t in make_mut_slice(&mut self.params_and_return) {
808 t.walk_mut_binders(f, binders);
809 }
810 }
811}
812
813impl Ty { 246impl Ty {
814 pub fn unit() -> Self {
815 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
816 }
817
818 pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty {
819 TyKind::Adt(AdtId(adt), substs).intern(&Interner)
820 }
821
822 pub fn fn_ptr(sig: CallableSig) -> Self {
823 TyKind::Function(FnPointer {
824 num_args: sig.params().len(),
825 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
826 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()),
827 })
828 .intern(&Interner)
829 }
830
831 pub fn builtin(builtin: BuiltinType) -> Self {
832 match builtin {
833 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
834 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
835 BuiltinType::Str => TyKind::Str.intern(&Interner),
836 BuiltinType::Int(t) => {
837 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
838 }
839 BuiltinType::Uint(t) => {
840 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
841 }
842 BuiltinType::Float(t) => {
843 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
844 }
845 }
846 }
847
848 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { 247 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
849 match self.kind(&Interner) { 248 match self.kind(&Interner) {
850 TyKind::Ref(mutability, ty) => Some((ty, *mutability)), 249 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
@@ -1068,7 +467,7 @@ impl Ty {
1068 let param_data = &generic_params.types[id.local_id]; 467 let param_data = &generic_params.types[id.local_id];
1069 match param_data.provenance { 468 match param_data.provenance {
1070 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { 469 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
1071 let substs = Substitution::type_params(db, id.parent); 470 let substs = TyBuilder::type_params_subst(db, id.parent);
1072 let predicates = db 471 let predicates = db
1073 .generic_predicates(id.parent) 472 .generic_predicates(id.parent)
1074 .into_iter() 473 .into_iter()
@@ -1114,200 +513,6 @@ impl Ty {
1114 } 513 }
1115} 514}
1116 515
1117/// This allows walking structures that contain types to do something with those
1118/// types, similar to Chalk's `Fold` trait.
1119pub trait TypeWalk {
1120 fn walk(&self, f: &mut impl FnMut(&Ty));
1121 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
1122 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
1123 }
1124 /// Walk the type, counting entered binders.
1125 ///
1126 /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
1127 /// to the innermost binder, 1 to the next, etc.. So when we want to
1128 /// substitute a certain bound variable, we can't just walk the whole type
1129 /// and blindly replace each instance of a certain index; when we 'enter'
1130 /// things that introduce new bound variables, we have to keep track of
1131 /// that. Currently, the only thing that introduces bound variables on our
1132 /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
1133 /// variable for the self type.
1134 fn walk_mut_binders(
1135 &mut self,
1136 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1137 binders: DebruijnIndex,
1138 );
1139
1140 fn fold_binders(
1141 mut self,
1142 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
1143 binders: DebruijnIndex,
1144 ) -> Self
1145 where
1146 Self: Sized,
1147 {
1148 self.walk_mut_binders(
1149 &mut |ty_mut, binders| {
1150 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
1151 *ty_mut = f(ty, binders);
1152 },
1153 binders,
1154 );
1155 self
1156 }
1157
1158 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
1159 where
1160 Self: Sized,
1161 {
1162 self.walk_mut(&mut |ty_mut| {
1163 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
1164 *ty_mut = f(ty);
1165 });
1166 self
1167 }
1168
1169 /// Substitutes `TyKind::Bound` vars with the given substitution.
1170 fn subst_bound_vars(self, substs: &Substitution) -> Self
1171 where
1172 Self: Sized,
1173 {
1174 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
1175 }
1176
1177 /// Substitutes `TyKind::Bound` vars with the given substitution.
1178 fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self
1179 where
1180 Self: Sized,
1181 {
1182 self.walk_mut_binders(
1183 &mut |ty, binders| {
1184 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
1185 if bound.debruijn >= binders {
1186 *ty = substs.0[bound.index]
1187 .assert_ty_ref(&Interner)
1188 .clone()
1189 .shift_bound_vars(binders);
1190 }
1191 }
1192 },
1193 depth,
1194 );
1195 self
1196 }
1197
1198 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
1199 fn shift_bound_vars(self, n: DebruijnIndex) -> Self
1200 where
1201 Self: Sized,
1202 {
1203 self.fold_binders(
1204 &mut |ty, binders| match ty.kind(&Interner) {
1205 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
1206 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
1207 }
1208 _ => ty,
1209 },
1210 DebruijnIndex::INNERMOST,
1211 )
1212 }
1213
1214 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
1215 fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self
1216 where
1217 Self: Sized + std::fmt::Debug,
1218 {
1219 self.fold_binders(
1220 &mut |ty, binders| match ty.kind(&Interner) {
1221 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
1222 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
1223 .intern(&Interner)
1224 }
1225 _ => ty,
1226 },
1227 DebruijnIndex::INNERMOST,
1228 )
1229 }
1230}
1231
1232impl TypeWalk for Ty {
1233 fn walk(&self, f: &mut impl FnMut(&Ty)) {
1234 match self.kind(&Interner) {
1235 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1236 for t in p_ty.substitution.iter(&Interner) {
1237 t.walk(f);
1238 }
1239 }
1240 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1241 for t in o_ty.substitution.iter(&Interner) {
1242 t.walk(f);
1243 }
1244 }
1245 TyKind::Dyn(dyn_ty) => {
1246 for p in dyn_ty.bounds.value.interned().iter() {
1247 p.walk(f);
1248 }
1249 }
1250 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1251 ty.walk(f);
1252 }
1253 _ => {
1254 if let Some(substs) = self.substs() {
1255 for t in substs.iter(&Interner) {
1256 t.walk(f);
1257 }
1258 }
1259 }
1260 }
1261 f(self);
1262 }
1263
1264 fn walk_mut_binders(
1265 &mut self,
1266 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1267 binders: DebruijnIndex,
1268 ) {
1269 match self.interned_mut() {
1270 TyKind::Alias(AliasTy::Projection(p_ty)) => {
1271 p_ty.substitution.walk_mut_binders(f, binders);
1272 }
1273 TyKind::Dyn(dyn_ty) => {
1274 for p in make_mut_slice(&mut dyn_ty.bounds.value.0) {
1275 p.walk_mut_binders(f, binders.shifted_in());
1276 }
1277 }
1278 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
1279 o_ty.substitution.walk_mut_binders(f, binders);
1280 }
1281 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
1282 ty.walk_mut_binders(f, binders);
1283 }
1284 _ => {
1285 if let Some(substs) = self.substs_mut() {
1286 substs.walk_mut_binders(f, binders);
1287 }
1288 }
1289 }
1290 f(self, binders);
1291 }
1292}
1293
1294impl<T: TypeWalk> TypeWalk for Vec<T> {
1295 fn walk(&self, f: &mut impl FnMut(&Ty)) {
1296 for t in self {
1297 t.walk(f);
1298 }
1299 }
1300 fn walk_mut_binders(
1301 &mut self,
1302 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
1303 binders: DebruijnIndex,
1304 ) {
1305 for t in self {
1306 t.walk_mut_binders(f, binders);
1307 }
1308 }
1309}
1310
1311#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 516#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
1312pub enum ImplTraitId { 517pub enum ImplTraitId {
1313 ReturnTypeImplTrait(hir_def::FunctionId, u16), 518 ReturnTypeImplTrait(hir_def::FunctionId, u16),
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index f595683e5..214655807 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -36,7 +36,7 @@ use crate::{
36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, 36 AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig,
37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, 37 ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses,
38 ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, 38 ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty,
39 TyKind, TypeWalk, WhereClause, 39 TyBuilder, TyKind, TypeWalk, WhereClause,
40}; 40};
41 41
42#[derive(Debug)] 42#[derive(Debug)]
@@ -234,7 +234,7 @@ impl<'a> TyLoweringContext<'a> {
234 let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx); 234 let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx);
235 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); 235 let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into();
236 let generics = generics(self.db.upcast(), func.into()); 236 let generics = generics(self.db.upcast(), func.into());
237 let parameters = Substitution::bound_vars(&generics, self.in_binders); 237 let parameters = generics.bound_vars_subst(self.in_binders);
238 TyKind::Alias(AliasTy::Opaque(OpaqueTy { 238 TyKind::Alias(AliasTy::Opaque(OpaqueTy {
239 opaque_ty_id, 239 opaque_ty_id,
240 substitution: parameters, 240 substitution: parameters,
@@ -411,24 +411,16 @@ impl<'a> TyLoweringContext<'a> {
411 TypeNs::SelfType(impl_id) => { 411 TypeNs::SelfType(impl_id) => {
412 let generics = generics(self.db.upcast(), impl_id.into()); 412 let generics = generics(self.db.upcast(), impl_id.into());
413 let substs = match self.type_param_mode { 413 let substs = match self.type_param_mode {
414 TypeParamLoweringMode::Placeholder => { 414 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db),
415 Substitution::type_params_for_generics(self.db, &generics) 415 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders),
416 }
417 TypeParamLoweringMode::Variable => {
418 Substitution::bound_vars(&generics, self.in_binders)
419 }
420 }; 416 };
421 self.db.impl_self_ty(impl_id).subst(&substs) 417 self.db.impl_self_ty(impl_id).subst(&substs)
422 } 418 }
423 TypeNs::AdtSelfType(adt) => { 419 TypeNs::AdtSelfType(adt) => {
424 let generics = generics(self.db.upcast(), adt.into()); 420 let generics = generics(self.db.upcast(), adt.into());
425 let substs = match self.type_param_mode { 421 let substs = match self.type_param_mode {
426 TypeParamLoweringMode::Placeholder => { 422 TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db),
427 Substitution::type_params_for_generics(self.db, &generics) 423 TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders),
428 }
429 TypeParamLoweringMode::Variable => {
430 Substitution::bound_vars(&generics, self.in_binders)
431 }
432 }; 424 };
433 self.db.ty(adt.into()).subst(&substs) 425 self.db.ty(adt.into()).subst(&substs)
434 } 426 }
@@ -478,12 +470,13 @@ impl<'a> TyLoweringContext<'a> {
478 TypeParamLoweringMode::Placeholder => { 470 TypeParamLoweringMode::Placeholder => {
479 // if we're lowering to placeholders, we have to put 471 // if we're lowering to placeholders, we have to put
480 // them in now 472 // them in now
481 let s = Substitution::type_params( 473 let generics = generics(
482 self.db, 474 self.db.upcast(),
483 self.resolver.generic_def().expect( 475 self.resolver.generic_def().expect(
484 "there should be generics if there's a generic param", 476 "there should be generics if there's a generic param",
485 ), 477 ),
486 ); 478 );
479 let s = generics.type_params_subst(self.db);
487 t.substitution.clone().subst_bound_vars(&s) 480 t.substitution.clone().subst_bound_vars(&s)
488 } 481 }
489 TypeParamLoweringMode::Variable => t.substitution.clone(), 482 TypeParamLoweringMode::Variable => t.substitution.clone(),
@@ -860,10 +853,9 @@ pub fn associated_type_shorthand_candidates<R>(
860 if generics.params.types[param_id.local_id].provenance 853 if generics.params.types[param_id.local_id].provenance
861 == TypeParamProvenance::TraitSelf 854 == TypeParamProvenance::TraitSelf
862 { 855 {
863 let trait_ref = TraitRef { 856 let trait_ref = TyBuilder::trait_ref(db, trait_id)
864 trait_id: to_chalk_trait_id(trait_id), 857 .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0)
865 substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), 858 .build();
866 };
867 return search(trait_ref); 859 return search(trait_ref);
868 } 860 }
869 } 861 }
@@ -972,7 +964,7 @@ pub(crate) fn trait_environment_query(
972 // function default implementations (and hypothetical code 964 // function default implementations (and hypothetical code
973 // inside consts or type aliases) 965 // inside consts or type aliases)
974 cov_mark::hit!(trait_self_implements_self); 966 cov_mark::hit!(trait_self_implements_self);
975 let substs = Substitution::type_params(db, trait_id); 967 let substs = TyBuilder::type_params_subst(db, trait_id);
976 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; 968 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs };
977 let pred = WhereClause::Implemented(trait_ref); 969 let pred = WhereClause::Implemented(trait_ref);
978 let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); 970 let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner);
@@ -1054,14 +1046,14 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
1054 let ret = (&ctx_ret).lower_ty(&data.ret_type); 1046 let ret = (&ctx_ret).lower_ty(&data.ret_type);
1055 let generics = generics(db.upcast(), def.into()); 1047 let generics = generics(db.upcast(), def.into());
1056 let num_binders = generics.len(); 1048 let num_binders = generics.len();
1057 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs)) 1049 Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs()))
1058} 1050}
1059 1051
1060/// Build the declared type of a function. This should not need to look at the 1052/// Build the declared type of a function. This should not need to look at the
1061/// function body. 1053/// function body.
1062fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 1054fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1063 let generics = generics(db.upcast(), def.into()); 1055 let generics = generics(db.upcast(), def.into());
1064 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1056 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1065 Binders::new( 1057 Binders::new(
1066 substs.len(&Interner), 1058 substs.len(&Interner),
1067 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), 1059 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner),
@@ -1106,7 +1098,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
1106 return type_for_adt(db, def.into()); 1098 return type_for_adt(db, def.into());
1107 } 1099 }
1108 let generics = generics(db.upcast(), def.into()); 1100 let generics = generics(db.upcast(), def.into());
1109 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1101 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1110 Binders::new( 1102 Binders::new(
1111 substs.len(&Interner), 1103 substs.len(&Interner),
1112 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner), 1104 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner),
@@ -1133,7 +1125,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1133 return type_for_adt(db, def.parent.into()); 1125 return type_for_adt(db, def.parent.into());
1134 } 1126 }
1135 let generics = generics(db.upcast(), def.parent.into()); 1127 let generics = generics(db.upcast(), def.parent.into());
1136 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1128 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1137 Binders::new( 1129 Binders::new(
1138 substs.len(&Interner), 1130 substs.len(&Interner),
1139 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner), 1131 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner),
@@ -1141,9 +1133,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1141} 1133}
1142 1134
1143fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 1135fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1144 let generics = generics(db.upcast(), adt.into()); 1136 let b = TyBuilder::adt(db, adt);
1145 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1137 let num_binders = b.remaining();
1146 Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) 1138 let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
1139 Binders::new(num_binders, ty)
1147} 1140}
1148 1141
1149fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { 1142fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
@@ -1215,7 +1208,7 @@ impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for V
1215/// namespace. 1208/// namespace.
1216pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> { 1209pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
1217 match def { 1210 match def {
1218 TyDefId::BuiltinType(it) => Binders::new(0, Ty::builtin(it)), 1211 TyDefId::BuiltinType(it) => Binders::new(0, TyBuilder::builtin(it)),
1219 TyDefId::AdtId(it) => type_for_adt(db, it), 1212 TyDefId::AdtId(it) => type_for_adt(db, it),
1220 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), 1213 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
1221 } 1214 }
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 338851fa8..0e4a620b6 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -19,10 +19,9 @@ use crate::{
19 db::HirDatabase, 19 db::HirDatabase,
20 from_foreign_def_id, 20 from_foreign_def_id,
21 primitive::{self, FloatTy, IntTy, UintTy}, 21 primitive::{self, FloatTy, IntTy, UintTy},
22 to_chalk_trait_id,
23 utils::all_super_traits, 22 utils::all_super_traits,
24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, 23 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
25 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, 24 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind,
26 TypeWalk, 25 TypeWalk,
27}; 26};
28 27
@@ -675,7 +674,7 @@ fn is_valid_candidate(
675 } 674 }
676 } 675 }
677 if let Some(receiver_ty) = receiver_ty { 676 if let Some(receiver_ty) = receiver_ty {
678 if !data.has_self_param { 677 if !data.has_self_param() {
679 return false; 678 return false;
680 } 679 }
681 let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { 680 let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) {
@@ -710,7 +709,7 @@ pub(crate) fn inherent_impl_substs(
710) -> Option<Substitution> { 709) -> Option<Substitution> {
711 // we create a var for each type parameter of the impl; we need to keep in 710 // we create a var for each type parameter of the impl; we need to keep in
712 // mind here that `self_ty` might have vars of its own 711 // mind here that `self_ty` might have vars of its own
713 let vars = Substitution::build_for_def(db, impl_id) 712 let vars = TyBuilder::subst_for_def(db, impl_id)
714 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) 713 .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner))
715 .build(); 714 .build();
716 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); 715 let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars);
@@ -761,13 +760,13 @@ fn transform_receiver_ty(
761 self_ty: &Canonical<Ty>, 760 self_ty: &Canonical<Ty>,
762) -> Option<Ty> { 761) -> Option<Ty> {
763 let substs = match function_id.lookup(db.upcast()).container { 762 let substs = match function_id.lookup(db.upcast()).container {
764 AssocContainerId::TraitId(_) => Substitution::build_for_def(db, function_id) 763 AssocContainerId::TraitId(_) => TyBuilder::subst_for_def(db, function_id)
765 .push(self_ty.value.clone()) 764 .push(self_ty.value.clone())
766 .fill_with_unknown() 765 .fill_with_unknown()
767 .build(), 766 .build(),
768 AssocContainerId::ImplId(impl_id) => { 767 AssocContainerId::ImplId(impl_id) => {
769 let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; 768 let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?;
770 Substitution::build_for_def(db, function_id) 769 TyBuilder::subst_for_def(db, function_id)
771 .use_parent_substs(&impl_substs) 770 .use_parent_substs(&impl_substs)
772 .fill_with_unknown() 771 .fill_with_unknown()
773 .build() 772 .build()
@@ -801,7 +800,7 @@ pub fn implements_trait_unique(
801 let goal = generic_implements_goal(db, env, trait_, ty.clone()); 800 let goal = generic_implements_goal(db, env, trait_, ty.clone());
802 let solution = db.trait_solve(krate, goal); 801 let solution = db.trait_solve(krate, goal);
803 802
804 matches!(solution, Some(crate::traits::Solution::Unique(_))) 803 matches!(solution, Some(crate::Solution::Unique(_)))
805} 804}
806 805
807/// This creates Substs for a trait with the given Self type and type variables 806/// This creates Substs for a trait with the given Self type and type variables
@@ -813,7 +812,7 @@ fn generic_implements_goal(
813 self_ty: Canonical<Ty>, 812 self_ty: Canonical<Ty>,
814) -> Canonical<InEnvironment<super::DomainGoal>> { 813) -> Canonical<InEnvironment<super::DomainGoal>> {
815 let mut kinds = self_ty.binders.interned().to_vec(); 814 let mut kinds = self_ty.binders.interned().to_vec();
816 let substs = super::Substitution::build_for_def(db, trait_) 815 let trait_ref = TyBuilder::trait_ref(db, trait_)
817 .push(self_ty.value) 816 .push(self_ty.value)
818 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) 817 .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len())
819 .build(); 818 .build();
@@ -822,9 +821,8 @@ fn generic_implements_goal(
822 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), 821 chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General),
823 UniverseIndex::ROOT, 822 UniverseIndex::ROOT,
824 )) 823 ))
825 .take(substs.len(&Interner) - 1), 824 .take(trait_ref.substitution.len(&Interner) - 1),
826 ); 825 );
827 let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs };
828 let obligation = trait_ref.cast(&Interner); 826 let obligation = trait_ref.cast(&Interner);
829 Canonical { 827 Canonical {
830 binders: CanonicalVarKinds::from_iter(&Interner, kinds), 828 binders: CanonicalVarKinds::from_iter(&Interner, kinds),
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs
index 8533e1ed8..90dd31a35 100644
--- a/crates/hir_ty/src/op.rs
+++ b/crates/hir_ty/src/op.rs
@@ -2,12 +2,12 @@
2use chalk_ir::TyVariableKind; 2use chalk_ir::TyVariableKind;
3use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; 3use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
4 4
5use crate::{Interner, Scalar, Ty, TyKind}; 5use crate::{Interner, Scalar, Ty, TyBuilder, TyKind};
6 6
7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { 7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
8 match op { 8 match op {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => Ty::unit(), 10 BinaryOp::Assignment { .. } => TyBuilder::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 match lhs_ty.kind(&Interner) { 12 match lhs_ty.kind(&Interner) {
13 TyKind::Scalar(Scalar::Int(_)) 13 TyKind::Scalar(Scalar::Int(_))
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs
index ad283c1e0..ccfb88c52 100644
--- a/crates/hir_ty/src/tests.rs
+++ b/crates/hir_ty/src/tests.rs
@@ -288,7 +288,7 @@ fn visit_module(
288 } 288 }
289 289
290 fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) { 290 fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) {
291 for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { 291 for (_, def_map) in body.blocks(db) {
292 for (mod_id, _) in def_map.modules() { 292 for (mod_id, _) in def_map.modules() {
293 visit_module(db, &def_map, mod_id, cb); 293 visit_module(db, &def_map, mod_id, cb);
294 } 294 }
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs
index e5e8cff33..66d600bfc 100644
--- a/crates/hir_ty/src/traits.rs
+++ b/crates/hir_ty/src/traits.rs
@@ -8,8 +8,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId};
8use stdx::panic_context; 8use stdx::panic_context;
9 9
10use crate::{ 10use crate::{
11 db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, 11 db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment,
12 TypeWalk, WhereClause, 12 Solution, SolutionVariables, Ty, TyKind, WhereClause,
13}; 13};
14 14
15use self::chalk::{from_chalk, Interner, ToChalk}; 15use self::chalk::{from_chalk, Interner, ToChalk};
@@ -70,55 +70,6 @@ impl Default for TraitEnvironment {
70 } 70 }
71} 71}
72 72
73/// Something (usually a goal), along with an environment.
74#[derive(Clone, Debug, PartialEq, Eq, Hash)]
75pub struct InEnvironment<T> {
76 pub environment: chalk_ir::Environment<Interner>,
77 pub goal: T,
78}
79
80impl<T> InEnvironment<T> {
81 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
82 InEnvironment { environment, goal: value }
83 }
84}
85
86/// Something that needs to be proven (by Chalk) during type checking, e.g. that
87/// a certain type implements a certain trait. Proving the Obligation might
88/// result in additional information about inference variables.
89#[derive(Clone, Debug, PartialEq, Eq, Hash)]
90pub enum DomainGoal {
91 Holds(WhereClause),
92}
93
94#[derive(Clone, Debug, PartialEq, Eq, Hash)]
95pub struct AliasEq {
96 pub alias: AliasTy,
97 pub ty: Ty,
98}
99
100impl TypeWalk for AliasEq {
101 fn walk(&self, f: &mut impl FnMut(&Ty)) {
102 self.ty.walk(f);
103 match &self.alias {
104 AliasTy::Projection(projection_ty) => projection_ty.walk(f),
105 AliasTy::Opaque(opaque) => opaque.walk(f),
106 }
107 }
108
109 fn walk_mut_binders(
110 &mut self,
111 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
112 binders: DebruijnIndex,
113 ) {
114 self.ty.walk_mut_binders(f, binders);
115 match &mut self.alias {
116 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
117 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
118 }
119 }
120}
121
122/// Solve a trait goal using Chalk. 73/// Solve a trait goal using Chalk.
123pub(crate) fn trait_solve_query( 74pub(crate) fn trait_solve_query(
124 db: &dyn HirDatabase, 75 db: &dyn HirDatabase,
@@ -246,41 +197,6 @@ fn solution_from_chalk(
246 } 197 }
247} 198}
248 199
249#[derive(Clone, Debug, PartialEq, Eq)]
250pub struct SolutionVariables(pub Canonical<Substitution>);
251
252#[derive(Clone, Debug, PartialEq, Eq)]
253/// A (possible) solution for a proposed goal.
254pub enum Solution {
255 /// The goal indeed holds, and there is a unique value for all existential
256 /// variables.
257 Unique(SolutionVariables),
258
259 /// The goal may be provable in multiple ways, but regardless we may have some guidance
260 /// for type inference. In this case, we don't return any lifetime
261 /// constraints, since we have not "committed" to any particular solution
262 /// yet.
263 Ambig(Guidance),
264}
265
266#[derive(Clone, Debug, PartialEq, Eq)]
267/// When a goal holds ambiguously (e.g., because there are multiple possible
268/// solutions), we issue a set of *guidance* back to type inference.
269pub enum Guidance {
270 /// The existential variables *must* have the given values if the goal is
271 /// ever to hold, but that alone isn't enough to guarantee the goal will
272 /// actually hold.
273 Definite(SolutionVariables),
274
275 /// There are multiple plausible values for the existentials, but the ones
276 /// here are suggested as the preferred choice heuristically. These should
277 /// be used for inference fallback only.
278 Suggested(SolutionVariables),
279
280 /// There's no useful information to feed back to type inference
281 Unknown,
282}
283
284#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] 200#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
285pub enum FnTrait { 201pub enum FnTrait {
286 FnOnce, 202 FnOnce,
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index fbac51b05..541e6082f 100644
--- a/crates/hir_ty/src/traits/chalk.rs
+++ b/crates/hir_ty/src/traits/chalk.rs
@@ -22,7 +22,7 @@ use crate::{
22 to_assoc_type_id, to_chalk_trait_id, 22 to_assoc_type_id, to_chalk_trait_id,
23 utils::generics, 23 utils::generics,
24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, 24 AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution,
25 TraitRef, Ty, TyKind, WhereClause, 25 TraitRef, Ty, TyBuilder, TyKind, WhereClause,
26}; 26};
27use mapping::{ 27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, 28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -300,7 +300,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
300 _closure_id: chalk_ir::ClosureId<Interner>, 300 _closure_id: chalk_ir::ClosureId<Interner>,
301 _substs: &chalk_ir::Substitution<Interner>, 301 _substs: &chalk_ir::Substitution<Interner>,
302 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 302 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
303 let ty = Ty::unit().to_chalk(self.db); 303 let ty = TyBuilder::unit().to_chalk(self.db);
304 make_binders(ty, 0) 304 make_binders(ty, 0)
305 } 305 }
306 fn closure_fn_substitution( 306 fn closure_fn_substitution(
@@ -387,7 +387,7 @@ pub(crate) fn associated_ty_data_query(
387 // Lower bounds -- we could/should maybe move this to a separate query in `lower` 387 // Lower bounds -- we could/should maybe move this to a separate query in `lower`
388 let type_alias_data = db.type_alias_data(type_alias); 388 let type_alias_data = db.type_alias_data(type_alias);
389 let generic_params = generics(db.upcast(), type_alias.into()); 389 let generic_params = generics(db.upcast(), type_alias.into());
390 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 390 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); 391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
392 let ctx = crate::TyLoweringContext::new(db, &resolver) 392 let ctx = crate::TyLoweringContext::new(db, &resolver)
393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); 393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
@@ -421,7 +421,7 @@ pub(crate) fn trait_datum_query(
421 let trait_data = db.trait_data(trait_); 421 let trait_data = db.trait_data(trait_);
422 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 422 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
423 let generic_params = generics(db.upcast(), trait_.into()); 423 let generic_params = generics(db.upcast(), trait_.into());
424 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 424 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
425 let flags = rust_ir::TraitFlags { 425 let flags = rust_ir::TraitFlags {
426 auto: trait_data.is_auto, 426 auto: trait_data.is_auto,
427 upstream: trait_.lookup(db.upcast()).container.krate() != krate, 427 upstream: trait_.lookup(db.upcast()).container.krate() != krate,
@@ -490,7 +490,7 @@ pub(crate) fn struct_datum_query(
490 let upstream = adt_id.module(db.upcast()).krate() != krate; 490 let upstream = adt_id.module(db.upcast()).krate() != krate;
491 let where_clauses = { 491 let where_clauses = {
492 let generic_params = generics(db.upcast(), adt_id.into()); 492 let generic_params = generics(db.upcast(), adt_id.into());
493 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 493 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
494 convert_where_clauses(db, adt_id.into(), &bound_vars) 494 convert_where_clauses(db, adt_id.into(), &bound_vars)
495 }; 495 };
496 let flags = rust_ir::AdtFlags { 496 let flags = rust_ir::AdtFlags {
@@ -539,7 +539,7 @@ fn impl_def_datum(
539 let impl_data = db.impl_data(impl_id); 539 let impl_data = db.impl_data(impl_id);
540 540
541 let generic_params = generics(db.upcast(), impl_id.into()); 541 let generic_params = generics(db.upcast(), impl_id.into());
542 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 542 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
543 let trait_ = trait_ref.hir_trait_id(); 543 let trait_ = trait_ref.hir_trait_id();
544 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { 544 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
545 rust_ir::ImplType::Local 545 rust_ir::ImplType::Local
@@ -629,7 +629,7 @@ pub(crate) fn fn_def_datum_query(
629 let callable_def: CallableDefId = from_chalk(db, fn_def_id); 629 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
630 let generic_params = generics(db.upcast(), callable_def.into()); 630 let generic_params = generics(db.upcast(), callable_def.into());
631 let sig = db.callable_item_signature(callable_def); 631 let sig = db.callable_item_signature(callable_def);
632 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 632 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
634 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 452b357e8..5e4f97a46 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -10,11 +10,9 @@ use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 db::HirDatabase, 13 db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer,
14 primitive::UintTy, 14 GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution,
15 traits::{Canonical, DomainGoal}, 15 TraitRef, Ty, TypeWalk, WhereClause,
16 AliasTy, CallableDefId, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy,
17 QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause,
18}; 16};
19 17
20use super::interner::*; 18use super::interner::*;
@@ -220,8 +218,8 @@ impl ToChalk for GenericArg {
220 type Chalk = chalk_ir::GenericArg<Interner>; 218 type Chalk = chalk_ir::GenericArg<Interner>;
221 219
222 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { 220 fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk {
223 match self.interned { 221 match self.interned() {
224 crate::GenericArgData::Ty(ty) => ty.to_chalk(db).cast(&Interner), 222 crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner),
225 } 223 }
226 } 224 }
227 225
@@ -249,7 +247,7 @@ impl ToChalk for Substitution {
249 parameters: chalk_ir::Substitution<Interner>, 247 parameters: chalk_ir::Substitution<Interner>,
250 ) -> Substitution { 248 ) -> Substitution {
251 let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); 249 let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect();
252 Substitution(tys) 250 Substitution::intern(tys)
253 } 251 }
254} 252}
255 253
@@ -546,7 +544,7 @@ pub(super) fn generic_predicate_to_inline_bound(
546 // have the expected self type 544 // have the expected self type
547 return None; 545 return None;
548 } 546 }
549 let args_no_self = trait_ref.substitution.interned(&Interner)[1..] 547 let args_no_self = trait_ref.substitution.interned()[1..]
550 .iter() 548 .iter()
551 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 549 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
552 .collect(); 550 .collect();
@@ -558,7 +556,7 @@ pub(super) fn generic_predicate_to_inline_bound(
558 return None; 556 return None;
559 } 557 }
560 let trait_ = projection_ty.trait_(db); 558 let trait_ = projection_ty.trait_(db);
561 let args_no_self = projection_ty.substitution.interned(&Interner)[1..] 559 let args_no_self = projection_ty.substitution.interned()[1..]
562 .iter() 560 .iter()
563 .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) 561 .map(|ty| ty.clone().to_chalk(db).cast(&Interner))
564 .collect(); 562 .collect();
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
new file mode 100644
index 000000000..53662fcdc
--- /dev/null
+++ b/crates/hir_ty/src/types.rs
@@ -0,0 +1,416 @@
1//! This is the home of `Ty` etc. until they get replaced by their chalk_ir
2//! equivalents.
3
4use std::sync::Arc;
5
6use chalk_ir::{
7 cast::{CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind,
9};
10use hir_def::LifetimeParamId;
11use smallvec::SmallVec;
12
13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex,
16};
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
19pub enum Lifetime {
20 Parameter(LifetimeParamId),
21 Static,
22}
23
24#[derive(Clone, PartialEq, Eq, Debug, Hash)]
25pub struct OpaqueTy {
26 pub opaque_ty_id: OpaqueTyId,
27 pub substitution: Substitution,
28}
29
30/// A "projection" type corresponds to an (unnormalized)
31/// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
32/// trait and all its parameters are fully known.
33#[derive(Clone, PartialEq, Eq, Debug, Hash)]
34pub struct ProjectionTy {
35 pub associated_ty_id: AssocTypeId,
36 pub substitution: Substitution,
37}
38
39#[derive(Clone, PartialEq, Eq, Debug, Hash)]
40pub struct DynTy {
41 /// The unknown self type.
42 pub bounds: Binders<QuantifiedWhereClauses>,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug, Hash)]
46pub struct FnPointer {
47 pub num_args: usize,
48 pub sig: FnSig,
49 pub substs: Substitution,
50}
51
52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
53pub enum AliasTy {
54 /// A "projection" type corresponds to an (unnormalized)
55 /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the
56 /// trait and all its parameters are fully known.
57 Projection(ProjectionTy),
58 /// An opaque type (`impl Trait`).
59 ///
60 /// This is currently only used for return type impl trait; each instance of
61 /// `impl Trait` in a return type gets its own ID.
62 Opaque(OpaqueTy),
63}
64
65/// A type.
66///
67/// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents
68/// the same thing (but in a different way).
69///
70/// This should be cheap to clone.
71#[derive(Clone, PartialEq, Eq, Debug, Hash)]
72pub enum TyKind {
73 /// Structures, enumerations and unions.
74 Adt(chalk_ir::AdtId<Interner>, Substitution),
75
76 /// Represents an associated item like `Iterator::Item`. This is used
77 /// when we have tried to normalize a projection like `T::Item` but
78 /// couldn't find a better representation. In that case, we generate
79 /// an **application type** like `(Iterator::Item)<T>`.
80 AssociatedType(AssocTypeId, Substitution),
81
82 /// a scalar type like `bool` or `u32`
83 Scalar(Scalar),
84
85 /// A tuple type. For example, `(i32, bool)`.
86 Tuple(usize, Substitution),
87
88 /// An array with the given length. Written as `[T; n]`.
89 Array(Ty),
90
91 /// The pointee of an array slice. Written as `[T]`.
92 Slice(Ty),
93
94 /// A raw pointer. Written as `*mut T` or `*const T`
95 Raw(Mutability, Ty),
96
97 /// A reference; a pointer with an associated lifetime. Written as
98 /// `&'a mut T` or `&'a T`.
99 Ref(Mutability, Ty),
100
101 /// This represents a placeholder for an opaque type in situations where we
102 /// don't know the hidden type (i.e. currently almost always). This is
103 /// analogous to the `AssociatedType` type constructor.
104 /// It is also used as the type of async block, with one type parameter
105 /// representing the Future::Output type.
106 OpaqueType(OpaqueTyId, Substitution),
107
108 /// The anonymous type of a function declaration/definition. Each
109 /// function has a unique type, which is output (for a function
110 /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`.
111 ///
112 /// This includes tuple struct / enum variant constructors as well.
113 ///
114 /// For example the type of `bar` here:
115 ///
116 /// ```
117 /// fn foo() -> i32 { 1 }
118 /// let bar = foo; // bar: fn() -> i32 {foo}
119 /// ```
120 FnDef(FnDefId, Substitution),
121
122 /// The pointee of a string slice. Written as `str`.
123 Str,
124
125 /// The never type `!`.
126 Never,
127
128 /// The type of a specific closure.
129 ///
130 /// The closure signature is stored in a `FnPtr` type in the first type
131 /// parameter.
132 Closure(ClosureId, Substitution),
133
134 /// Represents a foreign type declared in external blocks.
135 ForeignType(ForeignDefId),
136
137 /// A pointer to a function. Written as `fn() -> i32`.
138 ///
139 /// For example the type of `bar` here:
140 ///
141 /// ```
142 /// fn foo() -> i32 { 1 }
143 /// let bar: fn() -> i32 = foo;
144 /// ```
145 Function(FnPointer),
146
147 /// An "alias" type represents some form of type alias, such as:
148 /// - An associated type projection like `<T as Iterator>::Item`
149 /// - `impl Trait` types
150 /// - Named type aliases like `type Foo<X> = Vec<X>`
151 Alias(AliasTy),
152
153 /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T)
154 /// {}` when we're type-checking the body of that function. In this
155 /// situation, we know this stands for *some* type, but don't know the exact
156 /// type.
157 Placeholder(PlaceholderIndex),
158
159 /// A bound type variable. This is used in various places: when representing
160 /// some polymorphic type like the type of function `fn f<T>`, the type
161 /// parameters get turned into variables; during trait resolution, inference
162 /// variables get turned into bound variables and back; and in `Dyn` the
163 /// `Self` type is represented with a bound variable as well.
164 BoundVar(BoundVar),
165
166 /// A type variable used during type checking.
167 InferenceVar(InferenceVar, TyVariableKind),
168
169 /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust).
170 ///
171 /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)`
172 /// represents the `Self` type inside the bounds. This is currently
173 /// implicit; Chalk has the `Binders` struct to make it explicit, but it
174 /// didn't seem worth the overhead yet.
175 Dyn(DynTy),
176
177 /// A placeholder for a type which could not be computed; this is propagated
178 /// to avoid useless error messages. Doubles as a placeholder where type
179 /// variables are inserted before type checking, since we want to try to
180 /// infer a better type here anyway -- for the IDE use case, we want to try
181 /// to infer as much as possible even in the presence of type errors.
182 Unknown,
183}
184
185#[derive(Clone, PartialEq, Eq, Debug, Hash)]
186pub struct Ty(Arc<TyKind>);
187
188impl TyKind {
189 pub fn intern(self, _interner: &Interner) -> Ty {
190 Ty(Arc::new(self))
191 }
192}
193
194impl Ty {
195 pub fn kind(&self, _interner: &Interner) -> &TyKind {
196 &self.0
197 }
198
199 pub fn interned_mut(&mut self) -> &mut TyKind {
200 Arc::make_mut(&mut self.0)
201 }
202
203 pub fn into_inner(self) -> TyKind {
204 Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone())
205 }
206}
207
208#[derive(Clone, PartialEq, Eq, Debug, Hash)]
209pub struct GenericArg {
210 interned: GenericArgData,
211}
212
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub enum GenericArgData {
215 Ty(Ty),
216}
217
218impl GenericArg {
219 /// Constructs a generic argument using `GenericArgData`.
220 pub fn new(_interner: &Interner, data: GenericArgData) -> Self {
221 GenericArg { interned: data }
222 }
223
224 /// Gets the interned value.
225 pub fn interned(&self) -> &GenericArgData {
226 &self.interned
227 }
228
229 /// Asserts that this is a type argument.
230 pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty {
231 self.ty(interner).unwrap()
232 }
233
234 /// Checks whether the generic argument is a type.
235 pub fn is_ty(&self, _interner: &Interner) -> bool {
236 match self.interned() {
237 GenericArgData::Ty(_) => true,
238 }
239 }
240
241 /// Returns the type if it is one, `None` otherwise.
242 pub fn ty(&self, _interner: &Interner) -> Option<&Ty> {
243 match self.interned() {
244 GenericArgData::Ty(t) => Some(t),
245 }
246 }
247
248 pub fn interned_mut(&mut self) -> &mut GenericArgData {
249 &mut self.interned
250 }
251}
252
253/// A list of substitutions for generic parameters.
254#[derive(Clone, PartialEq, Eq, Debug, Hash)]
255pub struct Substitution(SmallVec<[GenericArg; 2]>);
256
257impl Substitution {
258 pub fn interned(&self) -> &[GenericArg] {
259 &self.0
260 }
261
262 pub fn len(&self, _: &Interner) -> usize {
263 self.0.len()
264 }
265
266 pub fn is_empty(&self, _: &Interner) -> bool {
267 self.0.is_empty()
268 }
269
270 pub fn at(&self, _: &Interner, i: usize) -> &GenericArg {
271 &self.0[i]
272 }
273
274 pub fn empty(_: &Interner) -> Substitution {
275 Substitution(SmallVec::new())
276 }
277
278 pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> {
279 self.0.iter()
280 }
281
282 pub fn from_iter(
283 interner: &Interner,
284 elements: impl IntoIterator<Item = impl CastTo<GenericArg>>,
285 ) -> Self {
286 Substitution(elements.into_iter().casted(interner).collect())
287 }
288
289 // We can hopefully add this to Chalk
290 pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution {
291 Substitution(interned)
292 }
293
294 pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> {
295 &mut self.0
296 }
297}
298
299#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
300pub struct Binders<T> {
301 pub num_binders: usize,
302 pub value: T,
303}
304
305/// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait.
306#[derive(Clone, PartialEq, Eq, Debug, Hash)]
307pub struct TraitRef {
308 pub trait_id: ChalkTraitId,
309 pub substitution: Substitution,
310}
311
312/// Like `generics::WherePredicate`, but with resolved types: A condition on the
313/// parameters of a generic item.
314#[derive(Debug, Clone, PartialEq, Eq, Hash)]
315pub enum WhereClause {
316 /// The given trait needs to be implemented for its type parameters.
317 Implemented(TraitRef),
318 /// An associated type bindings like in `Iterator<Item = T>`.
319 AliasEq(AliasEq),
320}
321
322pub type QuantifiedWhereClause = Binders<WhereClause>;
323
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
326
327impl QuantifiedWhereClauses {
328 pub fn from_iter(
329 _interner: &Interner,
330 elements: impl IntoIterator<Item = QuantifiedWhereClause>,
331 ) -> Self {
332 QuantifiedWhereClauses(elements.into_iter().collect())
333 }
334
335 pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> {
336 &self.0
337 }
338
339 pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> {
340 &mut self.0
341 }
342}
343
344/// Basically a claim (currently not validated / checked) that the contained
345/// type / trait ref contains no inference variables; any inference variables it
346/// contained have been replaced by bound variables, and `kinds` tells us how
347/// many there are and whether they were normal or float/int variables. This is
348/// used to erase irrelevant differences between types before using them in
349/// queries.
350#[derive(Debug, Clone, PartialEq, Eq, Hash)]
351pub struct Canonical<T> {
352 pub value: T,
353 pub binders: CanonicalVarKinds,
354}
355
356/// Something (usually a goal), along with an environment.
357#[derive(Clone, Debug, PartialEq, Eq, Hash)]
358pub struct InEnvironment<T> {
359 pub environment: chalk_ir::Environment<Interner>,
360 pub goal: T,
361}
362
363impl<T> InEnvironment<T> {
364 pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> {
365 InEnvironment { environment, goal: value }
366 }
367}
368
369/// Something that needs to be proven (by Chalk) during type checking, e.g. that
370/// a certain type implements a certain trait. Proving the Obligation might
371/// result in additional information about inference variables.
372#[derive(Clone, Debug, PartialEq, Eq, Hash)]
373pub enum DomainGoal {
374 Holds(WhereClause),
375}
376
377#[derive(Clone, Debug, PartialEq, Eq, Hash)]
378pub struct AliasEq {
379 pub alias: AliasTy,
380 pub ty: Ty,
381}
382
383#[derive(Clone, Debug, PartialEq, Eq)]
384pub struct SolutionVariables(pub Canonical<Substitution>);
385
386#[derive(Clone, Debug, PartialEq, Eq)]
387/// A (possible) solution for a proposed goal.
388pub enum Solution {
389 /// The goal indeed holds, and there is a unique value for all existential
390 /// variables.
391 Unique(SolutionVariables),
392
393 /// The goal may be provable in multiple ways, but regardless we may have some guidance
394 /// for type inference. In this case, we don't return any lifetime
395 /// constraints, since we have not "committed" to any particular solution
396 /// yet.
397 Ambig(Guidance),
398}
399
400#[derive(Clone, Debug, PartialEq, Eq)]
401/// When a goal holds ambiguously (e.g., because there are multiple possible
402/// solutions), we issue a set of *guidance* back to type inference.
403pub enum Guidance {
404 /// The existential variables *must* have the given values if the goal is
405 /// ever to hold, but that alone isn't enough to guarantee the goal will
406 /// actually hold.
407 Definite(SolutionVariables),
408
409 /// There are multiple plausible values for the existentials, but the ones
410 /// here are suggested as the preferred choice heuristically. These should
411 /// be used for inference fallback only.
412 Suggested(SolutionVariables),
413
414 /// There's no useful information to feed back to type inference
415 Unknown,
416}
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs
index 42d7af146..df0ea4368 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -2,13 +2,14 @@
2//! query, but can't be computed directly from `*Data` (ie, which need a `db`). 2//! query, but can't be computed directly from `*Data` (ie, which need a `db`).
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use chalk_ir::DebruijnIndex; 5use chalk_ir::{BoundVar, DebruijnIndex};
6use hir_def::{ 6use hir_def::{
7 adt::VariantData, 7 adt::VariantData,
8 db::DefDatabase, 8 db::DefDatabase,
9 generics::{ 9 generics::{
10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, 10 GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget,
11 }, 11 },
12 intern::Interned,
12 path::Path, 13 path::Path,
13 resolver::{HasResolver, TypeNs}, 14 resolver::{HasResolver, TypeNs},
14 type_ref::TypeRef, 15 type_ref::TypeRef,
@@ -16,7 +17,7 @@ use hir_def::{
16}; 17};
17use hir_expand::name::{name, Name}; 18use hir_expand::name::{name, Name};
18 19
19use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; 20use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause};
20 21
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 22fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
22 let resolver = trait_.resolver(db); 23 let resolver = trait_.resolver(db);
@@ -32,11 +33,10 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
32 .filter_map(|pred| match pred { 33 .filter_map(|pred| match pred {
33 WherePredicate::ForLifetime { target, bound, .. } 34 WherePredicate::ForLifetime { target, bound, .. }
34 | WherePredicate::TypeBound { target, bound } => match target { 35 | WherePredicate::TypeBound { target, bound } => match target {
35 WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) 36 WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref {
36 if p == &Path::from(name![Self]) => 37 TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(),
37 { 38 _ => None,
38 bound.as_path() 39 },
39 }
40 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { 40 WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => {
41 bound.as_path() 41 bound.as_path()
42 } 42 }
@@ -159,7 +159,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics {
159#[derive(Debug)] 159#[derive(Debug)]
160pub(crate) struct Generics { 160pub(crate) struct Generics {
161 def: GenericDefId, 161 def: GenericDefId,
162 pub(crate) params: Arc<GenericParams>, 162 pub(crate) params: Interned<GenericParams>,
163 parent_generics: Option<Box<Generics>>, 163 parent_generics: Option<Box<Generics>>,
164} 164}
165 165
@@ -249,6 +249,26 @@ impl Generics {
249 self.parent_generics.as_ref().and_then(|g| g.find_param(param)) 249 self.parent_generics.as_ref().and_then(|g| g.find_param(param))
250 } 250 }
251 } 251 }
252
253 /// Returns a Substitution that replaces each parameter by a bound variable.
254 pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution {
255 Substitution::from_iter(
256 &Interner,
257 self.iter()
258 .enumerate()
259 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
260 )
261 }
262
263 /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`).
264 pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution {
265 Substitution::from_iter(
266 &Interner,
267 self.iter().map(|(id, _)| {
268 TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner)
269 }),
270 )
271 }
252} 272}
253 273
254fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 274fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
new file mode 100644
index 000000000..bfb3f1041
--- /dev/null
+++ b/crates/hir_ty/src/walk.rs
@@ -0,0 +1,381 @@
1//! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and
2//! `Visit`).
3
4use std::mem;
5
6use chalk_ir::DebruijnIndex;
7
8use crate::{
9 utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, GenericArg, GenericArgData,
10 Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause,
11};
12
13/// This allows walking structures that contain types to do something with those
14/// types, similar to Chalk's `Fold` trait.
15pub trait TypeWalk {
16 fn walk(&self, f: &mut impl FnMut(&Ty));
17 fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) {
18 self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST);
19 }
20 /// Walk the type, counting entered binders.
21 ///
22 /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers
23 /// to the innermost binder, 1 to the next, etc.. So when we want to
24 /// substitute a certain bound variable, we can't just walk the whole type
25 /// and blindly replace each instance of a certain index; when we 'enter'
26 /// things that introduce new bound variables, we have to keep track of
27 /// that. Currently, the only thing that introduces bound variables on our
28 /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound
29 /// variable for the self type.
30 fn walk_mut_binders(
31 &mut self,
32 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
33 binders: DebruijnIndex,
34 );
35
36 fn fold_binders(
37 mut self,
38 f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty,
39 binders: DebruijnIndex,
40 ) -> Self
41 where
42 Self: Sized,
43 {
44 self.walk_mut_binders(
45 &mut |ty_mut, binders| {
46 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
47 *ty_mut = f(ty, binders);
48 },
49 binders,
50 );
51 self
52 }
53
54 fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self
55 where
56 Self: Sized,
57 {
58 self.walk_mut(&mut |ty_mut| {
59 let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner));
60 *ty_mut = f(ty);
61 });
62 self
63 }
64
65 /// Substitutes `TyKind::Bound` vars with the given substitution.
66 fn subst_bound_vars(self, substs: &Substitution) -> Self
67 where
68 Self: Sized,
69 {
70 self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST)
71 }
72
73 /// Substitutes `TyKind::Bound` vars with the given substitution.
74 fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self
75 where
76 Self: Sized,
77 {
78 self.walk_mut_binders(
79 &mut |ty, binders| {
80 if let &mut TyKind::BoundVar(bound) = ty.interned_mut() {
81 if bound.debruijn >= binders {
82 *ty = substs.interned()[bound.index]
83 .assert_ty_ref(&Interner)
84 .clone()
85 .shift_bound_vars(binders);
86 }
87 }
88 },
89 depth,
90 );
91 self
92 }
93
94 /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`.
95 fn shift_bound_vars(self, n: DebruijnIndex) -> Self
96 where
97 Self: Sized,
98 {
99 self.fold_binders(
100 &mut |ty, binders| match ty.kind(&Interner) {
101 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
102 TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner)
103 }
104 _ => ty,
105 },
106 DebruijnIndex::INNERMOST,
107 )
108 }
109
110 /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`.
111 fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self
112 where
113 Self: Sized + std::fmt::Debug,
114 {
115 self.fold_binders(
116 &mut |ty, binders| match ty.kind(&Interner) {
117 TyKind::BoundVar(bound) if bound.debruijn >= binders => {
118 TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone()))
119 .intern(&Interner)
120 }
121 _ => ty,
122 },
123 DebruijnIndex::INNERMOST,
124 )
125 }
126}
127
128impl TypeWalk for Ty {
129 fn walk(&self, f: &mut impl FnMut(&Ty)) {
130 match self.kind(&Interner) {
131 TyKind::Alias(AliasTy::Projection(p_ty)) => {
132 for t in p_ty.substitution.iter(&Interner) {
133 t.walk(f);
134 }
135 }
136 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
137 for t in o_ty.substitution.iter(&Interner) {
138 t.walk(f);
139 }
140 }
141 TyKind::Dyn(dyn_ty) => {
142 for p in dyn_ty.bounds.value.interned().iter() {
143 p.walk(f);
144 }
145 }
146 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
147 ty.walk(f);
148 }
149 _ => {
150 if let Some(substs) = self.substs() {
151 for t in substs.iter(&Interner) {
152 t.walk(f);
153 }
154 }
155 }
156 }
157 f(self);
158 }
159
160 fn walk_mut_binders(
161 &mut self,
162 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
163 binders: DebruijnIndex,
164 ) {
165 match self.interned_mut() {
166 TyKind::Alias(AliasTy::Projection(p_ty)) => {
167 p_ty.substitution.walk_mut_binders(f, binders);
168 }
169 TyKind::Dyn(dyn_ty) => {
170 for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) {
171 p.walk_mut_binders(f, binders.shifted_in());
172 }
173 }
174 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
175 o_ty.substitution.walk_mut_binders(f, binders);
176 }
177 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => {
178 ty.walk_mut_binders(f, binders);
179 }
180 _ => {
181 if let Some(substs) = self.substs_mut() {
182 substs.walk_mut_binders(f, binders);
183 }
184 }
185 }
186 f(self, binders);
187 }
188}
189
190impl<T: TypeWalk> TypeWalk for Vec<T> {
191 fn walk(&self, f: &mut impl FnMut(&Ty)) {
192 for t in self {
193 t.walk(f);
194 }
195 }
196 fn walk_mut_binders(
197 &mut self,
198 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
199 binders: DebruijnIndex,
200 ) {
201 for t in self {
202 t.walk_mut_binders(f, binders);
203 }
204 }
205}
206
207impl TypeWalk for OpaqueTy {
208 fn walk(&self, f: &mut impl FnMut(&Ty)) {
209 self.substitution.walk(f);
210 }
211
212 fn walk_mut_binders(
213 &mut self,
214 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
215 binders: DebruijnIndex,
216 ) {
217 self.substitution.walk_mut_binders(f, binders);
218 }
219}
220
221impl TypeWalk for ProjectionTy {
222 fn walk(&self, f: &mut impl FnMut(&Ty)) {
223 self.substitution.walk(f);
224 }
225
226 fn walk_mut_binders(
227 &mut self,
228 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
229 binders: DebruijnIndex,
230 ) {
231 self.substitution.walk_mut_binders(f, binders);
232 }
233}
234
235impl TypeWalk for AliasTy {
236 fn walk(&self, f: &mut impl FnMut(&Ty)) {
237 match self {
238 AliasTy::Projection(it) => it.walk(f),
239 AliasTy::Opaque(it) => it.walk(f),
240 }
241 }
242
243 fn walk_mut_binders(
244 &mut self,
245 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
246 binders: DebruijnIndex,
247 ) {
248 match self {
249 AliasTy::Projection(it) => it.walk_mut_binders(f, binders),
250 AliasTy::Opaque(it) => it.walk_mut_binders(f, binders),
251 }
252 }
253}
254
255impl TypeWalk for GenericArg {
256 fn walk(&self, f: &mut impl FnMut(&Ty)) {
257 match &self.interned() {
258 GenericArgData::Ty(ty) => {
259 ty.walk(f);
260 }
261 }
262 }
263
264 fn walk_mut_binders(
265 &mut self,
266 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
267 binders: DebruijnIndex,
268 ) {
269 match self.interned_mut() {
270 GenericArgData::Ty(ty) => {
271 ty.walk_mut_binders(f, binders);
272 }
273 }
274 }
275}
276
277impl TypeWalk for Substitution {
278 fn walk(&self, f: &mut impl FnMut(&Ty)) {
279 for t in self.iter(&Interner) {
280 t.walk(f);
281 }
282 }
283
284 fn walk_mut_binders(
285 &mut self,
286 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
287 binders: DebruijnIndex,
288 ) {
289 for t in self.interned_mut() {
290 t.walk_mut_binders(f, binders);
291 }
292 }
293}
294
295impl<T: TypeWalk> TypeWalk for Binders<T> {
296 fn walk(&self, f: &mut impl FnMut(&Ty)) {
297 self.value.walk(f);
298 }
299
300 fn walk_mut_binders(
301 &mut self,
302 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
303 binders: DebruijnIndex,
304 ) {
305 self.value.walk_mut_binders(f, binders.shifted_in())
306 }
307}
308
309impl TypeWalk for TraitRef {
310 fn walk(&self, f: &mut impl FnMut(&Ty)) {
311 self.substitution.walk(f);
312 }
313
314 fn walk_mut_binders(
315 &mut self,
316 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
317 binders: DebruijnIndex,
318 ) {
319 self.substitution.walk_mut_binders(f, binders);
320 }
321}
322
323impl TypeWalk for WhereClause {
324 fn walk(&self, f: &mut impl FnMut(&Ty)) {
325 match self {
326 WhereClause::Implemented(trait_ref) => trait_ref.walk(f),
327 WhereClause::AliasEq(alias_eq) => alias_eq.walk(f),
328 }
329 }
330
331 fn walk_mut_binders(
332 &mut self,
333 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
334 binders: DebruijnIndex,
335 ) {
336 match self {
337 WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders),
338 WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders),
339 }
340 }
341}
342
343impl TypeWalk for CallableSig {
344 fn walk(&self, f: &mut impl FnMut(&Ty)) {
345 for t in self.params_and_return.iter() {
346 t.walk(f);
347 }
348 }
349
350 fn walk_mut_binders(
351 &mut self,
352 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
353 binders: DebruijnIndex,
354 ) {
355 for t in make_mut_slice(&mut self.params_and_return) {
356 t.walk_mut_binders(f, binders);
357 }
358 }
359}
360
361impl TypeWalk for AliasEq {
362 fn walk(&self, f: &mut impl FnMut(&Ty)) {
363 self.ty.walk(f);
364 match &self.alias {
365 AliasTy::Projection(projection_ty) => projection_ty.walk(f),
366 AliasTy::Opaque(opaque) => opaque.walk(f),
367 }
368 }
369
370 fn walk_mut_binders(
371 &mut self,
372 f: &mut impl FnMut(&mut Ty, DebruijnIndex),
373 binders: DebruijnIndex,
374 ) {
375 self.ty.walk_mut_binders(f, binders);
376 match &mut self.alias {
377 AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders),
378 AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders),
379 }
380 }
381}