diff options
Diffstat (limited to 'crates')
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 | }; |
65 | use itertools::Itertools; | 65 | use 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 | ||
19 | use crate::{ | 19 | use 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)] |
242 | pub enum Statement { | 243 | pub 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 | ||
292 | impl From<Name> for Box<Path> { | ||
293 | fn from(name: Name) -> Box<Path> { | ||
294 | Box::new(Path::from(name)) | ||
295 | } | ||
296 | } | ||
297 | |||
292 | impl From<Name> for ModPath { | 298 | impl 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; | |||
13 | use crate::{ | 13 | use 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 | ||
3 | use hir_def::{AssocContainerId, Lookup, TraitId}; | 3 | use chalk_ir::Mutability; |
4 | use hir_def::{ | ||
5 | type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, TraitId, | ||
6 | }; | ||
4 | 7 | ||
5 | use crate::{ | 8 | use 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 | ||
10 | pub trait TyExt { | 15 | pub 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 | ||
14 | impl TyExt for Ty { | 39 | impl 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, ¶meters)) | ||
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 | ||
20 | pub trait ProjectionTyExt { | 243 | pub 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); | |||
162 | impl_intern_key!(InternedLifetimeParamId); | 164 | impl_intern_key!(InternedLifetimeParamId); |
163 | 165 | ||
164 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 166 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
167 | pub struct InternedConstParamId(salsa::InternId); | ||
168 | impl_intern_key!(InternedConstParamId); | ||
169 | |||
170 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
165 | pub struct InternedOpaqueTyId(salsa::InternId); | 171 | pub struct InternedOpaqueTyId(salsa::InternId); |
166 | impl_intern_key!(InternedOpaqueTyId); | 172 | impl_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::{ | |||
227 | use la_arena::Idx; | 227 | use la_arena::Idx; |
228 | use smallvec::{smallvec, SmallVec}; | 228 | use smallvec::{smallvec, SmallVec}; |
229 | 229 | ||
230 | use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyKind}; | 230 | use crate::{db::HirDatabase, AdtId, InferenceResult, Interner, TyExt, TyKind}; |
231 | 231 | ||
232 | #[derive(Debug, Clone, Copy)] | 232 | #[derive(Debug, Clone, Copy)] |
233 | /// Either a pattern from the source code being analyzed, represented as | 233 | /// Either a pattern from the source code being analyzed, represented as |
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 | }; |
12 | use hir_expand::diagnostics::DiagnosticSink; | 12 | use hir_expand::diagnostics::DiagnosticSink; |
13 | 13 | ||
14 | use crate::{db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyKind}; | 14 | use crate::{ |
15 | db::HirDatabase, diagnostics::MissingUnsafe, InferenceResult, Interner, TyExt, TyKind, | ||
16 | }; | ||
15 | 17 | ||
16 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { | 18 | pub(super) struct UnsafeValidator<'a, 'b: 'a> { |
17 | owner: DefWithBodyId, | 19 | owner: DefWithBodyId, |
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 | ||
8 | use chalk_ir::BoundVar; | ||
8 | use hir_def::{ | 9 | use hir_def::{ |
9 | db::DefDatabase, | 10 | db::DefDatabase, |
10 | find_path, | 11 | find_path, |
@@ -18,12 +19,12 @@ use hir_def::{ | |||
18 | use hir_expand::name::Name; | 19 | use hir_expand::name::Name; |
19 | 20 | ||
20 | use crate::{ | 21 | use 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 | ||
29 | pub struct HirFormatter<'a> { | 30 | pub struct HirFormatter<'a> { |
@@ -290,6 +291,29 @@ impl HirDisplay for GenericArg { | |||
290 | } | 291 | } |
291 | } | 292 | } |
292 | 293 | ||
294 | impl HirDisplay for Const { | ||
295 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
296 | let data = self.interned(); | ||
297 | match data.value { | ||
298 | ConstValue::BoundVar(idx) => idx.hir_fmt(f), | ||
299 | ConstValue::InferenceVar(..) => write!(f, "_"), | ||
300 | ConstValue::Placeholder(idx) => { | ||
301 | let id = const_from_placeholder_idx(f.db, idx); | ||
302 | let generics = generics(f.db.upcast(), id.parent); | ||
303 | let param_data = &generics.params.consts[id.local_id]; | ||
304 | write!(f, "{}", param_data.name) | ||
305 | } | ||
306 | ConstValue::Concrete(_) => write!(f, "_"), | ||
307 | } | ||
308 | } | ||
309 | } | ||
310 | |||
311 | impl HirDisplay for BoundVar { | ||
312 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
313 | write!(f, "?{}.{}", self.debruijn.depth(), self.index) | ||
314 | } | ||
315 | } | ||
316 | |||
293 | impl HirDisplay for Ty { | 317 | impl 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 { | |||
850 | impl HirDisplay for LifetimeData { | 876 | impl 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 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, |
45 | to_assoc_type_id, 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 @@ | |||
7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; | 7 | use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; |
8 | use hir_def::lang_item::LangItemTarget; | 8 | use hir_def::lang_item::LangItemTarget; |
9 | 9 | ||
10 | use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind}; | 10 | use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyExt, TyKind}; |
11 | 11 | ||
12 | use super::{InEnvironment, InferenceContext}; | 12 | use 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; | |||
15 | use syntax::ast::RangeOp; | 15 | use syntax::ast::RangeOp; |
16 | 16 | ||
17 | use crate::{ | 17 | use crate::{ |
18 | autoderef, | 18 | autoderef, dummy_usize_const, |
19 | lower::lower_to_chalk_mutability, | 19 | lower::lower_to_chalk_mutability, |
20 | method_resolution, op, | 20 | method_resolution, op, |
21 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
@@ -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 | ||
29 | use super::{ | 30 | use 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; | |||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use 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 | ||
20 | impl<'a> InferenceContext<'a> { | 20 | impl<'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 | }; |
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | 12 | ||
13 | use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; | 13 | use crate::{ |
14 | method_resolution, Interner, Substitution, Ty, TyBuilder, TyExt, TyKind, ValueTyDefId, | ||
15 | }; | ||
14 | 16 | ||
15 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 17 | use 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 | ||
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | 32 | ||
33 | use itertools::Itertools; | ||
34 | |||
35 | use base_db::salsa; | 33 | use base_db::salsa; |
34 | use chalk_ir::UintTy; | ||
36 | use hir_def::{ | 35 | use 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 | ||
41 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; | 40 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; |
@@ -71,6 +70,11 @@ pub type Lifetime = chalk_ir::Lifetime<Interner>; | |||
71 | pub type LifetimeData = chalk_ir::LifetimeData<Interner>; | 70 | pub type LifetimeData = chalk_ir::LifetimeData<Interner>; |
72 | pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; | 71 | pub type LifetimeOutlives = chalk_ir::LifetimeOutlives<Interner>; |
73 | 72 | ||
73 | pub type Const = chalk_ir::Const<Interner>; | ||
74 | pub type ConstData = chalk_ir::ConstData<Interner>; | ||
75 | pub type ConstValue = chalk_ir::ConstValue<Interner>; | ||
76 | pub type ConcreteConst = chalk_ir::ConcreteConst<Interner>; | ||
77 | |||
74 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 78 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
75 | 79 | ||
76 | pub type FnSig = chalk_ir::FnSig<Interner>; | 80 | pub type FnSig = chalk_ir::FnSig<Interner>; |
@@ -165,69 +169,12 @@ impl CallableSig { | |||
165 | } | 169 | } |
166 | 170 | ||
167 | impl Ty { | 171 | impl 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, ¶meters)) | ||
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 | ||
291 | pub 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 | |||
491 | pub fn to_chalk_trait_id(id: TraitId) -> ChalkTraitId { | 297 | pub 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 { | |||
499 | pub fn static_lifetime() -> Lifetime { | 305 | pub fn static_lifetime() -> Lifetime { |
500 | LifetimeData::Static.intern(&Interner) | 306 | LifetimeData::Static.intern(&Interner) |
501 | } | 307 | } |
308 | |||
309 | pub 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 | ||
28 | use crate::{ | 28 | use 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 | }; |
27 | use mapping::{ | 27 | use 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; | |||
10 | use hir_def::{GenericDefId, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | ||
18 | use super::interner::*; | 19 | use 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. |
206 | fn array_to_chalk(db: &dyn HirDatabase, ty: Ty) -> chalk_ir::Ty<Interner> { | 207 | fn 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 | ||
217 | impl ToChalk for GenericArg { | 212 | impl 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::{ | |||
10 | use smallvec::SmallVec; | 10 | use smallvec::SmallVec; |
11 | 11 | ||
12 | use crate::{ | 12 | use 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 | }; |
14 | use hir_def::FunctionId; | 14 | use hir_def::FunctionId; |
15 | use hir_ty::TypeWalk; | 15 | use hir_ty::{TyExt, TypeWalk}; |
16 | use ide::{AnalysisHost, RootDatabase}; | 16 | use ide::{AnalysisHost, RootDatabase}; |
17 | use ide_db::base_db::{ | 17 | use 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" | |||
14 | fst = "0.4" | 14 | fst = "0.4" |
15 | 15 | ||
16 | paths = { path = "../paths", version = "0.0.0" } | 16 | paths = { path = "../paths", version = "0.0.0" } |
17 | indexmap = "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. |
4 | use rustc_hash::FxHashMap; | 4 | use std::hash::BuildHasherDefault; |
5 | |||
6 | use indexmap::IndexSet; | ||
7 | use rustc_hash::FxHasher; | ||
5 | 8 | ||
6 | use crate::{FileId, VfsPath}; | 9 | use crate::{FileId, VfsPath}; |
7 | 10 | ||
8 | /// Structure to map between [`VfsPath`] and [`FileId`]. | 11 | /// Structure to map between [`VfsPath`] and [`FileId`]. |
9 | #[derive(Default)] | ||
10 | pub(crate) struct PathInterner { | 12 | pub(crate) struct PathInterner { |
11 | map: FxHashMap<VfsPath, FileId>, | 13 | map: IndexSet<VfsPath, BuildHasherDefault<FxHasher>>, |
12 | vec: Vec<VfsPath>, | 14 | } |
15 | |||
16 | impl Default for PathInterner { | ||
17 | fn default() -> Self { | ||
18 | Self { map: IndexSet::default() } | ||
19 | } | ||
13 | } | 20 | } |
14 | 21 | ||
15 | impl PathInterner { | 22 | impl 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 | } |