aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/display.rs4
-rw-r--r--crates/hir/src/lib.rs35
-rw-r--r--crates/hir_ty/src/autoderef.rs38
-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/diagnostics/expr.rs4
-rw-r--r--crates/hir_ty/src/display.rs8
-rw-r--r--crates/hir_ty/src/infer.rs15
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs102
-rw-r--r--crates/hir_ty/src/infer/pat.rs26
-rw-r--r--crates/hir_ty/src/infer/path.rs25
-rw-r--r--crates/hir_ty/src/infer/unify.rs13
-rw-r--r--crates/hir_ty/src/lib.rs158
-rw-r--r--crates/hir_ty/src/lower.rs49
-rw-r--r--crates/hir_ty/src/method_resolution.rs14
-rw-r--r--crates/hir_ty/src/op.rs4
-rw-r--r--crates/hir_ty/src/traits/chalk.rs14
-rw-r--r--crates/hir_ty/src/utils.rs24
-rw-r--r--crates/ide/src/inlay_hints.rs2
-rw-r--r--crates/ide_assists/src/handlers/convert_into_to_from.rs355
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs32
-rw-r--r--crates/ide_db/src/helpers.rs4
-rw-r--r--crates/ide_db/src/helpers/famous_defs_fixture.rs6
25 files changed, 821 insertions, 374 deletions
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs
index 559ea31a0..993772aac 100644
--- a/crates/hir/src/display.rs
+++ b/crates/hir/src/display.rs
@@ -13,7 +13,7 @@ use syntax::ast::{self, NameOwner};
13 13
14use crate::{ 14use crate::{
15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, 15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
16 Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, 16 Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant,
17}; 17};
18 18
19impl HirDisplay for Function { 19impl HirDisplay for Function {
@@ -234,7 +234,7 @@ impl HirDisplay for TypeParam {
234 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 234 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
235 write!(f, "{}", self.name(f.db))?; 235 write!(f, "{}", self.name(f.db))?;
236 let bounds = f.db.generic_predicates_for_param(self.id); 236 let bounds = f.db.generic_predicates_for_param(self.id);
237 let substs = Substitution::type_params(f.db, self.id.parent); 237 let substs = TyBuilder::type_params_subst(f.db, self.id.parent);
238 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); 238 let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>();
239 if !(predicates.is_empty() || f.omit_verbose_types()) { 239 if !(predicates.is_empty() || f.omit_verbose_types()) {
240 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; 240 write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?;
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index eb19e4b51..19901ed33 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -55,11 +55,10 @@ use hir_ty::{
55 autoderef, could_unify, 55 autoderef, could_unify,
56 method_resolution::{self, TyFingerprint}, 56 method_resolution::{self, TyFingerprint},
57 primitive::UintTy, 57 primitive::UintTy,
58 to_assoc_type_id,
59 traits::{FnTrait, Solution, SolutionVariables}, 58 traits::{FnTrait, Solution, SolutionVariables},
60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
61 DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, 60 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Substitution,
62 Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, 61 TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause,
63}; 62};
64use itertools::Itertools; 63use itertools::Itertools;
65use rustc_hash::FxHashSet; 64use rustc_hash::FxHashSet;
@@ -515,7 +514,7 @@ impl Field {
515 VariantDef::Union(it) => it.id.into(), 514 VariantDef::Union(it) => it.id.into(),
516 VariantDef::Variant(it) => it.parent.id.into(), 515 VariantDef::Variant(it) => it.parent.id.into(),
517 }; 516 };
518 let substs = Substitution::type_params(db, generic_def_id); 517 let substs = TyBuilder::type_params_subst(db, generic_def_id);
519 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 518 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
520 Type::new(db, self.parent.module(db).id.krate(), var_id, ty) 519 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
521 } 520 }
@@ -1129,7 +1128,7 @@ pub struct BuiltinType {
1129impl BuiltinType { 1128impl BuiltinType {
1130 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { 1129 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
1131 let resolver = module.id.resolver(db.upcast()); 1130 let resolver = module.id.resolver(db.upcast());
1132 Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) 1131 Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
1133 .expect("crate not present in resolver") 1132 .expect("crate not present in resolver")
1134 } 1133 }
1135 1134
@@ -1502,7 +1501,7 @@ impl TypeParam {
1502 let resolver = self.id.parent.resolver(db.upcast()); 1501 let resolver = self.id.parent.resolver(db.upcast());
1503 let krate = self.id.parent.module(db.upcast()).krate(); 1502 let krate = self.id.parent.module(db.upcast()).krate();
1504 let ty = params.get(local_idx)?.clone(); 1503 let ty = params.get(local_idx)?.clone();
1505 let subst = Substitution::type_params(db, self.id.parent); 1504 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1506 let ty = ty.subst(&subst.prefix(local_idx)); 1505 let ty = ty.subst(&subst.prefix(local_idx));
1507 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1506 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1508 } 1507 }
@@ -1703,10 +1702,9 @@ impl Type {
1703 fn from_def( 1702 fn from_def(
1704 db: &dyn HirDatabase, 1703 db: &dyn HirDatabase,
1705 krate: CrateId, 1704 krate: CrateId,
1706 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, 1705 def: impl HasResolver + Into<TyDefId>,
1707 ) -> Type { 1706 ) -> Type {
1708 let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); 1707 let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
1709 let ty = db.ty(def.into()).subst(&substs);
1710 Type::new(db, krate, def, ty) 1708 Type::new(db, krate, def, ty)
1711 } 1709 }
1712 1710
@@ -1785,13 +1783,10 @@ impl Type {
1785 } 1783 }
1786 1784
1787 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1785 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1788 let trait_ref = hir_ty::TraitRef { 1786 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
1789 trait_id: hir_ty::to_chalk_trait_id(trait_.id), 1787 .push(self.ty.clone())
1790 substitution: Substitution::build_for_def(db, trait_.id) 1788 .fill(args.iter().map(|t| t.ty.clone()))
1791 .push(self.ty.clone()) 1789 .build();
1792 .fill(args.iter().map(|t| t.ty.clone()))
1793 .build(),
1794 };
1795 1790
1796 let goal = Canonical { 1791 let goal = Canonical {
1797 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), 1792 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@@ -1804,11 +1799,10 @@ impl Type {
1804 pub fn normalize_trait_assoc_type( 1799 pub fn normalize_trait_assoc_type(
1805 &self, 1800 &self,
1806 db: &dyn HirDatabase, 1801 db: &dyn HirDatabase,
1807 trait_: Trait,
1808 args: &[Type], 1802 args: &[Type],
1809 alias: TypeAlias, 1803 alias: TypeAlias,
1810 ) -> Option<Type> { 1804 ) -> Option<Type> {
1811 let subst = Substitution::build_for_def(db, trait_.id) 1805 let projection = TyBuilder::assoc_type_projection(db, alias.id)
1812 .push(self.ty.clone()) 1806 .push(self.ty.clone())
1813 .fill(args.iter().map(|t| t.ty.clone())) 1807 .fill(args.iter().map(|t| t.ty.clone()))
1814 .build(); 1808 .build();
@@ -1816,10 +1810,7 @@ impl Type {
1816 InEnvironment::new( 1810 InEnvironment::new(
1817 self.env.env.clone(), 1811 self.env.env.clone(),
1818 AliasEq { 1812 AliasEq {
1819 alias: AliasTy::Projection(ProjectionTy { 1813 alias: AliasTy::Projection(projection),
1820 associated_ty_id: to_assoc_type_id(alias.id),
1821 substitution: subst,
1822 }),
1823 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 1814 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
1824 .intern(&Interner), 1815 .intern(&Interner),
1825 } 1816 }
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index c859f9491..70c56cc45 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -13,11 +13,9 @@ use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase,
16 to_assoc_type_id, to_chalk_trait_id,
17 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
18 utils::generics, 17 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, 18 TyBuilder, TyKind,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 19};
22 20
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 21const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +55,20 @@ fn deref_by_trait(
57 }; 55 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 56 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 57
60 let generic_params = generics(db.upcast(), target.into()); 58 let projection = {
61 if generic_params.len() != 1 { 59 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 60 if b.remaining() != 1 {
63 // namely Deref's Self type 61 // the Target type + Deref trait should only have one generic parameter,
64 return None; 62 // namely Deref's Self type
65 } 63 return None;
64 }
65 b.push(ty.goal.value.clone()).build()
66 };
66 67
67 // FIXME make the Canonical / bound var handling nicer 68 // FIXME make the Canonical / bound var handling nicer
68 69
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 70 // Check that the type implements Deref at all
73 let trait_ref = 71 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 { 72 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 73 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 74 value: InEnvironment {
@@ -84,11 +81,8 @@ fn deref_by_trait(
84 } 81 }
85 82
86 // Now do the assoc type projection 83 // Now do the assoc type projection
87 let projection = AliasEq { 84 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 85 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 86 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 87 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 88 ty.goal.binders.len(&Interner),
@@ -96,9 +90,7 @@ fn deref_by_trait(
96 .intern(&Interner), 90 .intern(&Interner),
97 }; 91 };
98 92
99 let obligation = projection.cast(&Interner); 93 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 94
103 let canonical = Canonical { 95 let canonical = Canonical {
104 value: in_env, 96 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..4a9a8058f
--- /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(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(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/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/display.rs b/crates/hir_ty/src/display.rs
index 97f1092c6..385bd9405 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> {
@@ -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,
@@ -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)?;
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index b871594bd..1b1d4458c 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -38,11 +38,11 @@ use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{DomainGoal, Guidance, Solution}, 40 traits::{DomainGoal, Guidance, Solution},
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, 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..028a4d568 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, traits::Solution, Interner, 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..c584a2c08 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, InEnvironment},
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, Interner, Rawness, Scalar, Substitution,
26 Substitution, TraitRef, Ty, TyKind, 26 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)
@@ -539,17 +534,10 @@ impl<'a> InferenceContext<'a> {
539 Expr::Box { expr } => { 534 Expr::Box { expr } => {
540 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); 535 let inner_ty = self.infer_expr_inner(*expr, &Expectation::none());
541 if let Some(box_) = self.resolve_boxed_box() { 536 if let Some(box_) = self.resolve_boxed_box() {
542 let mut sb = 537 TyBuilder::adt(self.db, box_)
543 Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); 538 .push(inner_ty)
544 sb = sb.push(inner_ty); 539 .fill_with_defaults(self.db, || self.table.new_type_var())
545 match self.db.generic_defaults(box_.into()).get(1) { 540 .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 { 541 } else {
554 self.err_ty() 542 self.err_ty()
555 } 543 }
@@ -639,31 +627,31 @@ impl<'a> InferenceContext<'a> {
639 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); 627 let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect));
640 match (range_type, lhs_ty, rhs_ty) { 628 match (range_type, lhs_ty, rhs_ty) {
641 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { 629 (RangeOp::Exclusive, None, None) => match self.resolve_range_full() {
642 Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), 630 Some(adt) => TyBuilder::adt(self.db, adt).build(),
643 None => self.err_ty(), 631 None => self.err_ty(),
644 }, 632 },
645 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { 633 (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() {
646 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 634 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
647 None => self.err_ty(), 635 None => self.err_ty(),
648 }, 636 },
649 (RangeOp::Inclusive, None, Some(ty)) => { 637 (RangeOp::Inclusive, None, Some(ty)) => {
650 match self.resolve_range_to_inclusive() { 638 match self.resolve_range_to_inclusive() {
651 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 639 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
652 None => self.err_ty(), 640 None => self.err_ty(),
653 } 641 }
654 } 642 }
655 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { 643 (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() {
656 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 644 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
657 None => self.err_ty(), 645 None => self.err_ty(),
658 }, 646 },
659 (RangeOp::Inclusive, Some(_), Some(ty)) => { 647 (RangeOp::Inclusive, Some(_), Some(ty)) => {
660 match self.resolve_range_inclusive() { 648 match self.resolve_range_inclusive() {
661 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 649 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
662 None => self.err_ty(), 650 None => self.err_ty(),
663 } 651 }
664 } 652 }
665 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { 653 (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() {
666 Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), 654 Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(),
667 None => self.err_ty(), 655 None => self.err_ty(),
668 }, 656 },
669 (RangeOp::Inclusive, _, None) => self.err_ty(), 657 (RangeOp::Inclusive, _, None) => self.err_ty(),
@@ -828,8 +816,8 @@ impl<'a> InferenceContext<'a> {
828 // we don't even make an attempt at coercion 816 // we don't even make an attempt at coercion
829 self.table.new_maybe_never_var() 817 self.table.new_maybe_never_var()
830 } else { 818 } else {
831 self.coerce(&Ty::unit(), &expected.coercion_target()); 819 self.coerce(&TyBuilder::unit(), &expected.coercion_target());
832 Ty::unit() 820 TyBuilder::unit()
833 } 821 }
834 }; 822 };
835 ty 823 ty
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 10df8d8cb..5b70d5e5a 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> {
@@ -246,23 +245,12 @@ impl<'a> InferenceContext<'a> {
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..671ea355f 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(&Interner)[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..a04b935ef 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)]
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index 4c3d904bf..a8c87eadf 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -14,6 +14,8 @@ 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;
17 19
18pub mod display; 20pub mod display;
19pub mod db; 21pub mod db;
@@ -24,24 +26,27 @@ mod tests;
24#[cfg(test)] 26#[cfg(test)]
25mod test_db; 27mod test_db;
26 28
27use std::{iter, mem, sync::Arc}; 29use std::{mem, sync::Arc};
28 30
29use base_db::salsa;
30use chalk_ir::cast::{CastTo, Caster}; 31use 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; 32use itertools::Itertools;
36use smallvec::SmallVec; 33use smallvec::SmallVec;
37 34
35use base_db::salsa;
36use hir_def::{
37 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule,
38 LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
39};
40
38use crate::{ 41use crate::{
39 db::HirDatabase, 42 db::HirDatabase,
40 display::HirDisplay, 43 display::HirDisplay,
41 utils::{generics, make_mut_slice, Generics}, 44 utils::{generics, make_mut_slice},
42}; 45};
43 46
44pub use autoderef::autoderef; 47pub use autoderef::autoderef;
48pub use builder::TyBuilder;
49pub use chalk_ext::TyExt;
45pub use infer::{could_unify, InferenceResult, InferenceVar}; 50pub use infer::{could_unify, InferenceResult, InferenceVar};
46pub use lower::{ 51pub use lower::{
47 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, 52 associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode,
@@ -457,51 +462,6 @@ impl Substitution {
457 ) -> Self { 462 ) -> Self {
458 Substitution(elements.into_iter().casted(interner).collect()) 463 Substitution(elements.into_iter().casted(interner).collect())
459 } 464 }
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 )
489 }
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} 465}
506 466
507/// Return an index of a parameter in the generic type parameter list by it's id. 467/// Return an index of a parameter in the generic type parameter list by it's id.
@@ -509,52 +469,6 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> {
509 generics(db.upcast(), id.parent).param_idx(id) 469 generics(db.upcast(), id.parent).param_idx(id)
510} 470}
511 471
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)] 472#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
559pub struct Binders<T> { 473pub struct Binders<T> {
560 pub num_binders: usize, 474 pub num_binders: usize,
@@ -760,7 +674,7 @@ impl CallableSig {
760 674
761 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { 675 pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig {
762 CallableSig { 676 CallableSig {
763 // FIXME: what to do about lifetime params? 677 // FIXME: what to do about lifetime params? -> return PolyFnSig
764 params_and_return: fn_ptr 678 params_and_return: fn_ptr
765 .substs 679 .substs
766 .clone() 680 .clone()
@@ -773,16 +687,6 @@ impl CallableSig {
773 } 687 }
774 } 688 }
775 689
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] { 690 pub fn params(&self) -> &[Ty] {
787 &self.params_and_return[0..self.params_and_return.len() - 1] 691 &self.params_and_return[0..self.params_and_return.len() - 1]
788 } 692 }
@@ -811,40 +715,6 @@ impl TypeWalk for CallableSig {
811} 715}
812 716
813impl Ty { 717impl 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)> { 718 pub fn as_reference(&self) -> Option<(&Ty, Mutability)> {
849 match self.kind(&Interner) { 719 match self.kind(&Interner) {
850 TyKind::Ref(mutability, ty) => Some((ty, *mutability)), 720 TyKind::Ref(mutability, ty) => Some((ty, *mutability)),
@@ -1068,7 +938,7 @@ impl Ty {
1068 let param_data = &generic_params.types[id.local_id]; 938 let param_data = &generic_params.types[id.local_id];
1069 match param_data.provenance { 939 match param_data.provenance {
1070 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { 940 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
1071 let substs = Substitution::type_params(db, id.parent); 941 let substs = TyBuilder::type_params_subst(db, id.parent);
1072 let predicates = db 942 let predicates = db
1073 .generic_predicates(id.parent) 943 .generic_predicates(id.parent)
1074 .into_iter() 944 .into_iter()
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index e60d7c730..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);
@@ -1061,7 +1053,7 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig {
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 c093fce20..a76586f0c 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
@@ -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()
@@ -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/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/utils.rs b/crates/hir_ty/src/utils.rs
index 42d7af146..b23e91b1b 100644
--- a/crates/hir_ty/src/utils.rs
+++ b/crates/hir_ty/src/utils.rs
@@ -2,7 +2,7 @@
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,
@@ -16,7 +16,7 @@ use hir_def::{
16}; 16};
17use hir_expand::name::{name, Name}; 17use hir_expand::name::{name, Name};
18 18
19use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; 19use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause};
20 20
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> {
22 let resolver = trait_.resolver(db); 22 let resolver = trait_.resolver(db);
@@ -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/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs
index f73edf8b6..d5ef054d8 100644
--- a/crates/ide/src/inlay_hints.rs
+++ b/crates/ide/src/inlay_hints.rs
@@ -234,7 +234,7 @@ fn hint_iterator(
234 hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), 234 hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias),
235 _ => None, 235 _ => None,
236 })?; 236 })?;
237 if let Some(ty) = ty.normalize_trait_assoc_type(db, iter_trait, &[], assoc_type_item) { 237 if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) {
238 const LABEL_START: &str = "impl Iterator<Item = "; 238 const LABEL_START: &str = "impl Iterator<Item = ";
239 const LABEL_END: &str = ">"; 239 const LABEL_END: &str = ">";
240 240
diff --git a/crates/ide_assists/src/handlers/convert_into_to_from.rs b/crates/ide_assists/src/handlers/convert_into_to_from.rs
new file mode 100644
index 000000000..199e1ad5c
--- /dev/null
+++ b/crates/ide_assists/src/handlers/convert_into_to_from.rs
@@ -0,0 +1,355 @@
1use ide_db::{
2 helpers::{mod_path_to_ast, FamousDefs},
3 traits::resolve_target_trait,
4};
5use syntax::ast::{self, AstNode, NameOwner};
6
7use crate::{AssistContext, AssistId, AssistKind, Assists};
8
9// Assist: convert_into_to_from
10//
11// Converts an Into impl to an equivalent From impl.
12//
13// ```
14// # //- /lib.rs crate:core
15// # pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
16// # //- /lib.rs crate:main deps:core
17// # use core::convert::Into;
18// impl $0Into<Thing> for usize {
19// fn into(self) -> Thing {
20// Thing {
21// b: self.to_string(),
22// a: self
23// }
24// }
25// }
26// ```
27// ->
28// ```
29// # use core::convert::Into;
30// impl From<usize> for Thing {
31// fn from(val: usize) -> Self {
32// Thing {
33// b: val.to_string(),
34// a: val
35// }
36// }
37// }
38// ```
39pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let impl_ = ctx.find_node_at_offset::<ast::Impl>()?;
41 let src_type = impl_.self_ty()?;
42 let ast_trait = impl_.trait_()?;
43
44 let module = ctx.sema.scope(impl_.syntax()).module()?;
45
46 let trait_ = resolve_target_trait(&ctx.sema, &impl_)?;
47 if trait_ != FamousDefs(&ctx.sema, Some(module.krate())).core_convert_Into()? {
48 return None;
49 }
50
51 let src_type_path = {
52 let src_type_path = src_type.syntax().descendants().find_map(ast::Path::cast)?;
53 let src_type_def = match ctx.sema.resolve_path(&src_type_path) {
54 Some(hir::PathResolution::Def(module_def)) => module_def,
55 _ => return None,
56 };
57
58 mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def)?)
59 };
60
61 let dest_type = match &ast_trait {
62 ast::Type::PathType(path) => {
63 path.path()?.segment()?.generic_arg_list()?.generic_args().next()?
64 }
65 _ => return None,
66 };
67
68 let into_fn = impl_.assoc_item_list()?.assoc_items().find_map(|item| {
69 if let ast::AssocItem::Fn(f) = item {
70 if f.name()?.text() == "into" {
71 return Some(f);
72 }
73 };
74 None
75 })?;
76
77 let into_fn_name = into_fn.name()?;
78 let into_fn_params = into_fn.param_list()?;
79 let into_fn_return = into_fn.ret_type()?;
80
81 let selfs = into_fn
82 .body()?
83 .syntax()
84 .descendants()
85 .filter_map(ast::NameRef::cast)
86 .filter(|name| name.text() == "self" || name.text() == "Self");
87
88 acc.add(
89 AssistId("convert_into_to_from", AssistKind::RefactorRewrite),
90 "Convert Into to From",
91 impl_.syntax().text_range(),
92 |builder| {
93 builder.replace(src_type.syntax().text_range(), dest_type.to_string());
94 builder.replace(ast_trait.syntax().text_range(), format!("From<{}>", src_type));
95 builder.replace(into_fn_return.syntax().text_range(), "-> Self");
96 builder.replace(
97 into_fn_params.syntax().text_range(),
98 format!("(val: {})", src_type.to_string()),
99 );
100 builder.replace(into_fn_name.syntax().text_range(), "from");
101
102 for s in selfs {
103 match s.text().as_ref() {
104 "self" => builder.replace(s.syntax().text_range(), "val"),
105 "Self" => builder.replace(s.syntax().text_range(), src_type_path.to_string()),
106 _ => {}
107 }
108 }
109 },
110 )
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 use crate::tests::check_assist;
118
119 #[test]
120 fn convert_into_to_from_converts_a_struct() {
121 check_convert_into_to_from(
122 r#"
123struct Thing {
124 a: String,
125 b: usize
126}
127
128impl $0core::convert::Into<Thing> for usize {
129 fn into(self) -> Thing {
130 Thing {
131 b: self.to_string(),
132 a: self
133 }
134 }
135}
136"#,
137 r#"
138struct Thing {
139 a: String,
140 b: usize
141}
142
143impl From<usize> for Thing {
144 fn from(val: usize) -> Self {
145 Thing {
146 b: val.to_string(),
147 a: val
148 }
149 }
150}
151"#,
152 )
153 }
154
155 #[test]
156 fn convert_into_to_from_converts_enums() {
157 check_convert_into_to_from(
158 r#"
159enum Thing {
160 Foo(String),
161 Bar(String)
162}
163
164impl $0core::convert::Into<String> for Thing {
165 fn into(self) -> String {
166 match self {
167 Self::Foo(s) => s,
168 Self::Bar(s) => s
169 }
170 }
171}
172"#,
173 r#"
174enum Thing {
175 Foo(String),
176 Bar(String)
177}
178
179impl From<Thing> for String {
180 fn from(val: Thing) -> Self {
181 match val {
182 Thing::Foo(s) => s,
183 Thing::Bar(s) => s
184 }
185 }
186}
187"#,
188 )
189 }
190
191 #[test]
192 fn convert_into_to_from_on_enum_with_lifetimes() {
193 check_convert_into_to_from(
194 r#"
195enum Thing<'a> {
196 Foo(&'a str),
197 Bar(&'a str)
198}
199
200impl<'a> $0core::convert::Into<&'a str> for Thing<'a> {
201 fn into(self) -> &'a str {
202 match self {
203 Self::Foo(s) => s,
204 Self::Bar(s) => s
205 }
206 }
207}
208"#,
209 r#"
210enum Thing<'a> {
211 Foo(&'a str),
212 Bar(&'a str)
213}
214
215impl<'a> From<Thing<'a>> for &'a str {
216 fn from(val: Thing<'a>) -> Self {
217 match val {
218 Thing::Foo(s) => s,
219 Thing::Bar(s) => s
220 }
221 }
222}
223"#,
224 )
225 }
226
227 #[test]
228 fn convert_into_to_from_works_on_references() {
229 check_convert_into_to_from(
230 r#"
231struct Thing(String);
232
233impl $0core::convert::Into<String> for &Thing {
234 fn into(self) -> Thing {
235 self.0.clone()
236 }
237}
238"#,
239 r#"
240struct Thing(String);
241
242impl From<&Thing> for String {
243 fn from(val: &Thing) -> Self {
244 val.0.clone()
245 }
246}
247"#,
248 )
249 }
250
251 #[test]
252 fn convert_into_to_from_works_on_qualified_structs() {
253 check_convert_into_to_from(
254 r#"
255mod things {
256 pub struct Thing(String);
257 pub struct BetterThing(String);
258}
259
260impl $0core::convert::Into<things::BetterThing> for &things::Thing {
261 fn into(self) -> Thing {
262 things::BetterThing(self.0.clone())
263 }
264}
265"#,
266 r#"
267mod things {
268 pub struct Thing(String);
269 pub struct BetterThing(String);
270}
271
272impl From<&things::Thing> for things::BetterThing {
273 fn from(val: &things::Thing) -> Self {
274 things::BetterThing(val.0.clone())
275 }
276}
277"#,
278 )
279 }
280
281 #[test]
282 fn convert_into_to_from_works_on_qualified_enums() {
283 check_convert_into_to_from(
284 r#"
285mod things {
286 pub enum Thing {
287 A(String)
288 }
289 pub struct BetterThing {
290 B(String)
291 }
292}
293
294impl $0core::convert::Into<things::BetterThing> for &things::Thing {
295 fn into(self) -> Thing {
296 match self {
297 Self::A(s) => things::BetterThing::B(s)
298 }
299 }
300}
301"#,
302 r#"
303mod things {
304 pub enum Thing {
305 A(String)
306 }
307 pub struct BetterThing {
308 B(String)
309 }
310}
311
312impl From<&things::Thing> for things::BetterThing {
313 fn from(val: &things::Thing) -> Self {
314 match val {
315 things::Thing::A(s) => things::BetterThing::B(s)
316 }
317 }
318}
319"#,
320 )
321 }
322
323 #[test]
324 fn convert_into_to_from_not_applicable_on_any_trait_named_into() {
325 check_assist_not_applicable(
326 r#"
327pub trait Into<T> {{
328 pub fn into(self) -> T;
329}}
330
331struct Thing {
332 a: String,
333}
334
335impl $0Into<Thing> for String {
336 fn into(self) -> Thing {
337 Thing {
338 a: self
339 }
340 }
341}
342"#,
343 );
344 }
345
346 fn check_convert_into_to_from(before: &str, after: &str) {
347 let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
348 check_assist(convert_into_to_from, before, after);
349 }
350
351 fn check_assist_not_applicable(before: &str) {
352 let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
353 crate::tests::check_assist_not_applicable(convert_into_to_from, before);
354 }
355}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 3d1dcef4c..3e2c82dac 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -117,6 +117,7 @@ mod handlers {
117 mod convert_integer_literal; 117 mod convert_integer_literal;
118 mod convert_comment_block; 118 mod convert_comment_block;
119 mod convert_iter_for_each_to_for; 119 mod convert_iter_for_each_to_for;
120 mod convert_into_to_from;
120 mod early_return; 121 mod early_return;
121 mod expand_glob_import; 122 mod expand_glob_import;
122 mod extract_function; 123 mod extract_function;
@@ -185,6 +186,7 @@ mod handlers {
185 convert_integer_literal::convert_integer_literal, 186 convert_integer_literal::convert_integer_literal,
186 convert_comment_block::convert_comment_block, 187 convert_comment_block::convert_comment_block,
187 convert_iter_for_each_to_for::convert_iter_for_each_to_for, 188 convert_iter_for_each_to_for::convert_iter_for_each_to_for,
189 convert_into_to_from::convert_into_to_from,
188 early_return::convert_to_guarded_return, 190 early_return::convert_to_guarded_return,
189 expand_glob_import::expand_glob_import, 191 expand_glob_import::expand_glob_import,
190 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 192 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 03b7fb366..27a22ca10 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -206,6 +206,38 @@ const _: i32 = 0b1010;
206} 206}
207 207
208#[test] 208#[test]
209fn doctest_convert_into_to_from() {
210 check_doc_test(
211 "convert_into_to_from",
212 r#####"
213//- /lib.rs crate:core
214pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
215//- /lib.rs crate:main deps:core
216use core::convert::Into;
217impl $0Into<Thing> for usize {
218 fn into(self) -> Thing {
219 Thing {
220 b: self.to_string(),
221 a: self
222 }
223 }
224}
225"#####,
226 r#####"
227use core::convert::Into;
228impl From<usize> for Thing {
229 fn from(val: usize) -> Self {
230 Thing {
231 b: val.to_string(),
232 a: val
233 }
234 }
235}
236"#####,
237 )
238}
239
240#[test]
209fn doctest_convert_iter_for_each_to_for() { 241fn doctest_convert_iter_for_each_to_for() {
210 check_doc_test( 242 check_doc_test(
211 "convert_iter_for_each_to_for", 243 "convert_iter_for_each_to_for",
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 9992a92bd..66798ea3a 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -93,6 +93,10 @@ impl FamousDefs<'_, '_> {
93 self.find_trait("core:convert:From") 93 self.find_trait("core:convert:From")
94 } 94 }
95 95
96 pub fn core_convert_Into(&self) -> Option<Trait> {
97 self.find_trait("core:convert:Into")
98 }
99
96 pub fn core_option_Option(&self) -> Option<Enum> { 100 pub fn core_option_Option(&self) -> Option<Enum> {
97 self.find_enum("core:option:Option") 101 self.find_enum("core:option:Option")
98 } 102 }
diff --git a/crates/ide_db/src/helpers/famous_defs_fixture.rs b/crates/ide_db/src/helpers/famous_defs_fixture.rs
index d3464ae17..4d79e064e 100644
--- a/crates/ide_db/src/helpers/famous_defs_fixture.rs
+++ b/crates/ide_db/src/helpers/famous_defs_fixture.rs
@@ -14,6 +14,10 @@ pub mod convert {
14 pub trait From<T> { 14 pub trait From<T> {
15 fn from(t: T) -> Self; 15 fn from(t: T) -> Self;
16 } 16 }
17
18 pub trait Into<T> {
19 pub fn into(self) -> T;
20 }
17} 21}
18 22
19pub mod default { 23pub mod default {
@@ -120,7 +124,7 @@ pub mod option {
120pub mod prelude { 124pub mod prelude {
121 pub use crate::{ 125 pub use crate::{
122 cmp::Ord, 126 cmp::Ord,
123 convert::From, 127 convert::{From, Into},
124 default::Default, 128 default::Default,
125 iter::{IntoIterator, Iterator}, 129 iter::{IntoIterator, Iterator},
126 ops::{Fn, FnMut, FnOnce}, 130 ops::{Fn, FnMut, FnOnce},