aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_ty/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_ty/src')
-rw-r--r--crates/hir_ty/src/builder.rs2
-rw-r--r--crates/hir_ty/src/chalk_ext.rs229
-rw-r--r--crates/hir_ty/src/db.rs6
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs4
-rw-r--r--crates/hir_ty/src/display.rs46
-rw-r--r--crates/hir_ty/src/infer.rs2
-rw-r--r--crates/hir_ty/src/infer/coerce.rs2
-rw-r--r--crates/hir_ty/src/infer/expr.rs22
-rw-r--r--crates/hir_ty/src/infer/pat.rs19
-rw-r--r--crates/hir_ty/src/infer/path.rs4
-rw-r--r--crates/hir_ty/src/infer/unify.rs4
-rw-r--r--crates/hir_ty/src/lib.rs237
-rw-r--r--crates/hir_ty/src/lower.rs4
-rw-r--r--crates/hir_ty/src/method_resolution.rs6
-rw-r--r--crates/hir_ty/src/traits/chalk.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs21
-rw-r--r--crates/hir_ty/src/types.rs4
-rw-r--r--crates/hir_ty/src/walk.rs10
19 files changed, 358 insertions, 268 deletions
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
index 791915fe0..09512d1ce 100644
--- a/crates/hir_ty/src/builder.rs
+++ b/crates/hir_ty/src/builder.rs
@@ -13,7 +13,7 @@ use smallvec::SmallVec;
13use crate::{ 13use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, 14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution, 15 CallableSig, FnPointer, FnSig, FnSubst, GenericArg, Interner, ProjectionTy, Substitution,
16 TraitRef, Ty, TyDefId, TyKind, TypeWalk, ValueTyDefId, 16 TraitRef, Ty, TyDefId, TyExt, TyKind, TypeWalk, ValueTyDefId,
17}; 17};
18 18
19/// This is a builder for `Ty` or anything that needs a `Substitution`. 19/// This is a builder for `Ty` or anything that needs a `Substitution`.
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
index 0f4cb43e9..8e8a1aa48 100644
--- a/crates/hir_ty/src/chalk_ext.rs
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -1,20 +1,243 @@
1//! Various extensions traits for Chalk types. 1//! Various extensions traits for Chalk types.
2 2
3use hir_def::{AssocContainerId, Lookup, TraitId}; 3use chalk_ir::Mutability;
4use hir_def::{
5 type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId,
6};
4 7
5use crate::{ 8use crate::{
6 db::HirDatabase, from_assoc_type_id, to_chalk_trait_id, Interner, ProjectionTy, TraitRef, Ty, 9 db::HirDatabase, from_assoc_type_id, from_chalk_trait_id, from_foreign_def_id,
7 TyKind, 10 from_placeholder_idx, to_chalk_trait_id, AdtId, AliasEq, AliasTy, Binders, CallableDefId,
11 CallableSig, ImplTraitId, Interner, Lifetime, ProjectionTy, QuantifiedWhereClause,
12 Substitution, TraitRef, Ty, TyBuilder, TyKind, WhereClause,
8}; 13};
9 14
10pub trait TyExt { 15pub trait TyExt {
11 fn is_unit(&self) -> bool; 16 fn is_unit(&self) -> bool;
17 fn is_never(&self) -> bool;
18 fn is_unknown(&self) -> bool;
19
20 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)>;
21 fn as_tuple(&self) -> Option<&Substitution>;
22 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId>;
23 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)>;
24 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)>;
25 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId>;
26
27 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId>;
28 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig>;
29
30 fn strip_references(&self) -> &Ty;
31
32 /// If this is a `dyn Trait`, returns that trait.
33 fn dyn_trait(&self) -> Option<TraitId>;
34
35 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>>;
36 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId>;
12} 37}
13 38
14impl TyExt for Ty { 39impl TyExt for Ty {
15 fn is_unit(&self) -> bool { 40 fn is_unit(&self) -> bool {
16 matches!(self.kind(&Interner), TyKind::Tuple(0, _)) 41 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
17 } 42 }
43
44 fn is_never(&self) -> bool {
45 matches!(self.kind(&Interner), TyKind::Never)
46 }
47
48 fn is_unknown(&self) -> bool {
49 matches!(self.kind(&Interner), TyKind::Error)
50 }
51
52 fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
53 match self.kind(&Interner) {
54 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
55 _ => None,
56 }
57 }
58
59 fn as_tuple(&self) -> Option<&Substitution> {
60 match self.kind(&Interner) {
61 TyKind::Tuple(_, substs) => Some(substs),
62 _ => None,
63 }
64 }
65
66 fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
67 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
68 Some(func)
69 } else {
70 None
71 }
72 }
73 fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
74 match self.kind(&Interner) {
75 TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
76 _ => None,
77 }
78 }
79
80 fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
81 match self.kind(&Interner) {
82 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
83 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
84 _ => None,
85 }
86 }
87
88 fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
89 match *self.kind(&Interner) {
90 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
91 TyKind::FnDef(callable, ..) => {
92 Some(db.lookup_intern_callable_def(callable.into()).into())
93 }
94 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
95 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
96 _ => None,
97 }
98 }
99
100 fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
101 match self.kind(&Interner) {
102 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
103 _ => None,
104 }
105 }
106
107 fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
108 match self.kind(&Interner) {
109 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
110 TyKind::FnDef(def, parameters) => {
111 let callable_def = db.lookup_intern_callable_def((*def).into());
112 let sig = db.callable_item_signature(callable_def);
113 Some(sig.substitute(&Interner, &parameters))
114 }
115 TyKind::Closure(.., substs) => {
116 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
117 sig_param.callable_sig(db)
118 }
119 _ => None,
120 }
121 }
122
123 fn dyn_trait(&self) -> Option<TraitId> {
124 let trait_ref = match self.kind(&Interner) {
125 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
126 match b.skip_binders() {
127 WhereClause::Implemented(trait_ref) => Some(trait_ref),
128 _ => None,
129 }
130 }),
131 _ => None,
132 }?;
133 Some(from_chalk_trait_id(trait_ref.trait_id))
134 }
135
136 fn strip_references(&self) -> &Ty {
137 let mut t: &Ty = self;
138 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
139 t = ty;
140 }
141 t
142 }
143
144 fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
145 match self.kind(&Interner) {
146 TyKind::OpaqueType(opaque_ty_id, ..) => {
147 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
148 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
149 let krate = def.module(db.upcast()).krate();
150 if let Some(future_trait) = db
151 .lang_item(krate, "future_trait".into())
152 .and_then(|item| item.as_trait())
153 {
154 // This is only used by type walking.
155 // Parameters will be walked outside, and projection predicate is not used.
156 // So just provide the Future trait.
157 let impl_bound = Binders::empty(
158 &Interner,
159 WhereClause::Implemented(TraitRef {
160 trait_id: to_chalk_trait_id(future_trait),
161 substitution: Substitution::empty(&Interner),
162 }),
163 );
164 Some(vec![impl_bound])
165 } else {
166 None
167 }
168 }
169 ImplTraitId::ReturnTypeImplTrait(..) => None,
170 }
171 }
172 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
173 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
174 {
175 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
176 db.return_type_impl_traits(func).map(|it| {
177 let data = (*it)
178 .as_ref()
179 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
180 data.substitute(&Interner, &opaque_ty.substitution)
181 })
182 }
183 // It always has an parameter for Future::Output type.
184 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
185 };
186
187 predicates.map(|it| it.into_value_and_skipped_binders().0)
188 }
189 TyKind::Placeholder(idx) => {
190 let id = from_placeholder_idx(db, *idx);
191 let generic_params = db.generic_params(id.parent);
192 let param_data = &generic_params.types[id.local_id];
193 match param_data.provenance {
194 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
195 let substs = TyBuilder::type_params_subst(db, id.parent);
196 let predicates = db
197 .generic_predicates(id.parent)
198 .into_iter()
199 .map(|pred| pred.clone().substitute(&Interner, &substs))
200 .filter(|wc| match &wc.skip_binders() {
201 WhereClause::Implemented(tr) => {
202 tr.self_type_parameter(&Interner) == self
203 }
204 WhereClause::AliasEq(AliasEq {
205 alias: AliasTy::Projection(proj),
206 ty: _,
207 }) => proj.self_type_parameter(&Interner) == self,
208 _ => false,
209 })
210 .collect::<Vec<_>>();
211
212 Some(predicates)
213 }
214 _ => None,
215 }
216 }
217 _ => None,
218 }
219 }
220
221 fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
222 match self.kind(&Interner) {
223 TyKind::AssociatedType(id, ..) => {
224 match from_assoc_type_id(*id).lookup(db.upcast()).container {
225 AssocContainerId::TraitId(trait_id) => Some(trait_id),
226 _ => None,
227 }
228 }
229 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
230 match from_assoc_type_id(projection_ty.associated_ty_id)
231 .lookup(db.upcast())
232 .container
233 {
234 AssocContainerId::TraitId(trait_id) => Some(trait_id),
235 _ => None,
236 }
237 }
238 _ => None,
239 }
240 }
18} 241}
19 242
20pub trait ProjectionTyExt { 243pub trait ProjectionTyExt {
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs
index 07510ae02..326c20240 100644
--- a/crates/hir_ty/src/db.rs
+++ b/crates/hir_ty/src/db.rs
@@ -88,6 +88,8 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> {
88 #[salsa::interned] 88 #[salsa::interned]
89 fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId; 89 fn intern_lifetime_param_id(&self, param_id: LifetimeParamId) -> InternedLifetimeParamId;
90 #[salsa::interned] 90 #[salsa::interned]
91 fn intern_const_param_id(&self, param_id: ConstParamId) -> InternedConstParamId;
92 #[salsa::interned]
91 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId; 93 fn intern_impl_trait_id(&self, id: ImplTraitId) -> InternedOpaqueTyId;
92 #[salsa::interned] 94 #[salsa::interned]
93 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId; 95 fn intern_closure(&self, id: (DefWithBodyId, ExprId)) -> InternedClosureId;
@@ -162,6 +164,10 @@ pub struct InternedLifetimeParamId(salsa::InternId);
162impl_intern_key!(InternedLifetimeParamId); 164impl_intern_key!(InternedLifetimeParamId);
163 165
164#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 166#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
167pub struct InternedConstParamId(salsa::InternId);
168impl_intern_key!(InternedConstParamId);
169
170#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
165pub struct InternedOpaqueTyId(salsa::InternId); 171pub struct InternedOpaqueTyId(salsa::InternId);
166impl_intern_key!(InternedOpaqueTyId); 172impl_intern_key!(InternedOpaqueTyId);
167 173
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 34291578a..e9762622f 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -227,7 +227,7 @@ use hir_def::{
227use la_arena::Idx; 227use la_arena::Idx;
228use smallvec::{smallvec, SmallVec}; 228use smallvec::{smallvec, SmallVec};
229 229
230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; 230use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind};
231 231
232#[derive(Debug, Clone, Copy)] 232#[derive(Debug, Clone, Copy)]
233/// Either a pattern from the source code being analyzed, represented as 233/// Either a pattern from the source code being analyzed, represented as
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index b5efe9df5..ed97dc0e3 100644
--- a/crates/hir_ty/src/diagnostics/unsafe_check.rs
+++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs
@@ -11,7 +11,9 @@ use hir_def::{
11}; 11};
12use hir_expand::diagnostics::DiagnosticSink; 12use hir_expand::diagnostics::DiagnosticSink;
13 13
14use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; 14use crate::{
15 db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind,
16};
15 17
16pub(super) struct UnsafeValidator<'a, 'b: 'a> { 18pub(super) struct UnsafeValidator<'a, 'b: 'a> {
17 owner: DefWithBodyId, 19 owner: DefWithBodyId,
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 22416c0cf..8fe4ed3fa 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -5,6 +5,7 @@ use std::{
5 fmt::{self, Debug}, 5 fmt::{self, Debug},
6}; 6};
7 7
8use chalk_ir::BoundVar;
8use hir_def::{ 9use hir_def::{
9 db::DefDatabase, 10 db::DefDatabase,
10 find_path, 11 find_path,
@@ -18,12 +19,12 @@ use hir_def::{
18use hir_expand::name::Name; 19use hir_expand::name::Name;
19 20
20use crate::{ 21use crate::{
21 db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, 22 const_from_placeholder_idx, db::HirDatabase, from_assoc_type_id, from_foreign_def_id,
22 lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id, traits::chalk::from_chalk, 23 from_placeholder_idx, lt_from_placeholder_idx, primitive, subst_prefix, to_assoc_type_id,
23 utils::generics, AdtId, AliasEq, AliasTy, CallableDefId, CallableSig, DomainGoal, GenericArg, 24 traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, CallableDefId,
24 ImplTraitId, Interner, Lifetime, LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, 25 CallableSig, Const, ConstValue, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime,
25 ProjectionTy, ProjectionTyExt, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, 26 LifetimeData, LifetimeOutlives, Mutability, OpaqueTy, ProjectionTy, ProjectionTyExt,
26 WhereClause, 27 QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause,
27}; 28};
28 29
29pub struct HirFormatter<'a> { 30pub struct HirFormatter<'a> {
@@ -290,6 +291,29 @@ impl HirDisplay for GenericArg {
290 } 291 }
291} 292}
292 293
294impl HirDisplay for Const {
295 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
296 let data = self.interned();
297 match data.value {
298 ConstValue::BoundVar(idx) => idx.hir_fmt(f),
299 ConstValue::InferenceVar(..) => write!(f, "_"),
300 ConstValue::Placeholder(idx) => {
301 let id = const_from_placeholder_idx(f.db, idx);
302 let generics = generics(f.db.upcast(), id.parent);
303 let param_data = &generics.params.consts[id.local_id];
304 write!(f, "{}", param_data.name)
305 }
306 ConstValue::Concrete(_) => write!(f, "_"),
307 }
308 }
309}
310
311impl HirDisplay for BoundVar {
312 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
313 write!(f, "?{}.{}", self.debruijn.depth(), self.index)
314 }
315}
316
293impl HirDisplay for Ty { 317impl HirDisplay for Ty {
294 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 318 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
295 if f.should_truncate() { 319 if f.should_truncate() {
@@ -309,10 +333,12 @@ impl HirDisplay for Ty {
309 t.hir_fmt(f)?; 333 t.hir_fmt(f)?;
310 write!(f, "]")?; 334 write!(f, "]")?;
311 } 335 }
312 TyKind::Array(t) => { 336 TyKind::Array(t, c) => {
313 write!(f, "[")?; 337 write!(f, "[")?;
314 t.hir_fmt(f)?; 338 t.hir_fmt(f)?;
315 write!(f, "; _]")?; 339 write!(f, "; ")?;
340 c.hir_fmt(f)?;
341 write!(f, "]")?;
316 } 342 }
317 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => { 343 TyKind::Raw(m, t) | TyKind::Ref(m, _, t) => {
318 let ty_display = 344 let ty_display =
@@ -617,7 +643,7 @@ impl HirDisplay for Ty {
617 } 643 }
618 } 644 }
619 } 645 }
620 TyKind::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index)?, 646 TyKind::BoundVar(idx) => idx.hir_fmt(f)?,
621 TyKind::Dyn(dyn_ty) => { 647 TyKind::Dyn(dyn_ty) => {
622 write_bounds_like_dyn_trait_with_prefix( 648 write_bounds_like_dyn_trait_with_prefix(
623 "dyn", 649 "dyn",
@@ -850,7 +876,7 @@ impl HirDisplay for Lifetime {
850impl HirDisplay for LifetimeData { 876impl HirDisplay for LifetimeData {
851 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 877 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
852 match self { 878 match self {
853 LifetimeData::BoundVar(idx) => write!(f, "?{}.{}", idx.debruijn.depth(), idx.index), 879 LifetimeData::BoundVar(idx) => idx.hir_fmt(f),
854 LifetimeData::InferenceVar(_) => write!(f, "_"), 880 LifetimeData::InferenceVar(_) => write!(f, "_"),
855 LifetimeData::Placeholder(idx) => { 881 LifetimeData::Placeholder(idx) => {
856 let id = lt_from_placeholder_idx(f.db, *idx); 882 let id = lt_from_placeholder_idx(f.db, *idx);
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 1c3faf5cb..5146d873b 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -42,7 +42,7 @@ use super::{
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, AliasEq, AliasTy, Interner, TyBuilder, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyExt, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index d6c48870a..159a53a63 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,7 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind}; 10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyExt, TyKind};
11 11
12use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
13 13
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 796487d02..5b3cdab4e 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -15,7 +15,7 @@ use stdx::always;
15use syntax::ast::RangeOp; 15use syntax::ast::RangeOp;
16 16
17use crate::{ 17use crate::{
18 autoderef, 18 autoderef, dummy_usize_const,
19 lower::lower_to_chalk_mutability, 19 lower::lower_to_chalk_mutability,
20 method_resolution, op, 20 method_resolution, op,
21 primitive::{self, UintTy}, 21 primitive::{self, UintTy},
@@ -23,7 +23,8 @@ use crate::{
23 traits::{chalk::from_chalk, FnTrait}, 23 traits::{chalk::from_chalk, FnTrait},
24 utils::{generics, variant_data, Generics}, 24 utils::{generics, variant_data, Generics},
25 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner, 25 AdtId, Binders, CallableDefId, FnPointer, FnSig, FnSubst, InEnvironment, Interner,
26 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyKind, TypeWalk, 26 ProjectionTyExt, Rawness, Scalar, Substitution, TraitRef, Ty, TyBuilder, TyExt, TyKind,
27 TypeWalk,
27}; 28};
28 29
29use super::{ 30use super::{
@@ -317,7 +318,13 @@ impl<'a> InferenceContext<'a> {
317 self.normalize_associated_types_in(ret_ty) 318 self.normalize_associated_types_in(ret_ty)
318 } 319 }
319 Expr::MethodCall { receiver, args, method_name, generic_args } => self 320 Expr::MethodCall { receiver, args, method_name, generic_args } => self
320 .infer_method_call(tgt_expr, *receiver, &args, &method_name, generic_args.as_ref()), 321 .infer_method_call(
322 tgt_expr,
323 *receiver,
324 &args,
325 &method_name,
326 generic_args.as_deref(),
327 ),
321 Expr::Match { expr, arms } => { 328 Expr::Match { expr, arms } => {
322 let input_ty = self.infer_expr(*expr, &Expectation::none()); 329 let input_ty = self.infer_expr(*expr, &Expectation::none());
323 330
@@ -398,7 +405,7 @@ impl<'a> InferenceContext<'a> {
398 TyKind::Never.intern(&Interner) 405 TyKind::Never.intern(&Interner)
399 } 406 }
400 Expr::RecordLit { path, fields, spread } => { 407 Expr::RecordLit { path, fields, spread } => {
401 let (ty, def_id) = self.resolve_variant(path.as_ref()); 408 let (ty, def_id) = self.resolve_variant(path.as_deref());
402 if let Some(variant) = def_id { 409 if let Some(variant) = def_id {
403 self.write_variant_resolution(tgt_expr.into(), variant); 410 self.write_variant_resolution(tgt_expr.into(), variant);
404 } 411 }
@@ -702,7 +709,7 @@ impl<'a> InferenceContext<'a> {
702 } 709 }
703 Expr::Array(array) => { 710 Expr::Array(array) => {
704 let elem_ty = match expected.ty.kind(&Interner) { 711 let elem_ty = match expected.ty.kind(&Interner) {
705 TyKind::Array(st) | TyKind::Slice(st) => st.clone(), 712 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
706 _ => self.table.new_type_var(), 713 _ => self.table.new_type_var(),
707 }; 714 };
708 715
@@ -726,7 +733,7 @@ impl<'a> InferenceContext<'a> {
726 } 733 }
727 } 734 }
728 735
729 TyKind::Array(elem_ty).intern(&Interner) 736 TyKind::Array(elem_ty, dummy_usize_const()).intern(&Interner)
730 } 737 }
731 Expr::Literal(lit) => match lit { 738 Expr::Literal(lit) => match lit {
732 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 739 Literal::Bool(..) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
@@ -736,7 +743,8 @@ impl<'a> InferenceContext<'a> {
736 } 743 }
737 Literal::ByteString(..) => { 744 Literal::ByteString(..) => {
738 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner); 745 let byte_type = TyKind::Scalar(Scalar::Uint(UintTy::U8)).intern(&Interner);
739 let array_type = TyKind::Array(byte_type).intern(&Interner); 746 let array_type =
747 TyKind::Array(byte_type, dummy_usize_const()).intern(&Interner);
740 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner) 748 TyKind::Ref(Mutability::Not, static_lifetime(), array_type).intern(&Interner)
741 } 749 }
742 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner), 750 Literal::Char(..) => TyKind::Scalar(Scalar::Char).intern(&Interner),
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs
index 2848a393c..12431ae07 100644
--- a/crates/hir_ty/src/infer/pat.rs
+++ b/crates/hir_ty/src/infer/pat.rs
@@ -14,7 +14,7 @@ use hir_expand::name::Name;
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 15use crate::{
16 lower::lower_to_chalk_mutability, static_lifetime, utils::variant_data, Interner, Substitution, 16 lower::lower_to_chalk_mutability, static_lifetime, utils::variant_data, Interner, Substitution,
17 Ty, TyBuilder, TyKind, 17 Ty, TyBuilder, TyExt, TyKind,
18}; 18};
19 19
20impl<'a> InferenceContext<'a> { 20impl<'a> InferenceContext<'a> {
@@ -174,7 +174,7 @@ impl<'a> InferenceContext<'a> {
174 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner) 174 TyKind::Ref(mutability, static_lifetime(), subty).intern(&Interner)
175 } 175 }
176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat( 176 Pat::TupleStruct { path: p, args: subpats, ellipsis } => self.infer_tuple_struct_pat(
177 p.as_ref(), 177 p.as_deref(),
178 subpats, 178 subpats,
179 expected, 179 expected,
180 default_bm, 180 default_bm,
@@ -182,7 +182,7 @@ impl<'a> InferenceContext<'a> {
182 *ellipsis, 182 *ellipsis,
183 ), 183 ),
184 Pat::Record { path: p, args: fields, ellipsis: _ } => { 184 Pat::Record { path: p, args: fields, ellipsis: _ } => {
185 self.infer_record_pat(p.as_ref(), fields, expected, default_bm, pat) 185 self.infer_record_pat(p.as_deref(), fields, expected, default_bm, pat)
186 } 186 }
187 Pat::Path(path) => { 187 Pat::Path(path) => {
188 // FIXME use correct resolver for the surrounding expression 188 // FIXME use correct resolver for the surrounding expression
@@ -214,17 +214,20 @@ impl<'a> InferenceContext<'a> {
214 return inner_ty; 214 return inner_ty;
215 } 215 }
216 Pat::Slice { prefix, slice, suffix } => { 216 Pat::Slice { prefix, slice, suffix } => {
217 let (container_ty, elem_ty): (fn(_) -> _, _) = match expected.kind(&Interner) { 217 let elem_ty = match expected.kind(&Interner) {
218 TyKind::Array(st) => (TyKind::Array, st.clone()), 218 TyKind::Array(st, _) | TyKind::Slice(st) => st.clone(),
219 TyKind::Slice(st) => (TyKind::Slice, st.clone()), 219 _ => self.err_ty(),
220 _ => (TyKind::Slice, self.err_ty()),
221 }; 220 };
222 221
223 for pat_id in prefix.iter().chain(suffix) { 222 for pat_id in prefix.iter().chain(suffix) {
224 self.infer_pat(*pat_id, &elem_ty, default_bm); 223 self.infer_pat(*pat_id, &elem_ty, default_bm);
225 } 224 }
226 225
227 let pat_ty = container_ty(elem_ty).intern(&Interner); 226 let pat_ty = match expected.kind(&Interner) {
227 TyKind::Array(_, const_) => TyKind::Array(elem_ty, const_.clone()),
228 _ => TyKind::Slice(elem_ty),
229 }
230 .intern(&Interner);
228 if let Some(slice_pat_id) = slice { 231 if let Some(slice_pat_id) = slice {
229 self.infer_pat(*slice_pat_id, &pat_ty, default_bm); 232 self.infer_pat(*slice_pat_id, &pat_ty, default_bm);
230 } 233 }
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs
index 14f705173..b19d67bb1 100644
--- a/crates/hir_ty/src/infer/path.rs
+++ b/crates/hir_ty/src/infer/path.rs
@@ -10,7 +10,9 @@ use hir_def::{
10}; 10};
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; 13use crate::{
14 method_resolution, Interner, Substitution, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId,
15};
14 16
15use super::{ExprOrPatId, InferenceContext, TraitRef}; 17use super::{ExprOrPatId, InferenceContext, TraitRef};
16 18
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs
index c7878ebfd..7d76cda68 100644
--- a/crates/hir_ty/src/infer/unify.rs
+++ b/crates/hir_ty/src/infer/unify.rs
@@ -317,9 +317,11 @@ impl InferenceTable {
317 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => { 317 | (TyKind::Closure(.., substs1), TyKind::Closure(.., substs2)) => {
318 self.unify_substs(substs1, substs2, depth + 1) 318 self.unify_substs(substs1, substs2, depth + 1)
319 } 319 }
320 (TyKind::Array(ty1, c1), TyKind::Array(ty2, c2)) if c1 == c2 => {
321 self.unify_inner(ty1, ty2, depth + 1)
322 }
320 (TyKind::Ref(_, _, ty1), TyKind::Ref(_, _, ty2)) 323 (TyKind::Ref(_, _, ty1), TyKind::Ref(_, _, ty2))
321 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2)) 324 | (TyKind::Raw(_, ty1), TyKind::Raw(_, ty2))
322 | (TyKind::Array(ty1), TyKind::Array(ty2))
323 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1), 325 | (TyKind::Slice(ty1), TyKind::Slice(ty2)) => self.unify_inner(ty1, ty2, depth + 1),
324 _ => true, /* we checked equals_ctor already */ 326 _ => true, /* we checked equals_ctor already */
325 } 327 }
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs
index bccc73449..f5b658cba 100644
--- a/crates/hir_ty/src/lib.rs
+++ b/crates/hir_ty/src/lib.rs
@@ -30,12 +30,11 @@ mod test_db;
30 30
31use std::sync::Arc; 31use std::sync::Arc;
32 32
33use itertools::Itertools;
34
35use base_db::salsa; 33use base_db::salsa;
34use chalk_ir::UintTy;
36use hir_def::{ 35use hir_def::{
37 expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, 36 expr::ExprId, type_ref::Rawness, ConstParamId, LifetimeParamId, TraitId, TypeAliasId,
38 LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, 37 TypeParamId,
39}; 38};
40 39
41use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; 40use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
@@ -71,6 +70,11 @@ pub type Lifetime = chalk_ir::Lifetime<Interner>;
71pub type LifetimeData = chalk_ir::LifetimeData<Interner>; 70pub type LifetimeData = chalk_ir::LifetimeData<Interner>;
72pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; 71pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>;
73 72
73pub type Const = chalk_ir::Const<Interner>;
74pub type ConstData = chalk_ir::ConstData<Interner>;
75pub type ConstValue = chalk_ir::ConstValue<Interner>;
76pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>;
77
74pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 78pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
75 79
76pub type FnSig = chalk_ir::FnSig<Interner>; 80pub type FnSig = chalk_ir::FnSig<Interner>;
@@ -165,69 +169,12 @@ impl CallableSig {
165} 169}
166 170
167impl Ty { 171impl Ty {
168 pub fn as_reference(&self) -> Option<(&Ty, Lifetime, Mutability)> {
169 match self.kind(&Interner) {
170 TyKind::Ref(mutability, lifetime, ty) => Some((ty, *lifetime, *mutability)),
171 _ => None,
172 }
173 }
174
175 pub fn as_reference_or_ptr(&self) -> Option<(&Ty, Rawness, Mutability)> {
176 match self.kind(&Interner) {
177 TyKind::Ref(mutability, _, ty) => Some((ty, Rawness::Ref, *mutability)),
178 TyKind::Raw(mutability, ty) => Some((ty, Rawness::RawPtr, *mutability)),
179 _ => None,
180 }
181 }
182
183 pub fn strip_references(&self) -> &Ty {
184 let mut t: &Ty = self;
185
186 while let TyKind::Ref(_mutability, _lifetime, ty) = t.kind(&Interner) {
187 t = ty;
188 }
189
190 t
191 }
192
193 pub fn as_adt(&self) -> Option<(hir_def::AdtId, &Substitution)> {
194 match self.kind(&Interner) {
195 TyKind::Adt(AdtId(adt), parameters) => Some((*adt, parameters)),
196 _ => None,
197 }
198 }
199
200 pub fn as_tuple(&self) -> Option<&Substitution> {
201 match self.kind(&Interner) {
202 TyKind::Tuple(_, substs) => Some(substs),
203 _ => None,
204 }
205 }
206
207 pub fn as_generic_def(&self, db: &dyn HirDatabase) -> Option<GenericDefId> {
208 match *self.kind(&Interner) {
209 TyKind::Adt(AdtId(adt), ..) => Some(adt.into()),
210 TyKind::FnDef(callable, ..) => {
211 Some(db.lookup_intern_callable_def(callable.into()).into())
212 }
213 TyKind::AssociatedType(type_alias, ..) => Some(from_assoc_type_id(type_alias).into()),
214 TyKind::Foreign(type_alias, ..) => Some(from_foreign_def_id(type_alias).into()),
215 _ => None,
216 }
217 }
218
219 pub fn is_never(&self) -> bool {
220 matches!(self.kind(&Interner), TyKind::Never)
221 }
222
223 pub fn is_unknown(&self) -> bool {
224 matches!(self.kind(&Interner), TyKind::Error)
225 }
226
227 pub fn equals_ctor(&self, other: &Ty) -> bool { 172 pub fn equals_ctor(&self, other: &Ty) -> bool {
228 match (self.kind(&Interner), other.kind(&Interner)) { 173 match (self.kind(&Interner), other.kind(&Interner)) {
229 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2, 174 (TyKind::Adt(adt, ..), TyKind::Adt(adt2, ..)) => adt == adt2,
230 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_), TyKind::Array(_)) => true, 175 (TyKind::Slice(_), TyKind::Slice(_)) | (TyKind::Array(_, _), TyKind::Array(_, _)) => {
176 true
177 }
231 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2, 178 (TyKind::FnDef(def_id, ..), TyKind::FnDef(def_id2, ..)) => def_id == def_id2,
232 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2, 179 (TyKind::OpaqueType(ty_id, ..), TyKind::OpaqueType(ty_id2, ..)) => ty_id == ty_id2,
233 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => { 180 (TyKind::AssociatedType(ty_id, ..), TyKind::AssociatedType(ty_id2, ..)) => {
@@ -252,24 +199,6 @@ impl Ty {
252 } 199 }
253 } 200 }
254 201
255 /// If this is a `dyn Trait` type, this returns the `Trait` part.
256 fn dyn_trait_ref(&self) -> Option<&TraitRef> {
257 match self.kind(&Interner) {
258 TyKind::Dyn(dyn_ty) => dyn_ty.bounds.skip_binders().interned().get(0).and_then(|b| {
259 match b.skip_binders() {
260 WhereClause::Implemented(trait_ref) => Some(trait_ref),
261 _ => None,
262 }
263 }),
264 _ => None,
265 }
266 }
267
268 /// If this is a `dyn Trait`, returns that trait.
269 pub fn dyn_trait(&self) -> Option<TraitId> {
270 self.dyn_trait_ref().map(|it| it.trait_id).map(from_chalk_trait_id)
271 }
272
273 fn builtin_deref(&self) -> Option<Ty> { 202 fn builtin_deref(&self) -> Option<Ty> {
274 match self.kind(&Interner) { 203 match self.kind(&Interner) {
275 TyKind::Ref(.., ty) => Some(ty.clone()), 204 TyKind::Ref(.., ty) => Some(ty.clone()),
@@ -278,37 +207,6 @@ impl Ty {
278 } 207 }
279 } 208 }
280 209
281 pub fn callable_def(&self, db: &dyn HirDatabase) -> Option<CallableDefId> {
282 match self.kind(&Interner) {
283 &TyKind::FnDef(def, ..) => Some(db.lookup_intern_callable_def(def.into())),
284 _ => None,
285 }
286 }
287
288 pub fn as_fn_def(&self, db: &dyn HirDatabase) -> Option<FunctionId> {
289 if let Some(CallableDefId::FunctionId(func)) = self.callable_def(db) {
290 Some(func)
291 } else {
292 None
293 }
294 }
295
296 pub fn callable_sig(&self, db: &dyn HirDatabase) -> Option<CallableSig> {
297 match self.kind(&Interner) {
298 TyKind::Function(fn_ptr) => Some(CallableSig::from_fn_ptr(fn_ptr)),
299 TyKind::FnDef(def, parameters) => {
300 let callable_def = db.lookup_intern_callable_def((*def).into());
301 let sig = db.callable_item_signature(callable_def);
302 Some(sig.substitute(&Interner, &parameters))
303 }
304 TyKind::Closure(.., substs) => {
305 let sig_param = substs.at(&Interner, 0).assert_ty_ref(&Interner);
306 sig_param.callable_sig(db)
307 }
308 _ => None,
309 }
310 }
311
312 /// Returns the type parameters of this type if it has some (i.e. is an ADT 210 /// Returns the type parameters of this type if it has some (i.e. is an ADT
313 /// or function); so if `self` is `Option<u32>`, this returns the `u32`. 211 /// or function); so if `self` is `Option<u32>`, this returns the `u32`.
314 pub fn substs(&self) -> Option<&Substitution> { 212 pub fn substs(&self) -> Option<&Substitution> {
@@ -336,104 +234,6 @@ impl Ty {
336 _ => None, 234 _ => None,
337 } 235 }
338 } 236 }
339
340 pub fn impl_trait_bounds(&self, db: &dyn HirDatabase) -> Option<Vec<QuantifiedWhereClause>> {
341 match self.kind(&Interner) {
342 TyKind::OpaqueType(opaque_ty_id, ..) => {
343 match db.lookup_intern_impl_trait_id((*opaque_ty_id).into()) {
344 ImplTraitId::AsyncBlockTypeImplTrait(def, _expr) => {
345 let krate = def.module(db.upcast()).krate();
346 if let Some(future_trait) = db
347 .lang_item(krate, "future_trait".into())
348 .and_then(|item| item.as_trait())
349 {
350 // This is only used by type walking.
351 // Parameters will be walked outside, and projection predicate is not used.
352 // So just provide the Future trait.
353 let impl_bound = Binders::empty(
354 &Interner,
355 WhereClause::Implemented(TraitRef {
356 trait_id: to_chalk_trait_id(future_trait),
357 substitution: Substitution::empty(&Interner),
358 }),
359 );
360 Some(vec![impl_bound])
361 } else {
362 None
363 }
364 }
365 ImplTraitId::ReturnTypeImplTrait(..) => None,
366 }
367 }
368 TyKind::Alias(AliasTy::Opaque(opaque_ty)) => {
369 let predicates = match db.lookup_intern_impl_trait_id(opaque_ty.opaque_ty_id.into())
370 {
371 ImplTraitId::ReturnTypeImplTrait(func, idx) => {
372 db.return_type_impl_traits(func).map(|it| {
373 let data = (*it)
374 .as_ref()
375 .map(|rpit| rpit.impl_traits[idx as usize].bounds.clone());
376 data.substitute(&Interner, &opaque_ty.substitution)
377 })
378 }
379 // It always has an parameter for Future::Output type.
380 ImplTraitId::AsyncBlockTypeImplTrait(..) => unreachable!(),
381 };
382
383 predicates.map(|it| it.into_value_and_skipped_binders().0)
384 }
385 TyKind::Placeholder(idx) => {
386 let id = from_placeholder_idx(db, *idx);
387 let generic_params = db.generic_params(id.parent);
388 let param_data = &generic_params.types[id.local_id];
389 match param_data.provenance {
390 hir_def::generics::TypeParamProvenance::ArgumentImplTrait => {
391 let substs = TyBuilder::type_params_subst(db, id.parent);
392 let predicates = db
393 .generic_predicates(id.parent)
394 .into_iter()
395 .map(|pred| pred.clone().substitute(&Interner, &substs))
396 .filter(|wc| match &wc.skip_binders() {
397 WhereClause::Implemented(tr) => {
398 tr.self_type_parameter(&Interner) == self
399 }
400 WhereClause::AliasEq(AliasEq {
401 alias: AliasTy::Projection(proj),
402 ty: _,
403 }) => proj.self_type_parameter(&Interner) == self,
404 _ => false,
405 })
406 .collect_vec();
407
408 Some(predicates)
409 }
410 _ => None,
411 }
412 }
413 _ => None,
414 }
415 }
416
417 pub fn associated_type_parent_trait(&self, db: &dyn HirDatabase) -> Option<TraitId> {
418 match self.kind(&Interner) {
419 TyKind::AssociatedType(id, ..) => {
420 match from_assoc_type_id(*id).lookup(db.upcast()).container {
421 AssocContainerId::TraitId(trait_id) => Some(trait_id),
422 _ => None,
423 }
424 }
425 TyKind::Alias(AliasTy::Projection(projection_ty)) => {
426 match from_assoc_type_id(projection_ty.associated_ty_id)
427 .lookup(db.upcast())
428 .container
429 {
430 AssocContainerId::TraitId(trait_id) => Some(trait_id),
431 _ => None,
432 }
433 }
434 _ => None,
435 }
436 }
437} 237}
438 238
439#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] 239#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -488,6 +288,12 @@ pub fn lt_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> L
488 db.lookup_intern_lifetime_param_id(interned_id) 288 db.lookup_intern_lifetime_param_id(interned_id)
489} 289}
490 290
291pub fn const_from_placeholder_idx(db: &dyn HirDatabase, idx: PlaceholderIndex) -> ConstParamId {
292 assert_eq!(idx.ui, chalk_ir::UniverseIndex::ROOT);
293 let interned_id = salsa::InternKey::from_intern_id(salsa::InternId::from(idx.idx));
294 db.lookup_intern_const_param_id(interned_id)
295}
296
491pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { 297pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId {
492 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id)) 298 chalk_ir::TraitId(salsa::InternKey::as_intern_id(&id))
493} 299}
@@ -499,3 +305,12 @@ pub fn from_chalk_trait_id(id: ChalkTraitId) -> TraitId {
499pub fn static_lifetime() -> Lifetime { 305pub fn static_lifetime() -> Lifetime {
500 LifetimeData::Static.intern(&Interner) 306 LifetimeData::Static.intern(&Interner)
501} 307}
308
309pub fn dummy_usize_const() -> Const {
310 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner);
311 chalk_ir::ConstData {
312 ty: usize_ty,
313 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
314 }
315 .intern(&Interner)
316}
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs
index df6619af3..8be1bcddb 100644
--- a/crates/hir_ty/src/lower.rs
+++ b/crates/hir_ty/src/lower.rs
@@ -27,7 +27,7 @@ use stdx::impl_from;
27 27
28use crate::{ 28use crate::{
29 db::HirDatabase, 29 db::HirDatabase,
30 static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx, 30 dummy_usize_const, static_lifetime, to_assoc_type_id, to_chalk_trait_id, to_placeholder_idx,
31 traits::chalk::{Interner, ToChalk}, 31 traits::chalk::{Interner, ToChalk},
32 utils::{ 32 utils::{
33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics, 33 all_super_trait_refs, associated_type_by_name_including_super_traits, generics,
@@ -166,7 +166,7 @@ impl<'a> TyLoweringContext<'a> {
166 } 166 }
167 TypeRef::Array(inner) => { 167 TypeRef::Array(inner) => {
168 let inner_ty = self.lower_ty(inner); 168 let inner_ty = self.lower_ty(inner);
169 TyKind::Array(inner_ty).intern(&Interner) 169 TyKind::Array(inner_ty, dummy_usize_const()).intern(&Interner)
170 } 170 }
171 TypeRef::Slice(inner) => { 171 TypeRef::Slice(inner) => {
172 let inner_ty = self.lower_ty(inner); 172 let inner_ty = self.lower_ty(inner);
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 436dea22b..ee725fd46 100644
--- a/crates/hir_ty/src/method_resolution.rs
+++ b/crates/hir_ty/src/method_resolution.rs
@@ -22,7 +22,7 @@ use crate::{
22 static_lifetime, 22 static_lifetime,
23 utils::all_super_traits, 23 utils::all_super_traits,
24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, 24 AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId,
25 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind, 25 InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
26 TypeWalk, 26 TypeWalk,
27}; 27};
28 28
@@ -842,7 +842,9 @@ fn autoderef_method_receiver(
842) -> Vec<Canonical<Ty>> { 842) -> Vec<Canonical<Ty>> {
843 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect(); 843 let mut deref_chain: Vec<_> = autoderef::autoderef(db, Some(krate), ty).collect();
844 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!) 844 // As a last step, we can do array unsizing (that's the only unsizing that rustc does for method receivers!)
845 if let Some(TyKind::Array(parameters)) = deref_chain.last().map(|ty| ty.value.kind(&Interner)) { 845 if let Some(TyKind::Array(parameters, _)) =
846 deref_chain.last().map(|ty| ty.value.kind(&Interner))
847 {
846 let kinds = deref_chain.last().unwrap().binders.clone(); 848 let kinds = deref_chain.last().unwrap().binders.clone();
847 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner); 849 let unsized_ty = TyKind::Slice(parameters.clone()).intern(&Interner);
848 deref_chain.push(Canonical { value: unsized_ty, binders: kinds }) 850 deref_chain.push(Canonical { value: unsized_ty, binders: kinds })
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs
index 5a8b5cd86..f03b92422 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, TyBuilder, TyKind, WhereClause, 25 TraitRef, Ty, TyBuilder, TyExt, 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,
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs
index 9267e32b5..cf73cb078 100644
--- a/crates/hir_ty/src/traits/chalk/mapping.rs
+++ b/crates/hir_ty/src/traits/chalk/mapping.rs
@@ -10,9 +10,10 @@ use base_db::salsa::InternKey;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use crate::{
13 chalk_ext::ProjectionTyExt, db::HirDatabase, primitive::UintTy, static_lifetime, AliasTy, 13 chalk_ext::ProjectionTyExt, db::HirDatabase, dummy_usize_const, static_lifetime, AliasTy,
14 CallableDefId, Canonical, DomainGoal, FnPointer, GenericArg, InEnvironment, Lifetime, OpaqueTy, 14 CallableDefId, Canonical, Const, DomainGoal, FnPointer, GenericArg, InEnvironment, Lifetime,
15 ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, 15 OpaqueTy, ProjectionTy, QuantifiedWhereClause, Substitution, TraitRef, Ty, TypeWalk,
16 WhereClause,
16}; 17};
17 18
18use super::interner::*; 19use super::interner::*;
@@ -23,7 +24,7 @@ impl ToChalk for Ty {
23 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> { 24 fn to_chalk(self, db: &dyn HirDatabase) -> chalk_ir::Ty<Interner> {
24 match self.into_inner() { 25 match self.into_inner() {
25 TyKind::Ref(m, lt, ty) => ref_to_chalk(db, m, lt, ty), 26 TyKind::Ref(m, lt, ty) => ref_to_chalk(db, m, lt, ty),
26 TyKind::Array(ty) => array_to_chalk(db, ty), 27 TyKind::Array(ty, size) => array_to_chalk(db, ty, size),
27 TyKind::Function(FnPointer { sig, substitution: substs, .. }) => { 28 TyKind::Function(FnPointer { sig, substitution: substs, .. }) => {
28 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db)); 29 let substitution = chalk_ir::FnSubst(substs.0.to_chalk(db));
29 chalk_ir::TyKind::Function(chalk_ir::FnPointer { 30 chalk_ir::TyKind::Function(chalk_ir::FnPointer {
@@ -110,7 +111,7 @@ impl ToChalk for Ty {
110 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self { 111 fn from_chalk(db: &dyn HirDatabase, chalk: chalk_ir::Ty<Interner>) -> Self {
111 match chalk.data(&Interner).kind.clone() { 112 match chalk.data(&Interner).kind.clone() {
112 chalk_ir::TyKind::Error => TyKind::Error, 113 chalk_ir::TyKind::Error => TyKind::Error,
113 chalk_ir::TyKind::Array(ty, _size) => TyKind::Array(from_chalk(db, ty)), 114 chalk_ir::TyKind::Array(ty, size) => TyKind::Array(from_chalk(db, ty), size),
114 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx), 115 chalk_ir::TyKind::Placeholder(idx) => TyKind::Placeholder(idx),
115 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => { 116 chalk_ir::TyKind::Alias(chalk_ir::AliasTy::Projection(proj)) => {
116 let associated_ty = proj.associated_ty_id; 117 let associated_ty = proj.associated_ty_id;
@@ -203,15 +204,9 @@ fn ref_to_chalk(
203 204
204/// We currently don't model constants, but Chalk does. So, we have to insert a 205/// We currently don't model constants, but Chalk does. So, we have to insert a
205/// fake constant here, because Chalks built-in logic may expect it to be there. 206/// fake constant here, because Chalks built-in logic may expect it to be there.
206fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> { 207fn array_to_chalk(db: &dyn HirDatabase, ty: Ty, _: Const) -> chalk_ir::Ty<Interner> {
207 let arg = ty.to_chalk(db); 208 let arg = ty.to_chalk(db);
208 let usize_ty = chalk_ir::TyKind::Scalar(Scalar::Uint(UintTy::Usize)).intern(&Interner); 209 chalk_ir::TyKind::Array(arg, dummy_usize_const()).intern(&Interner)
209 let const_ = chalk_ir::ConstData {
210 ty: usize_ty,
211 value: chalk_ir::ConstValue::Concrete(chalk_ir::ConcreteConst { interned: () }),
212 }
213 .intern(&Interner);
214 chalk_ir::TyKind::Array(arg, const_).intern(&Interner)
215} 210}
216 211
217impl ToChalk for GenericArg { 212impl ToChalk for GenericArg {
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs
index 844e57896..89c0ddd1a 100644
--- a/crates/hir_ty/src/types.rs
+++ b/crates/hir_ty/src/types.rs
@@ -10,7 +10,7 @@ use chalk_ir::{
10use smallvec::SmallVec; 10use smallvec::SmallVec;
11 11
12use crate::{ 12use crate::{
13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId, 13 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, Const, FnDefId, FnSig, ForeignDefId,
14 InferenceVar, Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind, 14 InferenceVar, Interner, Lifetime, OpaqueTyId, PlaceholderIndex, TypeWalk, VariableKind,
15 VariableKinds, 15 VariableKinds,
16}; 16};
@@ -114,7 +114,7 @@ pub enum TyKind {
114 Tuple(usize, Substitution), 114 Tuple(usize, Substitution),
115 115
116 /// An array with the given length. Written as `[T; n]`. 116 /// An array with the given length. Written as `[T; n]`.
117 Array(Ty), 117 Array(Ty, Const),
118 118
119 /// The pointee of an array slice. Written as `[T]`. 119 /// The pointee of an array slice. Written as `[T]`.
120 Slice(Ty), 120 Slice(Ty),
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs
index 4cc4e24fd..41ebf6137 100644
--- a/crates/hir_ty/src/walk.rs
+++ b/crates/hir_ty/src/walk.rs
@@ -153,7 +153,10 @@ impl TypeWalk for Ty {
153 p.walk(f); 153 p.walk(f);
154 } 154 }
155 } 155 }
156 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, _, ty) | TyKind::Raw(_, ty) => { 156 TyKind::Slice(ty)
157 | TyKind::Array(ty, _)
158 | TyKind::Ref(_, _, ty)
159 | TyKind::Raw(_, ty) => {
157 ty.walk(f); 160 ty.walk(f);
158 } 161 }
159 TyKind::Function(fn_pointer) => { 162 TyKind::Function(fn_pointer) => {
@@ -187,7 +190,10 @@ impl TypeWalk for Ty {
187 TyKind::Alias(AliasTy::Opaque(o_ty)) => { 190 TyKind::Alias(AliasTy::Opaque(o_ty)) => {
188 o_ty.substitution.walk_mut_binders(f, binders); 191 o_ty.substitution.walk_mut_binders(f, binders);
189 } 192 }
190 TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, _, ty) | TyKind::Raw(_, ty) => { 193 TyKind::Slice(ty)
194 | TyKind::Array(ty, _)
195 | TyKind::Ref(_, _, ty)
196 | TyKind::Raw(_, ty) => {
191 ty.walk_mut_binders(f, binders); 197 ty.walk_mut_binders(f, binders);
192 } 198 }
193 TyKind::Function(fn_pointer) => { 199 TyKind::Function(fn_pointer) => {