aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/hir/src/lib.rs6
-rw-r--r--crates/hir_def/src/body/lower.rs29
-rw-r--r--crates/hir_def/src/expr.rs19
-rw-r--r--crates/hir_def/src/path.rs6
-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
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs2
-rw-r--r--crates/vfs/Cargo.toml1
-rw-r--r--crates/vfs/src/path_interner.rs29
26 files changed, 413 insertions, 305 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs
index 813cd1295..8d00f7401 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -59,7 +59,7 @@ use hir_ty::{
59 traits::FnTrait, 59 traits::FnTrait,
60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 60 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, 61 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution,
62 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, 62 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyExt, TyKind,
63 TyVariableKind, WhereClause, 63 TyVariableKind, WhereClause,
64}; 64};
65use itertools::Itertools; 65use itertools::Itertools;
@@ -1888,7 +1888,7 @@ impl Type {
1888 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go) 1888 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
1889 } 1889 }
1890 1890
1891 TyKind::Array(ty) 1891 TyKind::Array(ty, _)
1892 | TyKind::Slice(ty) 1892 | TyKind::Slice(ty)
1893 | TyKind::Raw(_, ty) 1893 | TyKind::Raw(_, ty)
1894 | TyKind::Ref(_, _, ty) => go(ty), 1894 | TyKind::Ref(_, _, ty) => go(ty),
@@ -2151,7 +2151,7 @@ impl Type {
2151 2151
2152 TyKind::Ref(_, _, ty) 2152 TyKind::Ref(_, _, ty)
2153 | TyKind::Raw(_, ty) 2153 | TyKind::Raw(_, ty)
2154 | TyKind::Array(ty) 2154 | TyKind::Array(ty, _)
2155 | TyKind::Slice(ty) => { 2155 | TyKind::Slice(ty) => {
2156 walk_type(db, &type_.derived(ty.clone()), cb); 2156 walk_type(db, &type_.derived(ty.clone()), cb);
2157 } 2157 }
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs
index 63e89a1f4..bfb75a8a5 100644
--- a/crates/hir_def/src/body/lower.rs
+++ b/crates/hir_def/src/body/lower.rs
@@ -30,6 +30,7 @@ use crate::{
30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField, 30 LabelId, Literal, LogicOp, MatchArm, Ordering, Pat, PatId, RecordFieldPat, RecordLitField,
31 Statement, 31 Statement,
32 }, 32 },
33 intern::Interned,
33 item_scope::BuiltinShadowMode, 34 item_scope::BuiltinShadowMode,
34 path::{GenericArgs, Path}, 35 path::{GenericArgs, Path},
35 type_ref::{Mutability, Rawness, TypeRef}, 36 type_ref::{Mutability, Rawness, TypeRef},
@@ -322,8 +323,10 @@ impl ExprCollector<'_> {
322 Vec::new() 323 Vec::new()
323 }; 324 };
324 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing); 325 let method_name = e.name_ref().map(|nr| nr.as_name()).unwrap_or_else(Name::missing);
325 let generic_args = 326 let generic_args = e
326 e.generic_arg_list().and_then(|it| GenericArgs::from_ast(&self.ctx(), it)); 327 .generic_arg_list()
328 .and_then(|it| GenericArgs::from_ast(&self.ctx(), it))
329 .map(Box::new);
327 self.alloc_expr( 330 self.alloc_expr(
328 Expr::MethodCall { receiver, method_name, args, generic_args }, 331 Expr::MethodCall { receiver, method_name, args, generic_args },
329 syntax_ptr, 332 syntax_ptr,
@@ -385,7 +388,7 @@ impl ExprCollector<'_> {
385 self.alloc_expr(Expr::Yield { expr }, syntax_ptr) 388 self.alloc_expr(Expr::Yield { expr }, syntax_ptr)
386 } 389 }
387 ast::Expr::RecordExpr(e) => { 390 ast::Expr::RecordExpr(e) => {
388 let path = e.path().and_then(|path| self.expander.parse_path(path)); 391 let path = e.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
389 let record_lit = if let Some(nfl) = e.record_expr_field_list() { 392 let record_lit = if let Some(nfl) = e.record_expr_field_list() {
390 let fields = nfl 393 let fields = nfl
391 .fields() 394 .fields()
@@ -430,7 +433,7 @@ impl ExprCollector<'_> {
430 } 433 }
431 ast::Expr::CastExpr(e) => { 434 ast::Expr::CastExpr(e) => {
432 let expr = self.collect_expr_opt(e.expr()); 435 let expr = self.collect_expr_opt(e.expr());
433 let type_ref = TypeRef::from_ast_opt(&self.ctx(), e.ty()); 436 let type_ref = Interned::new(TypeRef::from_ast_opt(&self.ctx(), e.ty()));
434 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr) 437 self.alloc_expr(Expr::Cast { expr, type_ref }, syntax_ptr)
435 } 438 }
436 ast::Expr::RefExpr(e) => { 439 ast::Expr::RefExpr(e) => {
@@ -464,13 +467,16 @@ impl ExprCollector<'_> {
464 if let Some(pl) = e.param_list() { 467 if let Some(pl) = e.param_list() {
465 for param in pl.params() { 468 for param in pl.params() {
466 let pat = self.collect_pat_opt(param.pat()); 469 let pat = self.collect_pat_opt(param.pat());
467 let type_ref = param.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 470 let type_ref =
471 param.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
468 args.push(pat); 472 args.push(pat);
469 arg_types.push(type_ref); 473 arg_types.push(type_ref);
470 } 474 }
471 } 475 }
472 let ret_type = 476 let ret_type = e
473 e.ret_type().and_then(|r| r.ty()).map(|it| TypeRef::from_ast(&self.ctx(), it)); 477 .ret_type()
478 .and_then(|r| r.ty())
479 .map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
474 let body = self.collect_expr_opt(e.body()); 480 let body = self.collect_expr_opt(e.body());
475 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr) 481 self.alloc_expr(Expr::Lambda { args, arg_types, ret_type, body }, syntax_ptr)
476 } 482 }
@@ -625,7 +631,8 @@ impl ExprCollector<'_> {
625 return; 631 return;
626 } 632 }
627 let pat = self.collect_pat_opt(stmt.pat()); 633 let pat = self.collect_pat_opt(stmt.pat());
628 let type_ref = stmt.ty().map(|it| TypeRef::from_ast(&self.ctx(), it)); 634 let type_ref =
635 stmt.ty().map(|it| Interned::new(TypeRef::from_ast(&self.ctx(), it)));
629 let initializer = stmt.initializer().map(|e| self.collect_expr(e)); 636 let initializer = stmt.initializer().map(|e| self.collect_expr(e));
630 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer }); 637 self.statements_in_scope.push(Statement::Let { pat, type_ref, initializer });
631 } 638 }
@@ -755,7 +762,7 @@ impl ExprCollector<'_> {
755 } 762 }
756 } 763 }
757 ast::Pat::TupleStructPat(p) => { 764 ast::Pat::TupleStructPat(p) => {
758 let path = p.path().and_then(|path| self.expander.parse_path(path)); 765 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
759 let (args, ellipsis) = self.collect_tuple_pat(p.fields()); 766 let (args, ellipsis) = self.collect_tuple_pat(p.fields());
760 Pat::TupleStruct { path, args, ellipsis } 767 Pat::TupleStruct { path, args, ellipsis }
761 } 768 }
@@ -765,7 +772,7 @@ impl ExprCollector<'_> {
765 Pat::Ref { pat, mutability } 772 Pat::Ref { pat, mutability }
766 } 773 }
767 ast::Pat::PathPat(p) => { 774 ast::Pat::PathPat(p) => {
768 let path = p.path().and_then(|path| self.expander.parse_path(path)); 775 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
769 path.map(Pat::Path).unwrap_or(Pat::Missing) 776 path.map(Pat::Path).unwrap_or(Pat::Missing)
770 } 777 }
771 ast::Pat::OrPat(p) => { 778 ast::Pat::OrPat(p) => {
@@ -779,7 +786,7 @@ impl ExprCollector<'_> {
779 } 786 }
780 ast::Pat::WildcardPat(_) => Pat::Wild, 787 ast::Pat::WildcardPat(_) => Pat::Wild,
781 ast::Pat::RecordPat(p) => { 788 ast::Pat::RecordPat(p) => {
782 let path = p.path().and_then(|path| self.expander.parse_path(path)); 789 let path = p.path().and_then(|path| self.expander.parse_path(path)).map(Box::new);
783 let args: Vec<_> = p 790 let args: Vec<_> = p
784 .record_pat_field_list() 791 .record_pat_field_list()
785 .expect("every struct should have a field list") 792 .expect("every struct should have a field list")
diff --git a/crates/hir_def/src/expr.rs b/crates/hir_def/src/expr.rs
index 6c7376fad..b4ad984bd 100644
--- a/crates/hir_def/src/expr.rs
+++ b/crates/hir_def/src/expr.rs
@@ -18,6 +18,7 @@ use syntax::ast::RangeOp;
18 18
19use crate::{ 19use crate::{
20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint}, 20 builtin_type::{BuiltinFloat, BuiltinInt, BuiltinUint},
21 intern::Interned,
21 path::{GenericArgs, Path}, 22 path::{GenericArgs, Path},
22 type_ref::{Mutability, Rawness, TypeRef}, 23 type_ref::{Mutability, Rawness, TypeRef},
23 BlockId, 24 BlockId,
@@ -86,7 +87,7 @@ pub enum Expr {
86 receiver: ExprId, 87 receiver: ExprId,
87 method_name: Name, 88 method_name: Name,
88 args: Vec<ExprId>, 89 args: Vec<ExprId>,
89 generic_args: Option<GenericArgs>, 90 generic_args: Option<Box<GenericArgs>>,
90 }, 91 },
91 Match { 92 Match {
92 expr: ExprId, 93 expr: ExprId,
@@ -106,7 +107,7 @@ pub enum Expr {
106 expr: Option<ExprId>, 107 expr: Option<ExprId>,
107 }, 108 },
108 RecordLit { 109 RecordLit {
109 path: Option<Path>, 110 path: Option<Box<Path>>,
110 fields: Vec<RecordLitField>, 111 fields: Vec<RecordLitField>,
111 spread: Option<ExprId>, 112 spread: Option<ExprId>,
112 }, 113 },
@@ -131,7 +132,7 @@ pub enum Expr {
131 }, 132 },
132 Cast { 133 Cast {
133 expr: ExprId, 134 expr: ExprId,
134 type_ref: TypeRef, 135 type_ref: Interned<TypeRef>,
135 }, 136 },
136 Ref { 137 Ref {
137 expr: ExprId, 138 expr: ExprId,
@@ -161,8 +162,8 @@ pub enum Expr {
161 }, 162 },
162 Lambda { 163 Lambda {
163 args: Vec<PatId>, 164 args: Vec<PatId>,
164 arg_types: Vec<Option<TypeRef>>, 165 arg_types: Vec<Option<Interned<TypeRef>>>,
165 ret_type: Option<TypeRef>, 166 ret_type: Option<Interned<TypeRef>>,
166 body: ExprId, 167 body: ExprId,
167 }, 168 },
168 Tuple { 169 Tuple {
@@ -240,7 +241,7 @@ pub struct RecordLitField {
240 241
241#[derive(Debug, Clone, Eq, PartialEq)] 242#[derive(Debug, Clone, Eq, PartialEq)]
242pub enum Statement { 243pub enum Statement {
243 Let { pat: PatId, type_ref: Option<TypeRef>, initializer: Option<ExprId> }, 244 Let { pat: PatId, type_ref: Option<Interned<TypeRef>>, initializer: Option<ExprId> },
244 Expr(ExprId), 245 Expr(ExprId),
245} 246}
246 247
@@ -412,13 +413,13 @@ pub enum Pat {
412 Wild, 413 Wild,
413 Tuple { args: Vec<PatId>, ellipsis: Option<usize> }, 414 Tuple { args: Vec<PatId>, ellipsis: Option<usize> },
414 Or(Vec<PatId>), 415 Or(Vec<PatId>),
415 Record { path: Option<Path>, args: Vec<RecordFieldPat>, ellipsis: bool }, 416 Record { path: Option<Box<Path>>, args: Vec<RecordFieldPat>, ellipsis: bool },
416 Range { start: ExprId, end: ExprId }, 417 Range { start: ExprId, end: ExprId },
417 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> }, 418 Slice { prefix: Vec<PatId>, slice: Option<PatId>, suffix: Vec<PatId> },
418 Path(Path), 419 Path(Box<Path>),
419 Lit(ExprId), 420 Lit(ExprId),
420 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> }, 421 Bind { mode: BindingAnnotation, name: Name, subpat: Option<PatId> },
421 TupleStruct { path: Option<Path>, args: Vec<PatId>, ellipsis: Option<usize> }, 422 TupleStruct { path: Option<Box<Path>>, args: Vec<PatId>, ellipsis: Option<usize> },
422 Ref { pat: PatId, mutability: Mutability }, 423 Ref { pat: PatId, mutability: Mutability },
423 Box { inner: PatId }, 424 Box { inner: PatId },
424 ConstBlock(ExprId), 425 ConstBlock(ExprId),
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index f9c8328f0..b528ff8ba 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -289,6 +289,12 @@ impl From<Name> for Path {
289 } 289 }
290} 290}
291 291
292impl From<Name> for Box<Path> {
293 fn from(name: Name) -> Box<Path> {
294 Box::new(Path::from(name))
295 }
296}
297
292impl From<Name> for ModPath { 298impl From<Name> for ModPath {
293 fn from(name: Name) -> ModPath { 299 fn from(name: Name) -> ModPath {
294 ModPath::from_segments(PathKind::Plain, iter::once(name)) 300 ModPath::from_segments(PathKind::Plain, iter::once(name))
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) => {
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs
index 18fd7ea74..fe9f273b0 100644
--- a/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -12,7 +12,7 @@ use hir::{
12 AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef, 12 AssocItem, Crate, Function, HasSource, HirDisplay, ModuleDef,
13}; 13};
14use hir_def::FunctionId; 14use hir_def::FunctionId;
15use hir_ty::TypeWalk; 15use hir_ty::{TyExt, TypeWalk};
16use ide::{AnalysisHost, RootDatabase}; 16use ide::{AnalysisHost, RootDatabase};
17use ide_db::base_db::{ 17use ide_db::base_db::{
18 salsa::{self, ParallelDatabase}, 18 salsa::{self, ParallelDatabase},
diff --git a/crates/vfs/Cargo.toml b/crates/vfs/Cargo.toml
index c318a68f7..894944b18 100644
--- a/crates/vfs/Cargo.toml
+++ b/crates/vfs/Cargo.toml
@@ -14,3 +14,4 @@ rustc-hash = "1.0"
14fst = "0.4" 14fst = "0.4"
15 15
16paths = { path = "../paths", version = "0.0.0" } 16paths = { path = "../paths", version = "0.0.0" }
17indexmap = "1.6.2"
diff --git a/crates/vfs/src/path_interner.rs b/crates/vfs/src/path_interner.rs
index 2189e5e25..6e049f0d4 100644
--- a/crates/vfs/src/path_interner.rs
+++ b/crates/vfs/src/path_interner.rs
@@ -1,15 +1,22 @@
1//! Maps paths to compact integer ids. We don't care about clearings paths which 1//! Maps paths to compact integer ids. We don't care about clearings paths which
2//! no longer exist -- the assumption is total size of paths we ever look at is 2//! no longer exist -- the assumption is total size of paths we ever look at is
3//! not too big. 3//! not too big.
4use rustc_hash::FxHashMap; 4use std::hash::BuildHasherDefault;
5
6use indexmap::IndexSet;
7use rustc_hash::FxHasher;
5 8
6use crate::{FileId, VfsPath}; 9use crate::{FileId, VfsPath};
7 10
8/// Structure to map between [`VfsPath`] and [`FileId`]. 11/// Structure to map between [`VfsPath`] and [`FileId`].
9#[derive(Default)]
10pub(crate) struct PathInterner { 12pub(crate) struct PathInterner {
11 map: FxHashMap<VfsPath, FileId>, 13 map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>,
12 vec: Vec<VfsPath>, 14}
15
16impl Default for PathInterner {
17 fn default() -> Self {
18 Self { map: IndexSet::default() }
19 }
13} 20}
14 21
15impl PathInterner { 22impl PathInterner {
@@ -17,7 +24,7 @@ impl PathInterner {
17 /// 24 ///
18 /// If `path` does not exists in `self`, returns [`None`]. 25 /// If `path` does not exists in `self`, returns [`None`].
19 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> { 26 pub(crate) fn get(&self, path: &VfsPath) -> Option<FileId> {
20 self.map.get(path).copied() 27 self.map.get_index_of(path).map(|i| FileId(i as u32))
21 } 28 }
22 29
23 /// Insert `path` in `self`. 30 /// Insert `path` in `self`.
@@ -25,13 +32,9 @@ impl PathInterner {
25 /// - If `path` already exists in `self`, returns its associated id; 32 /// - If `path` already exists in `self`, returns its associated id;
26 /// - Else, returns a newly allocated id. 33 /// - Else, returns a newly allocated id.
27 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId { 34 pub(crate) fn intern(&mut self, path: VfsPath) -> FileId {
28 if let Some(id) = self.get(&path) { 35 let (id, _added) = self.map.insert_full(path);
29 return id; 36 assert!(id < u32::MAX as usize);
30 } 37 FileId(id as u32)
31 let id = FileId(self.vec.len() as u32);
32 self.map.insert(path.clone(), id);
33 self.vec.push(path);
34 id
35 } 38 }
36 39
37 /// Returns the path corresponding to `id`. 40 /// Returns the path corresponding to `id`.
@@ -40,6 +43,6 @@ impl PathInterner {
40 /// 43 ///
41 /// Panics if `id` does not exists in `self`. 44 /// Panics if `id` does not exists in `self`.
42 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath { 45 pub(crate) fn lookup(&self, id: FileId) -> &VfsPath {
43 &self.vec[id.0 as usize] 46 self.map.get_index(id.0 as usize).unwrap()
44 } 47 }
45} 48}