diff options
70 files changed, 2086 insertions, 1453 deletions
diff --git a/Cargo.lock b/Cargo.lock index 4344f8df5..05383d8b7 100644 --- a/Cargo.lock +++ b/Cargo.lock | |||
@@ -37,9 +37,9 @@ dependencies = [ | |||
37 | 37 | ||
38 | [[package]] | 38 | [[package]] |
39 | name = "anyhow" | 39 | name = "anyhow" |
40 | version = "1.0.39" | 40 | version = "1.0.40" |
41 | source = "registry+https://github.com/rust-lang/crates.io-index" | 41 | source = "registry+https://github.com/rust-lang/crates.io-index" |
42 | checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767" | 42 | checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b" |
43 | 43 | ||
44 | [[package]] | 44 | [[package]] |
45 | name = "anymap" | 45 | name = "anymap" |
@@ -49,9 +49,9 @@ checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344" | |||
49 | 49 | ||
50 | [[package]] | 50 | [[package]] |
51 | name = "arrayvec" | 51 | name = "arrayvec" |
52 | version = "0.6.0" | 52 | version = "0.6.1" |
53 | source = "registry+https://github.com/rust-lang/crates.io-index" | 53 | source = "registry+https://github.com/rust-lang/crates.io-index" |
54 | checksum = "682f88bd1270f264991da8922b89ee1fb520b0da73f97c9f73cda54980123017" | 54 | checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9" |
55 | 55 | ||
56 | [[package]] | 56 | [[package]] |
57 | name = "atty" | 57 | name = "atty" |
@@ -797,9 +797,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" | |||
797 | 797 | ||
798 | [[package]] | 798 | [[package]] |
799 | name = "libc" | 799 | name = "libc" |
800 | version = "0.2.91" | 800 | version = "0.2.92" |
801 | source = "registry+https://github.com/rust-lang/crates.io-index" | 801 | source = "registry+https://github.com/rust-lang/crates.io-index" |
802 | checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" | 802 | checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714" |
803 | 803 | ||
804 | [[package]] | 804 | [[package]] |
805 | name = "libloading" | 805 | name = "libloading" |
@@ -822,9 +822,9 @@ dependencies = [ | |||
822 | 822 | ||
823 | [[package]] | 823 | [[package]] |
824 | name = "lock_api" | 824 | name = "lock_api" |
825 | version = "0.4.2" | 825 | version = "0.4.3" |
826 | source = "registry+https://github.com/rust-lang/crates.io-index" | 826 | source = "registry+https://github.com/rust-lang/crates.io-index" |
827 | checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" | 827 | checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176" |
828 | dependencies = [ | 828 | dependencies = [ |
829 | "scopeguard", | 829 | "scopeguard", |
830 | ] | 830 | ] |
@@ -921,9 +921,9 @@ dependencies = [ | |||
921 | 921 | ||
922 | [[package]] | 922 | [[package]] |
923 | name = "memoffset" | 923 | name = "memoffset" |
924 | version = "0.6.1" | 924 | version = "0.6.3" |
925 | source = "registry+https://github.com/rust-lang/crates.io-index" | 925 | source = "registry+https://github.com/rust-lang/crates.io-index" |
926 | checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" | 926 | checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d" |
927 | dependencies = [ | 927 | dependencies = [ |
928 | "autocfg", | 928 | "autocfg", |
929 | ] | 929 | ] |
@@ -1157,9 +1157,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" | |||
1157 | 1157 | ||
1158 | [[package]] | 1158 | [[package]] |
1159 | name = "proc-macro2" | 1159 | name = "proc-macro2" |
1160 | version = "1.0.24" | 1160 | version = "1.0.26" |
1161 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1161 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1162 | checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" | 1162 | checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" |
1163 | dependencies = [ | 1163 | dependencies = [ |
1164 | "unicode-xid", | 1164 | "unicode-xid", |
1165 | ] | 1165 | ] |
@@ -1577,9 +1577,9 @@ dependencies = [ | |||
1577 | 1577 | ||
1578 | [[package]] | 1578 | [[package]] |
1579 | name = "syn" | 1579 | name = "syn" |
1580 | version = "1.0.64" | 1580 | version = "1.0.68" |
1581 | source = "registry+https://github.com/rust-lang/crates.io-index" | 1581 | source = "registry+https://github.com/rust-lang/crates.io-index" |
1582 | checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" | 1582 | checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87" |
1583 | dependencies = [ | 1583 | dependencies = [ |
1584 | "proc-macro2", | 1584 | "proc-macro2", |
1585 | "quote", | 1585 | "quote", |
diff --git a/crates/cfg/src/tests.rs b/crates/cfg/src/tests.rs index bd0f9ec48..d8736c893 100644 --- a/crates/cfg/src/tests.rs +++ b/crates/cfg/src/tests.rs | |||
@@ -8,7 +8,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) { | |||
8 | let (tt, _) = { | 8 | let (tt, _) = { |
9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
11 | ast_to_token_tree(&tt).unwrap() | 11 | ast_to_token_tree(&tt) |
12 | }; | 12 | }; |
13 | let cfg = CfgExpr::parse(&tt); | 13 | let cfg = CfgExpr::parse(&tt); |
14 | assert_eq!(cfg, expected); | 14 | assert_eq!(cfg, expected); |
@@ -18,7 +18,7 @@ fn check_dnf(input: &str, expect: Expect) { | |||
18 | let (tt, _) = { | 18 | let (tt, _) = { |
19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
21 | ast_to_token_tree(&tt).unwrap() | 21 | ast_to_token_tree(&tt) |
22 | }; | 22 | }; |
23 | let cfg = CfgExpr::parse(&tt); | 23 | let cfg = CfgExpr::parse(&tt); |
24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); | 24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); |
@@ -29,7 +29,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { | |||
29 | let (tt, _) = { | 29 | let (tt, _) = { |
30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
32 | ast_to_token_tree(&tt).unwrap() | 32 | ast_to_token_tree(&tt) |
33 | }; | 33 | }; |
34 | let cfg = CfgExpr::parse(&tt); | 34 | let cfg = CfgExpr::parse(&tt); |
35 | let dnf = DnfExpr::new(cfg); | 35 | let dnf = DnfExpr::new(cfg); |
@@ -42,7 +42,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { | |||
42 | let (tt, _) = { | 42 | let (tt, _) = { |
43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
45 | ast_to_token_tree(&tt).unwrap() | 45 | ast_to_token_tree(&tt) |
46 | }; | 46 | }; |
47 | let cfg = CfgExpr::parse(&tt); | 47 | let cfg = CfgExpr::parse(&tt); |
48 | let dnf = DnfExpr::new(cfg); | 48 | let dnf = DnfExpr::new(cfg); |
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 1902a8d16..df5758342 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -1,14 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::*; |
4 | AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, | ||
5 | CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, | ||
6 | ExprScopesQuery, FileItemTreeQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, | ||
7 | ImportMapQuery, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, | ||
8 | InternFunctionQuery, InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, | ||
9 | InternTypeAliasQuery, InternUnionQuery, LangItemQuery, StaticDataQuery, StructDataQuery, | ||
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | ||
11 | }; | ||
12 | pub use hir_expand::db::{ | 4 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, | 5 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, |
14 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, | 6 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, |
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index ab04c55bc..993772aac 100644 --- a/crates/hir/src/display.rs +++ b/crates/hir/src/display.rs | |||
@@ -13,29 +13,28 @@ use syntax::ast::{self, NameOwner}; | |||
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, | 15 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, |
16 | Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, | 16 | Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | impl HirDisplay for Function { | 19 | impl HirDisplay for Function { |
20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
21 | let data = f.db.function_data(self.id); | 21 | let data = f.db.function_data(self.id); |
22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | 22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; |
23 | let qual = &data.qualifier; | 23 | if data.is_default() { |
24 | if qual.is_default { | ||
25 | write!(f, "default ")?; | 24 | write!(f, "default ")?; |
26 | } | 25 | } |
27 | if qual.is_const { | 26 | if data.is_const() { |
28 | write!(f, "const ")?; | 27 | write!(f, "const ")?; |
29 | } | 28 | } |
30 | if qual.is_async { | 29 | if data.is_async() { |
31 | write!(f, "async ")?; | 30 | write!(f, "async ")?; |
32 | } | 31 | } |
33 | if qual.is_unsafe { | 32 | if data.is_unsafe() { |
34 | write!(f, "unsafe ")?; | 33 | write!(f, "unsafe ")?; |
35 | } | 34 | } |
36 | if let Some(abi) = &qual.abi { | 35 | if let Some(abi) = &data.abi { |
37 | // FIXME: String escape? | 36 | // FIXME: String escape? |
38 | write!(f, "extern \"{}\" ", abi)?; | 37 | write!(f, "extern \"{}\" ", &**abi)?; |
39 | } | 38 | } |
40 | write!(f, "fn {}", data.name)?; | 39 | write!(f, "fn {}", data.name)?; |
41 | 40 | ||
@@ -68,7 +67,7 @@ impl HirDisplay for Function { | |||
68 | write!(f, ", ")?; | 67 | write!(f, ", ")?; |
69 | } else { | 68 | } else { |
70 | first = false; | 69 | first = false; |
71 | if data.has_self_param { | 70 | if data.has_self_param() { |
72 | write_self_param(type_ref, f)?; | 71 | write_self_param(type_ref, f)?; |
73 | continue; | 72 | continue; |
74 | } | 73 | } |
@@ -88,7 +87,7 @@ impl HirDisplay for Function { | |||
88 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. | 87 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. |
89 | // Use ugly pattern match to strip the Future trait. | 88 | // Use ugly pattern match to strip the Future trait. |
90 | // Better way? | 89 | // Better way? |
91 | let ret_type = if !qual.is_async { | 90 | let ret_type = if !data.is_async() { |
92 | &data.ret_type | 91 | &data.ret_type |
93 | } else { | 92 | } else { |
94 | match &*data.ret_type { | 93 | match &*data.ret_type { |
@@ -235,7 +234,7 @@ impl HirDisplay for TypeParam { | |||
235 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 234 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
236 | write!(f, "{}", self.name(f.db))?; | 235 | write!(f, "{}", self.name(f.db))?; |
237 | let bounds = f.db.generic_predicates_for_param(self.id); | 236 | let bounds = f.db.generic_predicates_for_param(self.id); |
238 | let substs = Substitution::type_params(f.db, self.id.parent); | 237 | let substs = TyBuilder::type_params_subst(f.db, self.id.parent); |
239 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | 238 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); |
240 | if !(predicates.is_empty() || f.omit_verbose_types()) { | 239 | if !(predicates.is_empty() || f.omit_verbose_types()) { |
241 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | 240 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 29010191b..e41efb385 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -55,11 +55,11 @@ use hir_ty::{ | |||
55 | autoderef, could_unify, | 55 | autoderef, could_unify, |
56 | method_resolution::{self, TyFingerprint}, | 56 | method_resolution::{self, TyFingerprint}, |
57 | primitive::UintTy, | 57 | primitive::UintTy, |
58 | to_assoc_type_id, | 58 | traits::FnTrait, |
59 | traits::{FnTrait, Solution, SolutionVariables}, | ||
60 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, |
61 | DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, | 60 | DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution, |
62 | Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, | 61 | SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, |
62 | TyVariableKind, WhereClause, | ||
63 | }; | 63 | }; |
64 | use itertools::Itertools; | 64 | use itertools::Itertools; |
65 | use rustc_hash::FxHashSet; | 65 | use rustc_hash::FxHashSet; |
@@ -515,7 +515,7 @@ impl Field { | |||
515 | VariantDef::Union(it) => it.id.into(), | 515 | VariantDef::Union(it) => it.id.into(), |
516 | VariantDef::Variant(it) => it.parent.id.into(), | 516 | VariantDef::Variant(it) => it.parent.id.into(), |
517 | }; | 517 | }; |
518 | let substs = Substitution::type_params(db, generic_def_id); | 518 | let substs = TyBuilder::type_params_subst(db, generic_def_id); |
519 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); | 519 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); |
520 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) | 520 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) |
521 | } | 521 | } |
@@ -832,7 +832,7 @@ impl Function { | |||
832 | } | 832 | } |
833 | 833 | ||
834 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { | 834 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { |
835 | if !db.function_data(self.id).has_self_param { | 835 | if !db.function_data(self.id).has_self_param() { |
836 | return None; | 836 | return None; |
837 | } | 837 | } |
838 | Some(SelfParam { func: self.id }) | 838 | Some(SelfParam { func: self.id }) |
@@ -864,7 +864,7 @@ impl Function { | |||
864 | } | 864 | } |
865 | 865 | ||
866 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | 866 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { |
867 | db.function_data(self.id).qualifier.is_unsafe | 867 | db.function_data(self.id).is_unsafe() |
868 | } | 868 | } |
869 | 869 | ||
870 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 870 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
@@ -878,7 +878,7 @@ impl Function { | |||
878 | /// | 878 | /// |
879 | /// This is false in the case of required (not provided) trait methods. | 879 | /// This is false in the case of required (not provided) trait methods. |
880 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | 880 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { |
881 | db.function_data(self.id).has_body | 881 | db.function_data(self.id).has_body() |
882 | } | 882 | } |
883 | 883 | ||
884 | /// A textual representation of the HIR of this function for debugging purposes. | 884 | /// A textual representation of the HIR of this function for debugging purposes. |
@@ -1129,7 +1129,7 @@ pub struct BuiltinType { | |||
1129 | impl BuiltinType { | 1129 | impl BuiltinType { |
1130 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { | 1130 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { |
1131 | let resolver = module.id.resolver(db.upcast()); | 1131 | let resolver = module.id.resolver(db.upcast()); |
1132 | Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) | 1132 | Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner)) |
1133 | .expect("crate not present in resolver") | 1133 | .expect("crate not present in resolver") |
1134 | } | 1134 | } |
1135 | 1135 | ||
@@ -1502,7 +1502,7 @@ impl TypeParam { | |||
1502 | let resolver = self.id.parent.resolver(db.upcast()); | 1502 | let resolver = self.id.parent.resolver(db.upcast()); |
1503 | let krate = self.id.parent.module(db.upcast()).krate(); | 1503 | let krate = self.id.parent.module(db.upcast()).krate(); |
1504 | let ty = params.get(local_idx)?.clone(); | 1504 | let ty = params.get(local_idx)?.clone(); |
1505 | let subst = Substitution::type_params(db, self.id.parent); | 1505 | let subst = TyBuilder::type_params_subst(db, self.id.parent); |
1506 | let ty = ty.subst(&subst.prefix(local_idx)); | 1506 | let ty = ty.subst(&subst.prefix(local_idx)); |
1507 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) | 1507 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) |
1508 | } | 1508 | } |
@@ -1703,10 +1703,9 @@ impl Type { | |||
1703 | fn from_def( | 1703 | fn from_def( |
1704 | db: &dyn HirDatabase, | 1704 | db: &dyn HirDatabase, |
1705 | krate: CrateId, | 1705 | krate: CrateId, |
1706 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, | 1706 | def: impl HasResolver + Into<TyDefId>, |
1707 | ) -> Type { | 1707 | ) -> Type { |
1708 | let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); | 1708 | let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build(); |
1709 | let ty = db.ty(def.into()).subst(&substs); | ||
1710 | Type::new(db, krate, def, ty) | 1709 | Type::new(db, krate, def, ty) |
1711 | } | 1710 | } |
1712 | 1711 | ||
@@ -1785,13 +1784,10 @@ impl Type { | |||
1785 | } | 1784 | } |
1786 | 1785 | ||
1787 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { | 1786 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { |
1788 | let trait_ref = hir_ty::TraitRef { | 1787 | let trait_ref = TyBuilder::trait_ref(db, trait_.id) |
1789 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), | 1788 | .push(self.ty.clone()) |
1790 | substitution: Substitution::build_for_def(db, trait_.id) | 1789 | .fill(args.iter().map(|t| t.ty.clone())) |
1791 | .push(self.ty.clone()) | 1790 | .build(); |
1792 | .fill(args.iter().map(|t| t.ty.clone())) | ||
1793 | .build(), | ||
1794 | }; | ||
1795 | 1791 | ||
1796 | let goal = Canonical { | 1792 | let goal = Canonical { |
1797 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), | 1793 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), |
@@ -1804,11 +1800,10 @@ impl Type { | |||
1804 | pub fn normalize_trait_assoc_type( | 1800 | pub fn normalize_trait_assoc_type( |
1805 | &self, | 1801 | &self, |
1806 | db: &dyn HirDatabase, | 1802 | db: &dyn HirDatabase, |
1807 | trait_: Trait, | ||
1808 | args: &[Type], | 1803 | args: &[Type], |
1809 | alias: TypeAlias, | 1804 | alias: TypeAlias, |
1810 | ) -> Option<Type> { | 1805 | ) -> Option<Type> { |
1811 | let subst = Substitution::build_for_def(db, trait_.id) | 1806 | let projection = TyBuilder::assoc_type_projection(db, alias.id) |
1812 | .push(self.ty.clone()) | 1807 | .push(self.ty.clone()) |
1813 | .fill(args.iter().map(|t| t.ty.clone())) | 1808 | .fill(args.iter().map(|t| t.ty.clone())) |
1814 | .build(); | 1809 | .build(); |
@@ -1816,10 +1811,7 @@ impl Type { | |||
1816 | InEnvironment::new( | 1811 | InEnvironment::new( |
1817 | self.env.env.clone(), | 1812 | self.env.env.clone(), |
1818 | AliasEq { | 1813 | AliasEq { |
1819 | alias: AliasTy::Projection(ProjectionTy { | 1814 | alias: AliasTy::Projection(projection), |
1820 | associated_ty_id: to_assoc_type_id(alias.id), | ||
1821 | substitution: subst, | ||
1822 | }), | ||
1823 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) | 1815 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) |
1824 | .intern(&Interner), | 1816 | .intern(&Interner), |
1825 | } | 1817 | } |
@@ -1831,7 +1823,7 @@ impl Type { | |||
1831 | match db.trait_solve(self.krate, goal)? { | 1823 | match db.trait_solve(self.krate, goal)? { |
1832 | Solution::Unique(SolutionVariables(subst)) => subst | 1824 | Solution::Unique(SolutionVariables(subst)) => subst |
1833 | .value | 1825 | .value |
1834 | .interned(&Interner) | 1826 | .interned() |
1835 | .first() | 1827 | .first() |
1836 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), | 1828 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), |
1837 | Solution::Ambig(_) => None, | 1829 | Solution::Ambig(_) => None, |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 2bab121d9..442c5fb5b 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -533,7 +533,7 @@ impl Attr { | |||
533 | }; | 533 | }; |
534 | Some(AttrInput::Literal(value)) | 534 | Some(AttrInput::Literal(value)) |
535 | } else if let Some(tt) = ast.token_tree() { | 535 | } else if let Some(tt) = ast.token_tree() { |
536 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | 536 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0)) |
537 | } else { | 537 | } else { |
538 | None | 538 | None |
539 | }; | 539 | }; |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 1080d9c2c..96b959967 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -226,7 +226,7 @@ pub struct Body { | |||
226 | /// The `ExprId` of the actual body expression. | 226 | /// The `ExprId` of the actual body expression. |
227 | pub body_expr: ExprId, | 227 | pub body_expr: ExprId, |
228 | /// Block expressions in this body that may contain inner items. | 228 | /// Block expressions in this body that may contain inner items. |
229 | pub block_scopes: Vec<BlockId>, | 229 | block_scopes: Vec<BlockId>, |
230 | _c: Count<Self>, | 230 | _c: Count<Self>, |
231 | } | 231 | } |
232 | 232 | ||
@@ -302,7 +302,8 @@ impl Body { | |||
302 | } | 302 | } |
303 | }; | 303 | }; |
304 | let expander = Expander::new(db, file_id, module); | 304 | let expander = Expander::new(db, file_id, module); |
305 | let (body, source_map) = Body::new(db, expander, params, body); | 305 | let (mut body, source_map) = Body::new(db, expander, params, body); |
306 | body.shrink_to_fit(); | ||
306 | (Arc::new(body), Arc::new(source_map)) | 307 | (Arc::new(body), Arc::new(source_map)) |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,6 +311,16 @@ impl Body { | |||
310 | db.body_with_source_map(def).0 | 311 | db.body_with_source_map(def).0 |
311 | } | 312 | } |
312 | 313 | ||
314 | /// Returns an iterator over all block expressions in this body that define inner items. | ||
315 | pub fn blocks<'a>( | ||
316 | &'a self, | ||
317 | db: &'a dyn DefDatabase, | ||
318 | ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ { | ||
319 | self.block_scopes | ||
320 | .iter() | ||
321 | .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap"))) | ||
322 | } | ||
323 | |||
313 | fn new( | 324 | fn new( |
314 | db: &dyn DefDatabase, | 325 | db: &dyn DefDatabase, |
315 | expander: Expander, | 326 | expander: Expander, |
@@ -318,6 +329,15 @@ impl Body { | |||
318 | ) -> (Body, BodySourceMap) { | 329 | ) -> (Body, BodySourceMap) { |
319 | lower::lower(db, expander, params, body) | 330 | lower::lower(db, expander, params, body) |
320 | } | 331 | } |
332 | |||
333 | fn shrink_to_fit(&mut self) { | ||
334 | let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self; | ||
335 | block_scopes.shrink_to_fit(); | ||
336 | exprs.shrink_to_fit(); | ||
337 | labels.shrink_to_fit(); | ||
338 | params.shrink_to_fit(); | ||
339 | pats.shrink_to_fit(); | ||
340 | } | ||
321 | } | 341 | } |
322 | 342 | ||
323 | impl Index<ExprId> for Body { | 343 | impl Index<ExprId> for Body { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 229e81dd4..63e89a1f4 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -673,12 +673,14 @@ impl ExprCollector<'_> { | |||
673 | let block_loc = | 673 | let block_loc = |
674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
675 | let block_id = self.db.intern_block(block_loc); | 675 | let block_id = self.db.intern_block(block_loc); |
676 | self.body.block_scopes.push(block_id); | ||
677 | 676 | ||
678 | let opt_def_map = self.db.block_def_map(block_id); | 677 | let (module, def_map) = match self.db.block_def_map(block_id) { |
679 | let has_def_map = opt_def_map.is_some(); | 678 | Some(def_map) => { |
680 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 679 | self.body.block_scopes.push(block_id); |
681 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | 680 | (def_map.root(), def_map) |
681 | } | ||
682 | None => (self.expander.module, self.expander.def_map.clone()), | ||
683 | }; | ||
682 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 684 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
683 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 685 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
684 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 686 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 2a331dcaf..f40a7f80d 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -160,7 +160,7 @@ impl ChildBySource for EnumId { | |||
160 | impl ChildBySource for DefWithBodyId { | 160 | impl ChildBySource for DefWithBodyId { |
161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | 161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
162 | let body = db.body(*self); | 162 | let body = db.body(*self); |
163 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 163 | for (_, def_map) in body.blocks(db) { |
164 | // All block expressions are merged into the same map, because they logically all add | 164 | // All block expressions are merged into the same map, because they logically all add |
165 | // inner items to the containing `DefWithBodyId`. | 165 | // inner items to the containing `DefWithBodyId`. |
166 | def_map[def_map.root()].scope.child_by_source_to(db, res); | 166 | def_map[def_map.root()].scope.child_by_source_to(db, res); |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 31f994681..135a6698e 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | intern::Interned, | 12 | intern::Interned, |
13 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 13 | item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, |
14 | type_ref::{TraitRef, TypeBound, TypeRef}, | 14 | type_ref::{TraitRef, TypeBound, TypeRef}, |
15 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -23,14 +23,9 @@ pub struct FunctionData { | |||
23 | pub params: Vec<Interned<TypeRef>>, | 23 | pub params: Vec<Interned<TypeRef>>, |
24 | pub ret_type: Interned<TypeRef>, | 24 | pub ret_type: Interned<TypeRef>, |
25 | pub attrs: Attrs, | 25 | pub attrs: Attrs, |
26 | /// True if the first param is `self`. This is relevant to decide whether this | ||
27 | /// can be called as a method. | ||
28 | pub has_self_param: bool, | ||
29 | pub has_body: bool, | ||
30 | pub qualifier: FunctionQualifier, | ||
31 | pub is_in_extern_block: bool, | ||
32 | pub is_varargs: bool, | ||
33 | pub visibility: RawVisibility, | 26 | pub visibility: RawVisibility, |
27 | pub abi: Option<Interned<str>>, | ||
28 | flags: FnFlags, | ||
34 | } | 29 | } |
35 | 30 | ||
36 | impl FunctionData { | 31 | impl FunctionData { |
@@ -53,6 +48,11 @@ impl FunctionData { | |||
53 | .next_back() | 48 | .next_back() |
54 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | 49 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); |
55 | 50 | ||
51 | let mut flags = func.flags; | ||
52 | if is_varargs { | ||
53 | flags.bits |= FnFlags::IS_VARARGS; | ||
54 | } | ||
55 | |||
56 | Arc::new(FunctionData { | 56 | Arc::new(FunctionData { |
57 | name: func.name.clone(), | 57 | name: func.name.clone(), |
58 | params: enabled_params | 58 | params: enabled_params |
@@ -64,14 +64,45 @@ impl FunctionData { | |||
64 | .collect(), | 64 | .collect(), |
65 | ret_type: func.ret_type.clone(), | 65 | ret_type: func.ret_type.clone(), |
66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
67 | has_self_param: func.has_self_param, | ||
68 | has_body: func.has_body, | ||
69 | qualifier: func.qualifier.clone(), | ||
70 | is_in_extern_block: func.is_in_extern_block, | ||
71 | is_varargs, | ||
72 | visibility: item_tree[func.visibility].clone(), | 67 | visibility: item_tree[func.visibility].clone(), |
68 | abi: func.abi.clone(), | ||
69 | flags, | ||
73 | }) | 70 | }) |
74 | } | 71 | } |
72 | |||
73 | pub fn has_body(&self) -> bool { | ||
74 | self.flags.bits & FnFlags::HAS_BODY != 0 | ||
75 | } | ||
76 | |||
77 | /// True if the first param is `self`. This is relevant to decide whether this | ||
78 | /// can be called as a method. | ||
79 | pub fn has_self_param(&self) -> bool { | ||
80 | self.flags.bits & FnFlags::HAS_SELF_PARAM != 0 | ||
81 | } | ||
82 | |||
83 | pub fn is_default(&self) -> bool { | ||
84 | self.flags.bits & FnFlags::IS_DEFAULT != 0 | ||
85 | } | ||
86 | |||
87 | pub fn is_const(&self) -> bool { | ||
88 | self.flags.bits & FnFlags::IS_CONST != 0 | ||
89 | } | ||
90 | |||
91 | pub fn is_async(&self) -> bool { | ||
92 | self.flags.bits & FnFlags::IS_ASYNC != 0 | ||
93 | } | ||
94 | |||
95 | pub fn is_unsafe(&self) -> bool { | ||
96 | self.flags.bits & FnFlags::IS_UNSAFE != 0 | ||
97 | } | ||
98 | |||
99 | pub fn is_in_extern_block(&self) -> bool { | ||
100 | self.flags.bits & FnFlags::IS_IN_EXTERN_BLOCK != 0 | ||
101 | } | ||
102 | |||
103 | pub fn is_varargs(&self) -> bool { | ||
104 | self.flags.bits & FnFlags::IS_VARARGS != 0 | ||
105 | } | ||
75 | } | 106 | } |
76 | 107 | ||
77 | #[derive(Debug, Clone, PartialEq, Eq)] | 108 | #[derive(Debug, Clone, PartialEq, Eq)] |
diff --git a/crates/hir_def/src/db.rs b/crates/hir_def/src/db.rs index 068b2ee38..9b7a213a1 100644 --- a/crates/hir_def/src/db.rs +++ b/crates/hir_def/src/db.rs | |||
@@ -13,6 +13,7 @@ use crate::{ | |||
13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, | 13 | data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, |
14 | generics::GenericParams, | 14 | generics::GenericParams, |
15 | import_map::ImportMap, | 15 | import_map::ImportMap, |
16 | intern::Interned, | ||
16 | item_tree::ItemTree, | 17 | item_tree::ItemTree, |
17 | lang_item::{LangItemTarget, LangItems}, | 18 | lang_item::{LangItemTarget, LangItems}, |
18 | nameres::DefMap, | 19 | nameres::DefMap, |
@@ -113,7 +114,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> { | |||
113 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; | 114 | fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; |
114 | 115 | ||
115 | #[salsa::invoke(GenericParams::generic_params_query)] | 116 | #[salsa::invoke(GenericParams::generic_params_query)] |
116 | fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; | 117 | fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>; |
117 | 118 | ||
118 | #[salsa::invoke(Attrs::variants_attrs_query)] | 119 | #[salsa::invoke(Attrs::variants_attrs_query)] |
119 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; | 120 | fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; |
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs index 7c6cbff11..de5acced8 100644 --- a/crates/hir_def/src/generics.rs +++ b/crates/hir_def/src/generics.rs | |||
@@ -2,7 +2,6 @@ | |||
2 | //! structs, impls, traits, etc. This module provides a common HIR for these | 2 | //! structs, impls, traits, etc. This module provides a common HIR for these |
3 | //! generic parameters. See also the `Generics` type and the `generics_of` query | 3 | //! generic parameters. See also the `Generics` type and the `generics_of` query |
4 | //! in rustc. | 4 | //! in rustc. |
5 | use std::sync::Arc; | ||
6 | 5 | ||
7 | use base_db::FileId; | 6 | use base_db::FileId; |
8 | use either::Either; | 7 | use either::Either; |
@@ -18,6 +17,7 @@ use crate::{ | |||
18 | child_by_source::ChildBySource, | 17 | child_by_source::ChildBySource, |
19 | db::DefDatabase, | 18 | db::DefDatabase, |
20 | dyn_map::DynMap, | 19 | dyn_map::DynMap, |
20 | intern::Interned, | ||
21 | keys, | 21 | keys, |
22 | src::{HasChildSource, HasSource}, | 22 | src::{HasChildSource, HasSource}, |
23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, | 23 | type_ref::{LifetimeRef, TypeBound, TypeRef}, |
@@ -26,27 +26,27 @@ use crate::{ | |||
26 | }; | 26 | }; |
27 | 27 | ||
28 | /// Data about a generic type parameter (to a function, struct, impl, ...). | 28 | /// Data about a generic type parameter (to a function, struct, impl, ...). |
29 | #[derive(Clone, PartialEq, Eq, Debug)] | 29 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
30 | pub struct TypeParamData { | 30 | pub struct TypeParamData { |
31 | pub name: Option<Name>, | 31 | pub name: Option<Name>, |
32 | pub default: Option<TypeRef>, | 32 | pub default: Option<Interned<TypeRef>>, |
33 | pub provenance: TypeParamProvenance, | 33 | pub provenance: TypeParamProvenance, |
34 | } | 34 | } |
35 | 35 | ||
36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). | 36 | /// Data about a generic lifetime parameter (to a function, struct, impl, ...). |
37 | #[derive(Clone, PartialEq, Eq, Debug)] | 37 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
38 | pub struct LifetimeParamData { | 38 | pub struct LifetimeParamData { |
39 | pub name: Name, | 39 | pub name: Name, |
40 | } | 40 | } |
41 | 41 | ||
42 | /// Data about a generic const parameter (to a function, struct, impl, ...). | 42 | /// Data about a generic const parameter (to a function, struct, impl, ...). |
43 | #[derive(Clone, PartialEq, Eq, Debug)] | 43 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
44 | pub struct ConstParamData { | 44 | pub struct ConstParamData { |
45 | pub name: Name, | 45 | pub name: Name, |
46 | pub ty: TypeRef, | 46 | pub ty: Interned<TypeRef>, |
47 | } | 47 | } |
48 | 48 | ||
49 | #[derive(Copy, Clone, PartialEq, Eq, Debug)] | 49 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
50 | pub enum TypeParamProvenance { | 50 | pub enum TypeParamProvenance { |
51 | TypeParamList, | 51 | TypeParamList, |
52 | TraitSelf, | 52 | TraitSelf, |
@@ -54,7 +54,7 @@ pub enum TypeParamProvenance { | |||
54 | } | 54 | } |
55 | 55 | ||
56 | /// Data about the generic parameters of a function, struct, impl, etc. | 56 | /// Data about the generic parameters of a function, struct, impl, etc. |
57 | #[derive(Clone, PartialEq, Eq, Debug, Default)] | 57 | #[derive(Clone, PartialEq, Eq, Debug, Default, Hash)] |
58 | pub struct GenericParams { | 58 | pub struct GenericParams { |
59 | pub types: Arena<TypeParamData>, | 59 | pub types: Arena<TypeParamData>, |
60 | pub lifetimes: Arena<LifetimeParamData>, | 60 | pub lifetimes: Arena<LifetimeParamData>, |
@@ -66,16 +66,16 @@ pub struct GenericParams { | |||
66 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. | 66 | /// where clauses like `where T: Foo + Bar` are turned into multiple of these. |
67 | /// It might still result in multiple actual predicates though, because of | 67 | /// It might still result in multiple actual predicates though, because of |
68 | /// associated type bindings like `Iterator<Item = u32>`. | 68 | /// associated type bindings like `Iterator<Item = u32>`. |
69 | #[derive(Clone, PartialEq, Eq, Debug)] | 69 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
70 | pub enum WherePredicate { | 70 | pub enum WherePredicate { |
71 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, | 71 | TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, |
72 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, | 72 | Lifetime { target: LifetimeRef, bound: LifetimeRef }, |
73 | ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, | 73 | ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, |
74 | } | 74 | } |
75 | 75 | ||
76 | #[derive(Clone, PartialEq, Eq, Debug)] | 76 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] |
77 | pub enum WherePredicateTypeTarget { | 77 | pub enum WherePredicateTypeTarget { |
78 | TypeRef(TypeRef), | 78 | TypeRef(Interned<TypeRef>), |
79 | /// For desugared where predicates that can directly refer to a type param. | 79 | /// For desugared where predicates that can directly refer to a type param. |
80 | TypeParam(LocalTypeParamId), | 80 | TypeParam(LocalTypeParamId), |
81 | } | 81 | } |
@@ -91,7 +91,7 @@ impl GenericParams { | |||
91 | pub(crate) fn generic_params_query( | 91 | pub(crate) fn generic_params_query( |
92 | db: &dyn DefDatabase, | 92 | db: &dyn DefDatabase, |
93 | def: GenericDefId, | 93 | def: GenericDefId, |
94 | ) -> Arc<GenericParams> { | 94 | ) -> Interned<GenericParams> { |
95 | let _p = profile::span("generic_params_query"); | 95 | let _p = profile::span("generic_params_query"); |
96 | 96 | ||
97 | let generics = match def { | 97 | let generics = match def { |
@@ -99,47 +99,49 @@ impl GenericParams { | |||
99 | let id = id.lookup(db).id; | 99 | let id = id.lookup(db).id; |
100 | let tree = id.item_tree(db); | 100 | let tree = id.item_tree(db); |
101 | let item = &tree[id.value]; | 101 | let item = &tree[id.value]; |
102 | tree[item.generic_params].clone() | 102 | item.generic_params.clone() |
103 | } | 103 | } |
104 | GenericDefId::AdtId(AdtId::StructId(id)) => { | 104 | GenericDefId::AdtId(AdtId::StructId(id)) => { |
105 | let id = id.lookup(db).id; | 105 | let id = id.lookup(db).id; |
106 | let tree = id.item_tree(db); | 106 | let tree = id.item_tree(db); |
107 | let item = &tree[id.value]; | 107 | let item = &tree[id.value]; |
108 | tree[item.generic_params].clone() | 108 | item.generic_params.clone() |
109 | } | 109 | } |
110 | GenericDefId::AdtId(AdtId::EnumId(id)) => { | 110 | GenericDefId::AdtId(AdtId::EnumId(id)) => { |
111 | let id = id.lookup(db).id; | 111 | let id = id.lookup(db).id; |
112 | let tree = id.item_tree(db); | 112 | let tree = id.item_tree(db); |
113 | let item = &tree[id.value]; | 113 | let item = &tree[id.value]; |
114 | tree[item.generic_params].clone() | 114 | item.generic_params.clone() |
115 | } | 115 | } |
116 | GenericDefId::AdtId(AdtId::UnionId(id)) => { | 116 | GenericDefId::AdtId(AdtId::UnionId(id)) => { |
117 | let id = id.lookup(db).id; | 117 | let id = id.lookup(db).id; |
118 | let tree = id.item_tree(db); | 118 | let tree = id.item_tree(db); |
119 | let item = &tree[id.value]; | 119 | let item = &tree[id.value]; |
120 | tree[item.generic_params].clone() | 120 | item.generic_params.clone() |
121 | } | 121 | } |
122 | GenericDefId::TraitId(id) => { | 122 | GenericDefId::TraitId(id) => { |
123 | let id = id.lookup(db).id; | 123 | let id = id.lookup(db).id; |
124 | let tree = id.item_tree(db); | 124 | let tree = id.item_tree(db); |
125 | let item = &tree[id.value]; | 125 | let item = &tree[id.value]; |
126 | tree[item.generic_params].clone() | 126 | item.generic_params.clone() |
127 | } | 127 | } |
128 | GenericDefId::TypeAliasId(id) => { | 128 | GenericDefId::TypeAliasId(id) => { |
129 | let id = id.lookup(db).id; | 129 | let id = id.lookup(db).id; |
130 | let tree = id.item_tree(db); | 130 | let tree = id.item_tree(db); |
131 | let item = &tree[id.value]; | 131 | let item = &tree[id.value]; |
132 | tree[item.generic_params].clone() | 132 | item.generic_params.clone() |
133 | } | 133 | } |
134 | GenericDefId::ImplId(id) => { | 134 | GenericDefId::ImplId(id) => { |
135 | let id = id.lookup(db).id; | 135 | let id = id.lookup(db).id; |
136 | let tree = id.item_tree(db); | 136 | let tree = id.item_tree(db); |
137 | let item = &tree[id.value]; | 137 | let item = &tree[id.value]; |
138 | tree[item.generic_params].clone() | 138 | item.generic_params.clone() |
139 | } | ||
140 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => { | ||
141 | Interned::new(GenericParams::default()) | ||
139 | } | 142 | } |
140 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(), | ||
141 | }; | 143 | }; |
142 | Arc::new(generics) | 144 | generics |
143 | } | 145 | } |
144 | 146 | ||
145 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { | 147 | fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { |
@@ -217,6 +219,7 @@ impl GenericParams { | |||
217 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), | 219 | GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), |
218 | }; | 220 | }; |
219 | 221 | ||
222 | generics.shrink_to_fit(); | ||
220 | (generics, InFile::new(file_id, sm)) | 223 | (generics, InFile::new(file_id, sm)) |
221 | } | 224 | } |
222 | 225 | ||
@@ -256,7 +259,8 @@ impl GenericParams { | |||
256 | for type_param in params.type_params() { | 259 | for type_param in params.type_params() { |
257 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); | 260 | let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); |
258 | // FIXME: Use `Path::from_src` | 261 | // FIXME: Use `Path::from_src` |
259 | let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it)); | 262 | let default = |
263 | type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it))); | ||
260 | let param = TypeParamData { | 264 | let param = TypeParamData { |
261 | name: Some(name.clone()), | 265 | name: Some(name.clone()), |
262 | default, | 266 | default, |
@@ -280,7 +284,7 @@ impl GenericParams { | |||
280 | for const_param in params.const_params() { | 284 | for const_param in params.const_params() { |
281 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); | 285 | let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); |
282 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); | 286 | let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); |
283 | let param = ConstParamData { name, ty }; | 287 | let param = ConstParamData { name, ty: Interned::new(ty) }; |
284 | let param_id = self.consts.alloc(param); | 288 | let param_id = self.consts.alloc(param); |
285 | sm.const_params.insert(param_id, const_param.clone()); | 289 | sm.const_params.insert(param_id, const_param.clone()); |
286 | } | 290 | } |
@@ -334,11 +338,11 @@ impl GenericParams { | |||
334 | (Either::Left(type_ref), bound) => match hrtb_lifetimes { | 338 | (Either::Left(type_ref), bound) => match hrtb_lifetimes { |
335 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { | 339 | Some(hrtb_lifetimes) => WherePredicate::ForLifetime { |
336 | lifetimes: hrtb_lifetimes.clone(), | 340 | lifetimes: hrtb_lifetimes.clone(), |
337 | target: WherePredicateTypeTarget::TypeRef(type_ref), | 341 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
338 | bound, | 342 | bound, |
339 | }, | 343 | }, |
340 | None => WherePredicate::TypeBound { | 344 | None => WherePredicate::TypeBound { |
341 | target: WherePredicateTypeTarget::TypeRef(type_ref), | 345 | target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)), |
342 | bound, | 346 | bound, |
343 | }, | 347 | }, |
344 | }, | 348 | }, |
@@ -369,6 +373,14 @@ impl GenericParams { | |||
369 | }); | 373 | }); |
370 | } | 374 | } |
371 | 375 | ||
376 | pub(crate) fn shrink_to_fit(&mut self) { | ||
377 | let Self { consts, lifetimes, types, where_predicates } = self; | ||
378 | consts.shrink_to_fit(); | ||
379 | lifetimes.shrink_to_fit(); | ||
380 | types.shrink_to_fit(); | ||
381 | where_predicates.shrink_to_fit(); | ||
382 | } | ||
383 | |||
372 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { | 384 | pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { |
373 | self.types | 385 | self.types |
374 | .iter() | 386 | .iter() |
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs index d163f633f..2467e9299 100644 --- a/crates/hir_def/src/intern.rs +++ b/crates/hir_def/src/intern.rs | |||
@@ -14,6 +14,8 @@ use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue}; | |||
14 | use once_cell::sync::OnceCell; | 14 | use once_cell::sync::OnceCell; |
15 | use rustc_hash::FxHasher; | 15 | use rustc_hash::FxHasher; |
16 | 16 | ||
17 | use crate::generics::GenericParams; | ||
18 | |||
17 | type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; | 19 | type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; |
18 | type Guard<T> = | 20 | type Guard<T> = |
19 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; | 21 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; |
@@ -194,4 +196,10 @@ macro_rules! impl_internable { | |||
194 | )+ }; | 196 | )+ }; |
195 | } | 197 | } |
196 | 198 | ||
197 | impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str); | 199 | impl_internable!( |
200 | crate::type_ref::TypeRef, | ||
201 | crate::type_ref::TraitRef, | ||
202 | crate::path::ModPath, | ||
203 | GenericParams, | ||
204 | str | ||
205 | ); | ||
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index f3ebe7c72..a8ee5eeac 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -285,6 +285,28 @@ impl ItemScope { | |||
285 | buf.push('\n'); | 285 | buf.push('\n'); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | |||
289 | pub(crate) fn shrink_to_fit(&mut self) { | ||
290 | // Exhaustive match to require handling new fields. | ||
291 | let Self { | ||
292 | types, | ||
293 | values, | ||
294 | macros, | ||
295 | unresolved, | ||
296 | defs, | ||
297 | impls, | ||
298 | unnamed_trait_imports, | ||
299 | legacy_macros, | ||
300 | } = self; | ||
301 | types.shrink_to_fit(); | ||
302 | values.shrink_to_fit(); | ||
303 | macros.shrink_to_fit(); | ||
304 | unresolved.shrink_to_fit(); | ||
305 | defs.shrink_to_fit(); | ||
306 | impls.shrink_to_fit(); | ||
307 | unnamed_trait_imports.shrink_to_fit(); | ||
308 | legacy_macros.shrink_to_fit(); | ||
309 | } | ||
288 | } | 310 | } |
289 | 311 | ||
290 | impl PerNs { | 312 | impl PerNs { |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 69a313c7e..240662486 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
@@ -58,13 +58,6 @@ impl fmt::Debug for RawVisibilityId { | |||
58 | } | 58 | } |
59 | } | 59 | } |
60 | 60 | ||
61 | #[derive(Debug, Copy, Clone, Eq, PartialEq)] | ||
62 | pub struct GenericParamsId(u32); | ||
63 | |||
64 | impl GenericParamsId { | ||
65 | pub const EMPTY: Self = GenericParamsId(u32::max_value()); | ||
66 | } | ||
67 | |||
68 | /// The item tree of a source file. | 61 | /// The item tree of a source file. |
69 | #[derive(Debug, Default, Eq, PartialEq)] | 62 | #[derive(Debug, Default, Eq, PartialEq)] |
70 | pub struct ItemTree { | 63 | pub struct ItemTree { |
@@ -146,7 +139,6 @@ impl ItemTree { | |||
146 | macro_rules, | 139 | macro_rules, |
147 | macro_defs, | 140 | macro_defs, |
148 | vis, | 141 | vis, |
149 | generics, | ||
150 | inner_items, | 142 | inner_items, |
151 | } = &mut **data; | 143 | } = &mut **data; |
152 | 144 | ||
@@ -170,7 +162,6 @@ impl ItemTree { | |||
170 | macro_defs.shrink_to_fit(); | 162 | macro_defs.shrink_to_fit(); |
171 | 163 | ||
172 | vis.arena.shrink_to_fit(); | 164 | vis.arena.shrink_to_fit(); |
173 | generics.arena.shrink_to_fit(); | ||
174 | 165 | ||
175 | inner_items.shrink_to_fit(); | 166 | inner_items.shrink_to_fit(); |
176 | } | 167 | } |
@@ -242,32 +233,6 @@ static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKi | |||
242 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); | 233 | static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); |
243 | 234 | ||
244 | #[derive(Default, Debug, Eq, PartialEq)] | 235 | #[derive(Default, Debug, Eq, PartialEq)] |
245 | struct GenericParamsStorage { | ||
246 | arena: Arena<GenericParams>, | ||
247 | } | ||
248 | |||
249 | impl GenericParamsStorage { | ||
250 | fn alloc(&mut self, params: GenericParams) -> GenericParamsId { | ||
251 | if params.types.is_empty() | ||
252 | && params.lifetimes.is_empty() | ||
253 | && params.consts.is_empty() | ||
254 | && params.where_predicates.is_empty() | ||
255 | { | ||
256 | return GenericParamsId::EMPTY; | ||
257 | } | ||
258 | |||
259 | GenericParamsId(self.arena.alloc(params).into_raw().into()) | ||
260 | } | ||
261 | } | ||
262 | |||
263 | static EMPTY_GENERICS: GenericParams = GenericParams { | ||
264 | types: Arena::new(), | ||
265 | lifetimes: Arena::new(), | ||
266 | consts: Arena::new(), | ||
267 | where_predicates: Vec::new(), | ||
268 | }; | ||
269 | |||
270 | #[derive(Default, Debug, Eq, PartialEq)] | ||
271 | struct ItemTreeData { | 236 | struct ItemTreeData { |
272 | imports: Arena<Import>, | 237 | imports: Arena<Import>, |
273 | extern_crates: Arena<ExternCrate>, | 238 | extern_crates: Arena<ExternCrate>, |
@@ -289,7 +254,6 @@ struct ItemTreeData { | |||
289 | macro_defs: Arena<MacroDef>, | 254 | macro_defs: Arena<MacroDef>, |
290 | 255 | ||
291 | vis: ItemVisibilities, | 256 | vis: ItemVisibilities, |
292 | generics: GenericParamsStorage, | ||
293 | 257 | ||
294 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 258 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
295 | } | 259 | } |
@@ -508,17 +472,6 @@ impl Index<RawVisibilityId> for ItemTree { | |||
508 | } | 472 | } |
509 | } | 473 | } |
510 | 474 | ||
511 | impl Index<GenericParamsId> for ItemTree { | ||
512 | type Output = GenericParams; | ||
513 | |||
514 | fn index(&self, index: GenericParamsId) -> &Self::Output { | ||
515 | match index { | ||
516 | GenericParamsId::EMPTY => &EMPTY_GENERICS, | ||
517 | _ => &self.data().generics.arena[Idx::from_raw(index.0.into())], | ||
518 | } | ||
519 | } | ||
520 | } | ||
521 | |||
522 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 475 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
523 | type Output = N; | 476 | type Output = N; |
524 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 477 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -529,7 +482,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | |||
529 | /// A desugared `use` import. | 482 | /// A desugared `use` import. |
530 | #[derive(Debug, Clone, Eq, PartialEq)] | 483 | #[derive(Debug, Clone, Eq, PartialEq)] |
531 | pub struct Import { | 484 | pub struct Import { |
532 | pub path: ModPath, | 485 | pub path: Interned<ModPath>, |
533 | pub alias: Option<ImportAlias>, | 486 | pub alias: Option<ImportAlias>, |
534 | pub visibility: RawVisibilityId, | 487 | pub visibility: RawVisibilityId, |
535 | pub is_glob: bool, | 488 | pub is_glob: bool, |
@@ -555,16 +508,12 @@ pub struct ExternCrate { | |||
555 | pub struct Function { | 508 | pub struct Function { |
556 | pub name: Name, | 509 | pub name: Name, |
557 | pub visibility: RawVisibilityId, | 510 | pub visibility: RawVisibilityId, |
558 | pub generic_params: GenericParamsId, | 511 | pub generic_params: Interned<GenericParams>, |
559 | pub has_self_param: bool, | 512 | pub abi: Option<Interned<str>>, |
560 | pub has_body: bool, | ||
561 | pub qualifier: FunctionQualifier, | ||
562 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
563 | /// `extern "abi" fn`). | ||
564 | pub is_in_extern_block: bool, | ||
565 | pub params: IdRange<Param>, | 513 | pub params: IdRange<Param>, |
566 | pub ret_type: Interned<TypeRef>, | 514 | pub ret_type: Interned<TypeRef>, |
567 | pub ast_id: FileAstId<ast::Fn>, | 515 | pub ast_id: FileAstId<ast::Fn>, |
516 | pub(crate) flags: FnFlags, | ||
568 | } | 517 | } |
569 | 518 | ||
570 | #[derive(Debug, Clone, Eq, PartialEq)] | 519 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -573,20 +522,28 @@ pub enum Param { | |||
573 | Varargs, | 522 | Varargs, |
574 | } | 523 | } |
575 | 524 | ||
576 | #[derive(Debug, Clone, PartialEq, Eq)] | 525 | #[derive(Debug, Clone, Copy, Eq, PartialEq, Default)] |
577 | pub struct FunctionQualifier { | 526 | pub(crate) struct FnFlags { |
578 | pub is_default: bool, | 527 | pub(crate) bits: u8, |
579 | pub is_const: bool, | 528 | } |
580 | pub is_async: bool, | 529 | impl FnFlags { |
581 | pub is_unsafe: bool, | 530 | pub(crate) const HAS_SELF_PARAM: u8 = 1 << 0; |
582 | pub abi: Option<SmolStr>, | 531 | pub(crate) const HAS_BODY: u8 = 1 << 1; |
532 | pub(crate) const IS_DEFAULT: u8 = 1 << 2; | ||
533 | pub(crate) const IS_CONST: u8 = 1 << 3; | ||
534 | pub(crate) const IS_ASYNC: u8 = 1 << 4; | ||
535 | pub(crate) const IS_UNSAFE: u8 = 1 << 5; | ||
536 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
537 | /// `extern "abi" fn`). | ||
538 | pub(crate) const IS_IN_EXTERN_BLOCK: u8 = 1 << 6; | ||
539 | pub(crate) const IS_VARARGS: u8 = 1 << 7; | ||
583 | } | 540 | } |
584 | 541 | ||
585 | #[derive(Debug, Clone, Eq, PartialEq)] | 542 | #[derive(Debug, Clone, Eq, PartialEq)] |
586 | pub struct Struct { | 543 | pub struct Struct { |
587 | pub name: Name, | 544 | pub name: Name, |
588 | pub visibility: RawVisibilityId, | 545 | pub visibility: RawVisibilityId, |
589 | pub generic_params: GenericParamsId, | 546 | pub generic_params: Interned<GenericParams>, |
590 | pub fields: Fields, | 547 | pub fields: Fields, |
591 | pub ast_id: FileAstId<ast::Struct>, | 548 | pub ast_id: FileAstId<ast::Struct>, |
592 | pub kind: StructDefKind, | 549 | pub kind: StructDefKind, |
@@ -606,7 +563,7 @@ pub enum StructDefKind { | |||
606 | pub struct Union { | 563 | pub struct Union { |
607 | pub name: Name, | 564 | pub name: Name, |
608 | pub visibility: RawVisibilityId, | 565 | pub visibility: RawVisibilityId, |
609 | pub generic_params: GenericParamsId, | 566 | pub generic_params: Interned<GenericParams>, |
610 | pub fields: Fields, | 567 | pub fields: Fields, |
611 | pub ast_id: FileAstId<ast::Union>, | 568 | pub ast_id: FileAstId<ast::Union>, |
612 | } | 569 | } |
@@ -615,7 +572,7 @@ pub struct Union { | |||
615 | pub struct Enum { | 572 | pub struct Enum { |
616 | pub name: Name, | 573 | pub name: Name, |
617 | pub visibility: RawVisibilityId, | 574 | pub visibility: RawVisibilityId, |
618 | pub generic_params: GenericParamsId, | 575 | pub generic_params: Interned<GenericParams>, |
619 | pub variants: IdRange<Variant>, | 576 | pub variants: IdRange<Variant>, |
620 | pub ast_id: FileAstId<ast::Enum>, | 577 | pub ast_id: FileAstId<ast::Enum>, |
621 | } | 578 | } |
@@ -644,7 +601,7 @@ pub struct Static { | |||
644 | pub struct Trait { | 601 | pub struct Trait { |
645 | pub name: Name, | 602 | pub name: Name, |
646 | pub visibility: RawVisibilityId, | 603 | pub visibility: RawVisibilityId, |
647 | pub generic_params: GenericParamsId, | 604 | pub generic_params: Interned<GenericParams>, |
648 | pub is_auto: bool, | 605 | pub is_auto: bool, |
649 | pub is_unsafe: bool, | 606 | pub is_unsafe: bool, |
650 | pub bounds: Box<[TypeBound]>, | 607 | pub bounds: Box<[TypeBound]>, |
@@ -654,7 +611,7 @@ pub struct Trait { | |||
654 | 611 | ||
655 | #[derive(Debug, Clone, Eq, PartialEq)] | 612 | #[derive(Debug, Clone, Eq, PartialEq)] |
656 | pub struct Impl { | 613 | pub struct Impl { |
657 | pub generic_params: GenericParamsId, | 614 | pub generic_params: Interned<GenericParams>, |
658 | pub target_trait: Option<Interned<TraitRef>>, | 615 | pub target_trait: Option<Interned<TraitRef>>, |
659 | pub self_ty: Interned<TypeRef>, | 616 | pub self_ty: Interned<TypeRef>, |
660 | pub is_negative: bool, | 617 | pub is_negative: bool, |
@@ -668,7 +625,7 @@ pub struct TypeAlias { | |||
668 | pub visibility: RawVisibilityId, | 625 | pub visibility: RawVisibilityId, |
669 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 626 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
670 | pub bounds: Box<[TypeBound]>, | 627 | pub bounds: Box<[TypeBound]>, |
671 | pub generic_params: GenericParamsId, | 628 | pub generic_params: Interned<GenericParams>, |
672 | pub type_ref: Option<Interned<TypeRef>>, | 629 | pub type_ref: Option<Interned<TypeRef>>, |
673 | pub is_extern: bool, | 630 | pub is_extern: bool, |
674 | pub ast_id: FileAstId<ast::TypeAlias>, | 631 | pub ast_id: FileAstId<ast::TypeAlias>, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 5247379c5..c5629af24 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -395,39 +395,51 @@ impl Ctx { | |||
395 | ret_type | 395 | ret_type |
396 | }; | 396 | }; |
397 | 397 | ||
398 | let has_body = func.body().is_some(); | 398 | let abi = func.abi().map(|abi| { |
399 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | ||
400 | match abi.syntax().last_token() { | ||
401 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | ||
402 | // FIXME: Better way to unescape? | ||
403 | Interned::new_str(tok.text().trim_matches('"')) | ||
404 | } | ||
405 | _ => { | ||
406 | // `extern` default to be `extern "C"`. | ||
407 | Interned::new_str("C") | ||
408 | } | ||
409 | } | ||
410 | }); | ||
399 | 411 | ||
400 | let ast_id = self.source_ast_id_map.ast_id(func); | 412 | let ast_id = self.source_ast_id_map.ast_id(func); |
401 | let qualifier = FunctionQualifier { | 413 | |
402 | is_default: func.default_token().is_some(), | 414 | let mut flags = FnFlags::default(); |
403 | is_const: func.const_token().is_some(), | 415 | if func.body().is_some() { |
404 | is_async: func.async_token().is_some(), | 416 | flags.bits |= FnFlags::HAS_BODY; |
405 | is_unsafe: func.unsafe_token().is_some(), | 417 | } |
406 | abi: func.abi().map(|abi| { | 418 | if has_self_param { |
407 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | 419 | flags.bits |= FnFlags::HAS_SELF_PARAM; |
408 | match abi.syntax().last_token() { | 420 | } |
409 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | 421 | if func.default_token().is_some() { |
410 | // FIXME: Better way to unescape? | 422 | flags.bits |= FnFlags::IS_DEFAULT; |
411 | tok.text().trim_matches('"').into() | 423 | } |
412 | } | 424 | if func.const_token().is_some() { |
413 | _ => { | 425 | flags.bits |= FnFlags::IS_CONST; |
414 | // `extern` default to be `extern "C"`. | 426 | } |
415 | "C".into() | 427 | if func.async_token().is_some() { |
416 | } | 428 | flags.bits |= FnFlags::IS_ASYNC; |
417 | } | 429 | } |
418 | }), | 430 | if func.unsafe_token().is_some() { |
419 | }; | 431 | flags.bits |= FnFlags::IS_UNSAFE; |
432 | } | ||
433 | |||
420 | let mut res = Function { | 434 | let mut res = Function { |
421 | name, | 435 | name, |
422 | visibility, | 436 | visibility, |
423 | generic_params: GenericParamsId::EMPTY, | 437 | generic_params: Interned::new(GenericParams::default()), |
424 | has_self_param, | 438 | abi, |
425 | has_body, | ||
426 | qualifier, | ||
427 | is_in_extern_block: false, | ||
428 | params, | 439 | params, |
429 | ret_type: Interned::new(ret_type), | 440 | ret_type: Interned::new(ret_type), |
430 | ast_id, | 441 | ast_id, |
442 | flags, | ||
431 | }; | 443 | }; |
432 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | 444 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); |
433 | 445 | ||
@@ -577,7 +589,7 @@ impl Ctx { | |||
577 | &self.hygiene, | 589 | &self.hygiene, |
578 | |path, _use_tree, is_glob, alias| { | 590 | |path, _use_tree, is_glob, alias| { |
579 | imports.push(id(tree.imports.alloc(Import { | 591 | imports.push(id(tree.imports.alloc(Import { |
580 | path, | 592 | path: Interned::new(path), |
581 | alias, | 593 | alias, |
582 | visibility, | 594 | visibility, |
583 | is_glob, | 595 | is_glob, |
@@ -640,8 +652,10 @@ impl Ctx { | |||
640 | ast::ExternItem::Fn(ast) => { | 652 | ast::ExternItem::Fn(ast) => { |
641 | let func_id = self.lower_function(&ast)?; | 653 | let func_id = self.lower_function(&ast)?; |
642 | let func = &mut self.data().functions[func_id.index]; | 654 | let func = &mut self.data().functions[func_id.index]; |
643 | func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); | 655 | if is_intrinsic_fn_unsafe(&func.name) { |
644 | func.is_in_extern_block = true; | 656 | func.flags.bits |= FnFlags::IS_UNSAFE; |
657 | } | ||
658 | func.flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK; | ||
645 | func_id.into() | 659 | func_id.into() |
646 | } | 660 | } |
647 | ast::ExternItem::Static(ast) => { | 661 | ast::ExternItem::Static(ast) => { |
@@ -668,7 +682,7 @@ impl Ctx { | |||
668 | &mut self, | 682 | &mut self, |
669 | owner: GenericsOwner<'_>, | 683 | owner: GenericsOwner<'_>, |
670 | node: &impl ast::GenericParamsOwner, | 684 | node: &impl ast::GenericParamsOwner, |
671 | ) -> GenericParamsId { | 685 | ) -> Interned<GenericParams> { |
672 | // Generics are part of item headers and may contain inner items we need to collect. | 686 | // Generics are part of item headers and may contain inner items we need to collect. |
673 | if let Some(params) = node.generic_param_list() { | 687 | if let Some(params) = node.generic_param_list() { |
674 | self.collect_inner_items(params.syntax()); | 688 | self.collect_inner_items(params.syntax()); |
@@ -684,7 +698,7 @@ impl Ctx { | |||
684 | &mut self, | 698 | &mut self, |
685 | owner: GenericsOwner<'_>, | 699 | owner: GenericsOwner<'_>, |
686 | node: &impl ast::GenericParamsOwner, | 700 | node: &impl ast::GenericParamsOwner, |
687 | ) -> GenericParamsId { | 701 | ) -> Interned<GenericParams> { |
688 | let mut sm = &mut Default::default(); | 702 | let mut sm = &mut Default::default(); |
689 | let mut generics = GenericParams::default(); | 703 | let mut generics = GenericParams::default(); |
690 | match owner { | 704 | match owner { |
@@ -725,7 +739,8 @@ impl Ctx { | |||
725 | } | 739 | } |
726 | } | 740 | } |
727 | 741 | ||
728 | self.data().generics.alloc(generics) | 742 | generics.shrink_to_fit(); |
743 | Interned::new(generics) | ||
729 | } | 744 | } |
730 | 745 | ||
731 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { | 746 | fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { |
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index f408e510a..be9a5e1a0 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -27,6 +27,7 @@ pub mod dyn_map; | |||
27 | pub mod keys; | 27 | pub mod keys; |
28 | 28 | ||
29 | pub mod item_tree; | 29 | pub mod item_tree; |
30 | pub mod intern; | ||
30 | 31 | ||
31 | pub mod adt; | 32 | pub mod adt; |
32 | pub mod data; | 33 | pub mod data; |
@@ -49,7 +50,6 @@ pub mod import_map; | |||
49 | 50 | ||
50 | #[cfg(test)] | 51 | #[cfg(test)] |
51 | mod test_db; | 52 | mod test_db; |
52 | mod intern; | ||
53 | 53 | ||
54 | use std::{ | 54 | use std::{ |
55 | hash::{Hash, Hasher}, | 55 | hash::{Hash, Hasher}, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 9e8e4e9ec..7dd68219f 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -409,6 +409,31 @@ impl DefMap { | |||
409 | } | 409 | } |
410 | } | 410 | } |
411 | } | 411 | } |
412 | |||
413 | fn shrink_to_fit(&mut self) { | ||
414 | // Exhaustive match to require handling new fields. | ||
415 | let Self { | ||
416 | _c: _, | ||
417 | exported_proc_macros, | ||
418 | extern_prelude, | ||
419 | diagnostics, | ||
420 | modules, | ||
421 | block: _, | ||
422 | edition: _, | ||
423 | krate: _, | ||
424 | prelude: _, | ||
425 | root: _, | ||
426 | } = self; | ||
427 | |||
428 | extern_prelude.shrink_to_fit(); | ||
429 | exported_proc_macros.shrink_to_fit(); | ||
430 | diagnostics.shrink_to_fit(); | ||
431 | modules.shrink_to_fit(); | ||
432 | for (_, module) in modules.iter_mut() { | ||
433 | module.children.shrink_to_fit(); | ||
434 | module.scope.shrink_to_fit(); | ||
435 | } | ||
436 | } | ||
412 | } | 437 | } |
413 | 438 | ||
414 | impl ModuleData { | 439 | impl ModuleData { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index c8f494707..4ddc791ce 100644 --- a/crates/hir_def/src/nameres/collector.rs +++ b/crates/hir_def/src/nameres/collector.rs | |||
@@ -23,6 +23,7 @@ use crate::{ | |||
23 | attr::Attrs, | 23 | attr::Attrs, |
24 | db::DefDatabase, | 24 | db::DefDatabase, |
25 | derive_macro_as_call_id, | 25 | derive_macro_as_call_id, |
26 | intern::Interned, | ||
26 | item_scope::{ImportType, PerNsGlobImports}, | 27 | item_scope::{ImportType, PerNsGlobImports}, |
27 | item_tree::{ | 28 | item_tree::{ |
28 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, | 29 | self, FileItemTreeId, ItemTree, ItemTreeId, MacroCall, MacroDef, MacroRules, Mod, ModItem, |
@@ -108,7 +109,9 @@ pub(super) fn collect_defs( | |||
108 | } | 109 | } |
109 | } | 110 | } |
110 | collector.collect(); | 111 | collector.collect(); |
111 | collector.finish() | 112 | let mut def_map = collector.finish(); |
113 | def_map.shrink_to_fit(); | ||
114 | def_map | ||
112 | } | 115 | } |
113 | 116 | ||
114 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | 117 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] |
@@ -139,7 +142,7 @@ enum ImportSource { | |||
139 | 142 | ||
140 | #[derive(Clone, Debug, Eq, PartialEq)] | 143 | #[derive(Clone, Debug, Eq, PartialEq)] |
141 | struct Import { | 144 | struct Import { |
142 | path: ModPath, | 145 | path: Interned<ModPath>, |
143 | alias: Option<ImportAlias>, | 146 | alias: Option<ImportAlias>, |
144 | visibility: RawVisibility, | 147 | visibility: RawVisibility, |
145 | is_glob: bool, | 148 | is_glob: bool, |
@@ -181,7 +184,10 @@ impl Import { | |||
181 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); | 184 | let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); |
182 | let visibility = &tree[it.visibility]; | 185 | let visibility = &tree[it.visibility]; |
183 | Self { | 186 | Self { |
184 | path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())), | 187 | path: Interned::new(ModPath::from_segments( |
188 | PathKind::Plain, | ||
189 | iter::once(it.name.clone()), | ||
190 | )), | ||
185 | alias: it.alias.clone(), | 191 | alias: it.alias.clone(), |
186 | visibility: visibility.clone(), | 192 | visibility: visibility.clone(), |
187 | is_glob: false, | 193 | is_glob: false, |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index a3e83e2cf..f9c8328f0 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -122,7 +122,7 @@ impl ModPath { | |||
122 | pub struct Path { | 122 | pub struct Path { |
123 | /// Type based path like `<T>::foo`. | 123 | /// Type based path like `<T>::foo`. |
124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. | 124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. |
125 | type_anchor: Option<Box<TypeRef>>, | 125 | type_anchor: Option<Interned<TypeRef>>, |
126 | mod_path: Interned<ModPath>, | 126 | mod_path: Interned<ModPath>, |
127 | /// Invariant: the same len as `self.mod_path.segments` | 127 | /// Invariant: the same len as `self.mod_path.segments` |
128 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 128 | generic_args: Vec<Option<Arc<GenericArgs>>>, |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 28f6244da..7b29d9d4f 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -69,7 +69,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
69 | match trait_ref { | 69 | match trait_ref { |
70 | // <T>::foo | 70 | // <T>::foo |
71 | None => { | 71 | None => { |
72 | type_anchor = Some(Box::new(self_type)); | 72 | type_anchor = Some(Interned::new(self_type)); |
73 | kind = PathKind::Plain; | 73 | kind = PathKind::Plain; |
74 | } | 74 | } |
75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs index a73585ee7..0391cc49b 100644 --- a/crates/hir_def/src/resolver.rs +++ b/crates/hir_def/src/resolver.rs | |||
@@ -14,6 +14,7 @@ use crate::{ | |||
14 | db::DefDatabase, | 14 | db::DefDatabase, |
15 | expr::{ExprId, LabelId, PatId}, | 15 | expr::{ExprId, LabelId, PatId}, |
16 | generics::GenericParams, | 16 | generics::GenericParams, |
17 | intern::Interned, | ||
17 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, | 18 | item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, |
18 | nameres::DefMap, | 19 | nameres::DefMap, |
19 | path::{ModPath, PathKind}, | 20 | path::{ModPath, PathKind}, |
@@ -50,7 +51,7 @@ enum Scope { | |||
50 | /// All the items and imported names of a module | 51 | /// All the items and imported names of a module |
51 | ModuleScope(ModuleItemMap), | 52 | ModuleScope(ModuleItemMap), |
52 | /// Brings the generic parameters of an item into scope | 53 | /// Brings the generic parameters of an item into scope |
53 | GenericParams { def: GenericDefId, params: Arc<GenericParams> }, | 54 | GenericParams { def: GenericDefId, params: Interned<GenericParams> }, |
54 | /// Brings `Self` in `impl` block into scope | 55 | /// Brings `Self` in `impl` block into scope |
55 | ImplDefScope(ImplId), | 56 | ImplDefScope(ImplId), |
56 | /// Brings `Self` in enum, struct and union definitions into scope | 57 | /// Brings `Self` in enum, struct and union definitions into scope |
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs index 7d00a37c4..9908cd926 100644 --- a/crates/hir_def/src/visibility.rs +++ b/crates/hir_def/src/visibility.rs | |||
@@ -11,7 +11,7 @@ use crate::{ | |||
11 | nameres::DefMap, | 11 | nameres::DefMap, |
12 | path::{ModPath, PathKind}, | 12 | path::{ModPath, PathKind}, |
13 | resolver::HasResolver, | 13 | resolver::HasResolver, |
14 | FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, | 14 | FunctionId, HasModule, LocalFieldId, ModuleId, VariantId, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | /// Visibility of an item, not yet resolved. | 17 | /// Visibility of an item, not yet resolved. |
@@ -25,7 +25,7 @@ pub enum RawVisibility { | |||
25 | } | 25 | } |
26 | 26 | ||
27 | impl RawVisibility { | 27 | impl RawVisibility { |
28 | pub(crate) const fn private() -> RawVisibility { | 28 | pub(crate) fn private() -> RawVisibility { |
29 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) | 29 | RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) |
30 | } | 30 | } |
31 | 31 | ||
@@ -217,6 +217,6 @@ pub(crate) fn field_visibilities_query( | |||
217 | 217 | ||
218 | /// Resolve visibility of a function. | 218 | /// Resolve visibility of a function. |
219 | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { | 219 | pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { |
220 | let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); | 220 | let resolver = def.resolver(db); |
221 | db.function_data(def).visibility.resolve(db, &resolver) | 221 | db.function_data(def).visibility.resolve(db, &resolver) |
222 | } | 222 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 3aa3d8997..75ec4196b 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -584,7 +584,7 @@ mod tests { | |||
584 | }; | 584 | }; |
585 | 585 | ||
586 | let args = macro_call.token_tree().unwrap(); | 586 | let args = macro_call.token_tree().unwrap(); |
587 | let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; | 587 | let parsed_args = mbe::ast_to_token_tree(&args).0; |
588 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); | 588 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_call)); |
589 | 589 | ||
590 | let arg_id = db.intern_eager_expansion({ | 590 | let arg_id = db.intern_eager_expansion({ |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index c0ab70b60..10fe60821 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -119,7 +119,7 @@ pub fn expand_hypothetical( | |||
119 | token_to_map: syntax::SyntaxToken, | 119 | token_to_map: syntax::SyntaxToken, |
120 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { | 120 | ) -> Option<(SyntaxNode, syntax::SyntaxToken)> { |
121 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; | 121 | let macro_file = MacroFile { macro_call_id: actual_macro_call }; |
122 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()).unwrap(); | 122 | let (tt, tmap_1) = mbe::syntax_node_to_token_tree(hypothetical_args.syntax()); |
123 | let range = | 123 | let range = |
124 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; | 124 | token_to_map.text_range().checked_sub(hypothetical_args.syntax().text_range().start())?; |
125 | let token_id = tmap_1.token_by_range(range)?; | 125 | let token_id = tmap_1.token_by_range(range)?; |
@@ -143,10 +143,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, | |||
143 | MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { | 143 | MacroDefKind::Declarative(ast_id) => match ast_id.to_node(db) { |
144 | syntax::ast::Macro::MacroRules(macro_rules) => { | 144 | syntax::ast::Macro::MacroRules(macro_rules) => { |
145 | let arg = macro_rules.token_tree()?; | 145 | let arg = macro_rules.token_tree()?; |
146 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 146 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
147 | log::warn!("fail on macro_rules to token tree: {:#?}", arg); | ||
148 | None | ||
149 | })?; | ||
150 | let rules = match MacroRules::parse(&tt) { | 147 | let rules = match MacroRules::parse(&tt) { |
151 | Ok(it) => it, | 148 | Ok(it) => it, |
152 | Err(err) => { | 149 | Err(err) => { |
@@ -159,10 +156,7 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, | |||
159 | } | 156 | } |
160 | syntax::ast::Macro::MacroDef(macro_def) => { | 157 | syntax::ast::Macro::MacroDef(macro_def) => { |
161 | let arg = macro_def.body()?; | 158 | let arg = macro_def.body()?; |
162 | let (tt, tmap) = mbe::ast_to_token_tree(&arg).or_else(|| { | 159 | let (tt, tmap) = mbe::ast_to_token_tree(&arg); |
163 | log::warn!("fail on macro_def to token tree: {:#?}", arg); | ||
164 | None | ||
165 | })?; | ||
166 | let rules = match MacroDef::parse(&tt) { | 160 | let rules = match MacroDef::parse(&tt) { |
167 | Ok(it) => it, | 161 | Ok(it) => it, |
168 | Err(err) => { | 162 | Err(err) => { |
@@ -202,7 +196,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
202 | 196 | ||
203 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 197 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
204 | let arg = db.macro_arg_text(id)?; | 198 | let arg = db.macro_arg_text(id)?; |
205 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?; | 199 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg)); |
206 | Some(Arc::new((tt, tmap))) | 200 | Some(Arc::new((tt, tmap))) |
207 | } | 201 | } |
208 | 202 | ||
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 9eedc8461..9705526fa 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -106,7 +106,7 @@ pub fn expand_eager_macro( | |||
106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), | 106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), |
107 | ) -> Result<EagerMacroId, ErrorEmitted> { | 107 | ) -> Result<EagerMacroId, ErrorEmitted> { |
108 | let parsed_args = diagnostic_sink.option_with( | 108 | let parsed_args = diagnostic_sink.option_with( |
109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?)?.0), | 109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?).0), |
110 | || err("malformed macro invocation"), | 110 | || err("malformed macro invocation"), |
111 | )?; | 111 | )?; |
112 | 112 | ||
@@ -161,7 +161,7 @@ pub fn expand_eager_macro( | |||
161 | } | 161 | } |
162 | 162 | ||
163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { | 163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { |
164 | let mut subtree = mbe::syntax_node_to_token_tree(node)?.0; | 164 | let mut subtree = mbe::syntax_node_to_token_tree(node).0; |
165 | subtree.delimiter = None; | 165 | subtree.delimiter = None; |
166 | Some(subtree) | 166 | Some(subtree) |
167 | } | 167 | } |
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index c859f9491..7ca4af80e 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -12,12 +12,8 @@ use hir_expand::name::name; | |||
12 | use log::{info, warn}; | 12 | use log::{info, warn}; |
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::HirDatabase, | 15 | db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, |
16 | to_assoc_type_id, to_chalk_trait_id, | 16 | InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind, |
17 | traits::{InEnvironment, Solution}, | ||
18 | utils::generics, | ||
19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, | ||
20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, | ||
21 | }; | 17 | }; |
22 | 18 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 19 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -57,21 +53,20 @@ fn deref_by_trait( | |||
57 | }; | 53 | }; |
58 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; | 54 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; |
59 | 55 | ||
60 | let generic_params = generics(db.upcast(), target.into()); | 56 | let projection = { |
61 | if generic_params.len() != 1 { | 57 | let b = TyBuilder::assoc_type_projection(db, target); |
62 | // the Target type + Deref trait should only have one generic parameter, | 58 | if b.remaining() != 1 { |
63 | // namely Deref's Self type | 59 | // the Target type + Deref trait should only have one generic parameter, |
64 | return None; | 60 | // namely Deref's Self type |
65 | } | 61 | return None; |
62 | } | ||
63 | b.push(ty.goal.value.clone()).build() | ||
64 | }; | ||
66 | 65 | ||
67 | // FIXME make the Canonical / bound var handling nicer | 66 | // FIXME make the Canonical / bound var handling nicer |
68 | 67 | ||
69 | let parameters = | ||
70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); | ||
71 | |||
72 | // Check that the type implements Deref at all | 68 | // Check that the type implements Deref at all |
73 | let trait_ref = | 69 | let trait_ref = projection.trait_ref(db); |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | ||
75 | let implements_goal = Canonical { | 70 | let implements_goal = Canonical { |
76 | binders: ty.goal.binders.clone(), | 71 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 72 | value: InEnvironment { |
@@ -84,11 +79,8 @@ fn deref_by_trait( | |||
84 | } | 79 | } |
85 | 80 | ||
86 | // Now do the assoc type projection | 81 | // Now do the assoc type projection |
87 | let projection = AliasEq { | 82 | let alias_eq = AliasEq { |
88 | alias: AliasTy::Projection(ProjectionTy { | 83 | alias: AliasTy::Projection(projection), |
89 | associated_ty_id: to_assoc_type_id(target), | ||
90 | substitution: parameters, | ||
91 | }), | ||
92 | ty: TyKind::BoundVar(BoundVar::new( | 84 | ty: TyKind::BoundVar(BoundVar::new( |
93 | DebruijnIndex::INNERMOST, | 85 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | 86 | ty.goal.binders.len(&Interner), |
@@ -96,9 +88,7 @@ fn deref_by_trait( | |||
96 | .intern(&Interner), | 88 | .intern(&Interner), |
97 | }; | 89 | }; |
98 | 90 | ||
99 | let obligation = projection.cast(&Interner); | 91 | let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment }; |
100 | |||
101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; | ||
102 | 92 | ||
103 | let canonical = Canonical { | 93 | let canonical = Canonical { |
104 | value: in_env, | 94 | value: in_env, |
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs new file mode 100644 index 000000000..0bac31e4c --- /dev/null +++ b/crates/hir_ty/src/builder.rs | |||
@@ -0,0 +1,219 @@ | |||
1 | //! `TyBuilder`, a helper for building instances of `Ty` and related types. | ||
2 | |||
3 | use std::iter; | ||
4 | |||
5 | use chalk_ir::{ | ||
6 | cast::{Cast, CastTo, Caster}, | ||
7 | interner::HasInterner, | ||
8 | AdtId, BoundVar, DebruijnIndex, Safety, Scalar, | ||
9 | }; | ||
10 | use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId}; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use crate::{ | ||
14 | db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, | ||
15 | CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, | ||
16 | TyDefId, TyKind, TypeWalk, ValueTyDefId, | ||
17 | }; | ||
18 | |||
19 | /// This is a builder for `Ty` or anything that needs a `Substitution`. | ||
20 | pub struct TyBuilder<D> { | ||
21 | /// The `data` field is used to keep track of what we're building (e.g. an | ||
22 | /// ADT, a `TraitRef`, ...). | ||
23 | data: D, | ||
24 | vec: SmallVec<[GenericArg; 2]>, | ||
25 | param_count: usize, | ||
26 | } | ||
27 | |||
28 | impl<D> TyBuilder<D> { | ||
29 | fn new(data: D, param_count: usize) -> TyBuilder<D> { | ||
30 | TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) } | ||
31 | } | ||
32 | |||
33 | fn build_internal(self) -> (D, Substitution) { | ||
34 | assert_eq!(self.vec.len(), self.param_count); | ||
35 | // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form | ||
36 | let subst = Substitution::intern(self.vec); | ||
37 | (self.data, subst) | ||
38 | } | ||
39 | |||
40 | pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self { | ||
41 | self.vec.push(arg.cast(&Interner)); | ||
42 | self | ||
43 | } | ||
44 | |||
45 | pub fn remaining(&self) -> usize { | ||
46 | self.param_count - self.vec.len() | ||
47 | } | ||
48 | |||
49 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { | ||
50 | self.fill( | ||
51 | (starting_from..) | ||
52 | .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
53 | ) | ||
54 | } | ||
55 | |||
56 | pub fn fill_with_unknown(self) -> Self { | ||
57 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
58 | } | ||
59 | |||
60 | pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self { | ||
61 | self.vec.extend(filler.take(self.remaining()).casted(&Interner)); | ||
62 | assert_eq!(self.remaining(), 0); | ||
63 | self | ||
64 | } | ||
65 | |||
66 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { | ||
67 | assert!(self.vec.is_empty()); | ||
68 | assert!(parent_substs.len(&Interner) <= self.param_count); | ||
69 | self.vec.extend(parent_substs.iter(&Interner).cloned()); | ||
70 | self | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl TyBuilder<()> { | ||
75 | pub fn unit() -> Ty { | ||
76 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) | ||
77 | } | ||
78 | |||
79 | pub fn fn_ptr(sig: CallableSig) -> Ty { | ||
80 | TyKind::Function(FnPointer { | ||
81 | num_args: sig.params().len(), | ||
82 | sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, | ||
83 | substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), | ||
84 | }) | ||
85 | .intern(&Interner) | ||
86 | } | ||
87 | |||
88 | pub fn builtin(builtin: BuiltinType) -> Ty { | ||
89 | match builtin { | ||
90 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), | ||
91 | BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), | ||
92 | BuiltinType::Str => TyKind::Str.intern(&Interner), | ||
93 | BuiltinType::Int(t) => { | ||
94 | TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) | ||
95 | } | ||
96 | BuiltinType::Uint(t) => { | ||
97 | TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) | ||
98 | } | ||
99 | BuiltinType::Float(t) => { | ||
100 | TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution { | ||
106 | let params = generics(db.upcast(), def.into()); | ||
107 | params.type_params_subst(db) | ||
108 | } | ||
109 | |||
110 | pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> { | ||
111 | let def = def.into(); | ||
112 | let params = generics(db.upcast(), def); | ||
113 | let param_count = params.len(); | ||
114 | TyBuilder::new((), param_count) | ||
115 | } | ||
116 | |||
117 | pub fn build(self) -> Substitution { | ||
118 | let ((), subst) = self.build_internal(); | ||
119 | subst | ||
120 | } | ||
121 | } | ||
122 | |||
123 | impl TyBuilder<hir_def::AdtId> { | ||
124 | pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> { | ||
125 | let generics = generics(db.upcast(), adt.into()); | ||
126 | let param_count = generics.len(); | ||
127 | TyBuilder::new(adt, param_count) | ||
128 | } | ||
129 | |||
130 | pub fn fill_with_defaults( | ||
131 | mut self, | ||
132 | db: &dyn HirDatabase, | ||
133 | mut fallback: impl FnMut() -> Ty, | ||
134 | ) -> Self { | ||
135 | let defaults = db.generic_defaults(self.data.into()); | ||
136 | for default_ty in defaults.iter().skip(self.vec.len()) { | ||
137 | if default_ty.skip_binders().is_unknown() { | ||
138 | self.vec.push(fallback().cast(&Interner)); | ||
139 | } else { | ||
140 | // each default can depend on the previous parameters | ||
141 | let subst_so_far = Substitution::intern(self.vec.clone()); | ||
142 | self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); | ||
143 | } | ||
144 | } | ||
145 | self | ||
146 | } | ||
147 | |||
148 | pub fn build(self) -> Ty { | ||
149 | let (adt, subst) = self.build_internal(); | ||
150 | TyKind::Adt(AdtId(adt), subst).intern(&Interner) | ||
151 | } | ||
152 | } | ||
153 | |||
154 | pub struct Tuple(usize); | ||
155 | impl TyBuilder<Tuple> { | ||
156 | pub fn tuple(size: usize) -> TyBuilder<Tuple> { | ||
157 | TyBuilder::new(Tuple(size), size) | ||
158 | } | ||
159 | |||
160 | pub fn build(self) -> Ty { | ||
161 | let (Tuple(size), subst) = self.build_internal(); | ||
162 | TyKind::Tuple(size, subst).intern(&Interner) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | impl TyBuilder<TraitId> { | ||
167 | pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> { | ||
168 | let generics = generics(db.upcast(), trait_id.into()); | ||
169 | let param_count = generics.len(); | ||
170 | TyBuilder::new(trait_id, param_count) | ||
171 | } | ||
172 | |||
173 | pub fn build(self) -> TraitRef { | ||
174 | let (trait_id, substitution) = self.build_internal(); | ||
175 | TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } | ||
176 | } | ||
177 | } | ||
178 | |||
179 | impl TyBuilder<TypeAliasId> { | ||
180 | pub fn assoc_type_projection( | ||
181 | db: &dyn HirDatabase, | ||
182 | type_alias: TypeAliasId, | ||
183 | ) -> TyBuilder<TypeAliasId> { | ||
184 | let generics = generics(db.upcast(), type_alias.into()); | ||
185 | let param_count = generics.len(); | ||
186 | TyBuilder::new(type_alias, param_count) | ||
187 | } | ||
188 | |||
189 | pub fn build(self) -> ProjectionTy { | ||
190 | let (type_alias, substitution) = self.build_internal(); | ||
191 | ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution } | ||
192 | } | ||
193 | } | ||
194 | |||
195 | impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { | ||
196 | fn subst_binders(b: Binders<T>) -> Self { | ||
197 | let param_count = b.num_binders; | ||
198 | TyBuilder::new(b, param_count) | ||
199 | } | ||
200 | |||
201 | pub fn build(self) -> T { | ||
202 | let (b, subst) = self.build_internal(); | ||
203 | b.subst(&subst) | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl TyBuilder<Binders<Ty>> { | ||
208 | pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> { | ||
209 | TyBuilder::subst_binders(db.ty(def.into())) | ||
210 | } | ||
211 | |||
212 | pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> { | ||
213 | TyBuilder::subst_binders(db.impl_self_ty(def)) | ||
214 | } | ||
215 | |||
216 | pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> { | ||
217 | TyBuilder::subst_binders(db.value_ty(def)) | ||
218 | } | ||
219 | } | ||
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs new file mode 100644 index 000000000..b7463366b --- /dev/null +++ b/crates/hir_ty/src/chalk_ext.rs | |||
@@ -0,0 +1,13 @@ | |||
1 | //! Various extensions traits for Chalk types. | ||
2 | |||
3 | use crate::{Interner, Ty, TyKind}; | ||
4 | |||
5 | pub trait TyExt { | ||
6 | fn is_unit(&self) -> bool; | ||
7 | } | ||
8 | |||
9 | impl TyExt for Ty { | ||
10 | fn is_unit(&self) -> bool { | ||
11 | matches!(self.kind(&Interner), TyKind::Tuple(0, _)) | ||
12 | } | ||
13 | } | ||
diff --git a/crates/hir_ty/src/db.rs b/crates/hir_ty/src/db.rs index 58e4247c6..4300680d9 100644 --- a/crates/hir_ty/src/db.rs +++ b/crates/hir_ty/src/db.rs | |||
@@ -123,7 +123,7 @@ pub trait HirDatabase: DefDatabase + Upcast<dyn DefDatabase> { | |||
123 | &self, | 123 | &self, |
124 | krate: CrateId, | 124 | krate: CrateId, |
125 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, | 125 | goal: crate::Canonical<crate::InEnvironment<crate::DomainGoal>>, |
126 | ) -> Option<crate::traits::Solution>; | 126 | ) -> Option<crate::Solution>; |
127 | 127 | ||
128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] | 128 | #[salsa::invoke(crate::traits::chalk::program_clauses_for_chalk_env_query)] |
129 | fn program_clauses_for_chalk_env( | 129 | fn program_clauses_for_chalk_env( |
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 33a0f4d7d..1c9f9ede7 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
91 | 91 | ||
92 | fn validate_func(&mut self, func: FunctionId) { | 92 | fn validate_func(&mut self, func: FunctionId) { |
93 | let data = self.db.function_data(func); | 93 | let data = self.db.function_data(func); |
94 | if data.is_in_extern_block { | 94 | if data.is_in_extern_block() { |
95 | cov_mark::hit!(extern_func_incorrect_case_ignored); | 95 | cov_mark::hit!(extern_func_incorrect_case_ignored); |
96 | return; | 96 | return; |
97 | } | 97 | } |
@@ -99,8 +99,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
99 | let body = self.db.body(func.into()); | 99 | let body = self.db.body(func.into()); |
100 | 100 | ||
101 | // Recursively validate inner scope items, such as static variables and constants. | 101 | // Recursively validate inner scope items, such as static variables and constants. |
102 | let db = self.db; | 102 | for (_, block_def_map) in body.blocks(self.db.upcast()) { |
103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | ||
104 | for (_, module) in block_def_map.modules() { | 103 | for (_, module) in block_def_map.modules() { |
105 | for def_id in module.scope.declarations() { | 104 | for def_id in module.scope.declarations() { |
106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 105 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index ad1259b34..8169b759f 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | MissingPatFields, RemoveThisSemicolon, | 15 | MissingPatFields, RemoveThisSemicolon, |
16 | }, | 16 | }, |
17 | utils::variant_data, | 17 | utils::variant_data, |
18 | AdtId, InferenceResult, Interner, Ty, TyKind, | 18 | AdtId, InferenceResult, Interner, TyExt, TyKind, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub(crate) use hir_def::{ | 21 | pub(crate) use hir_def::{ |
@@ -423,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
423 | None => return, | 423 | None => return, |
424 | }; | 424 | }; |
425 | 425 | ||
426 | if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { | 426 | if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty { |
427 | return; | 427 | return; |
428 | } | 428 | } |
429 | 429 | ||
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index a71eebc6f..b5efe9df5 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { | |||
32 | let def = self.owner; | 32 | let def = self.owner; |
33 | let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); | 33 | let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); |
34 | let is_unsafe = match self.owner { | 34 | let is_unsafe = match self.owner { |
35 | DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, | 35 | DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(), |
36 | DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, | 36 | DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, |
37 | }; | 37 | }; |
38 | if is_unsafe | 38 | if is_unsafe |
@@ -86,7 +86,7 @@ fn walk_unsafe( | |||
86 | match expr { | 86 | match expr { |
87 | &Expr::Call { callee, .. } => { | 87 | &Expr::Call { callee, .. } => { |
88 | if let Some(func) = infer[callee].as_fn_def(db) { | 88 | if let Some(func) = infer[callee].as_fn_def(db) { |
89 | if db.function_data(func).qualifier.is_unsafe { | 89 | if db.function_data(func).is_unsafe() { |
90 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 90 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
91 | } | 91 | } |
92 | } | 92 | } |
@@ -103,7 +103,7 @@ fn walk_unsafe( | |||
103 | Expr::MethodCall { .. } => { | 103 | Expr::MethodCall { .. } => { |
104 | if infer | 104 | if infer |
105 | .method_resolution(current) | 105 | .method_resolution(current) |
106 | .map(|func| db.function_data(func).qualifier.is_unsafe) | 106 | .map(|func| db.function_data(func).is_unsafe()) |
107 | .unwrap_or(false) | 107 | .unwrap_or(false) |
108 | { | 108 | { |
109 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 109 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 97f1092c6..148eb7506 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -19,7 +19,7 @@ use crate::{ | |||
19 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 19 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
20 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 20 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
21 | CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, | 21 | CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, |
22 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 22 | ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | pub struct HirFormatter<'a> { | 25 | pub struct HirFormatter<'a> { |
@@ -260,7 +260,7 @@ impl HirDisplay for ProjectionTy { | |||
260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | 260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; |
261 | if self.substitution.len(&Interner) > 1 { | 261 | if self.substitution.len(&Interner) > 1 { |
262 | write!(f, "<")?; | 262 | write!(f, "<")?; |
263 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; | 263 | f.write_joined(&self.substitution.interned()[1..], ", ")?; |
264 | write!(f, ">")?; | 264 | write!(f, ">")?; |
265 | } | 265 | } |
266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; | 266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; |
@@ -387,7 +387,7 @@ impl HirDisplay for Ty { | |||
387 | write!(f, ",)")?; | 387 | write!(f, ",)")?; |
388 | } else { | 388 | } else { |
389 | write!(f, "(")?; | 389 | write!(f, "(")?; |
390 | f.write_joined(&*substs.0, ", ")?; | 390 | f.write_joined(&*substs.interned(), ", ")?; |
391 | write!(f, ")")?; | 391 | write!(f, ")")?; |
392 | } | 392 | } |
393 | } | 393 | } |
@@ -415,7 +415,7 @@ impl HirDisplay for Ty { | |||
415 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? | 415 | // We print all params except implicit impl Trait params. Still a bit weird; should we leave out parent and self? |
416 | if total_len > 0 { | 416 | if total_len > 0 { |
417 | write!(f, "<")?; | 417 | write!(f, "<")?; |
418 | f.write_joined(¶meters.0[..total_len], ", ")?; | 418 | f.write_joined(¶meters.interned()[..total_len], ", ")?; |
419 | write!(f, ">")?; | 419 | write!(f, ">")?; |
420 | } | 420 | } |
421 | } | 421 | } |
@@ -423,7 +423,7 @@ impl HirDisplay for Ty { | |||
423 | f.write_joined(sig.params(), ", ")?; | 423 | f.write_joined(sig.params(), ", ")?; |
424 | write!(f, ")")?; | 424 | write!(f, ")")?; |
425 | let ret = sig.ret(); | 425 | let ret = sig.ret(); |
426 | if *ret != Ty::unit() { | 426 | if !ret.is_unit() { |
427 | let ret_display = ret.into_displayable( | 427 | let ret_display = ret.into_displayable( |
428 | f.db, | 428 | f.db, |
429 | f.max_size, | 429 | f.max_size, |
@@ -468,7 +468,7 @@ impl HirDisplay for Ty { | |||
468 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) | 468 | .map(|generic_def_id| f.db.generic_defaults(generic_def_id)) |
469 | .filter(|defaults| !defaults.is_empty()) | 469 | .filter(|defaults| !defaults.is_empty()) |
470 | { | 470 | { |
471 | None => parameters.0.as_ref(), | 471 | None => parameters.interned().as_ref(), |
472 | Some(default_parameters) => { | 472 | Some(default_parameters) => { |
473 | let mut default_from = 0; | 473 | let mut default_from = 0; |
474 | for (i, parameter) in parameters.iter(&Interner).enumerate() { | 474 | for (i, parameter) in parameters.iter(&Interner).enumerate() { |
@@ -490,11 +490,11 @@ impl HirDisplay for Ty { | |||
490 | } | 490 | } |
491 | } | 491 | } |
492 | } | 492 | } |
493 | ¶meters.0[0..default_from] | 493 | ¶meters.interned()[0..default_from] |
494 | } | 494 | } |
495 | } | 495 | } |
496 | } else { | 496 | } else { |
497 | parameters.0.as_ref() | 497 | parameters.interned().as_ref() |
498 | }; | 498 | }; |
499 | if !parameters_to_write.is_empty() { | 499 | if !parameters_to_write.is_empty() { |
500 | write!(f, "<")?; | 500 | write!(f, "<")?; |
@@ -517,7 +517,7 @@ impl HirDisplay for Ty { | |||
517 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; | 517 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
518 | if parameters.len(&Interner) > 0 { | 518 | if parameters.len(&Interner) > 0 { |
519 | write!(f, "<")?; | 519 | write!(f, "<")?; |
520 | f.write_joined(&*parameters.0, ", ")?; | 520 | f.write_joined(&*parameters.interned(), ", ")?; |
521 | write!(f, ">")?; | 521 | write!(f, ">")?; |
522 | } | 522 | } |
523 | } else { | 523 | } else { |
@@ -591,7 +591,7 @@ impl HirDisplay for Ty { | |||
591 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 591 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
592 | } | 592 | } |
593 | TypeParamProvenance::ArgumentImplTrait => { | 593 | TypeParamProvenance::ArgumentImplTrait => { |
594 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 594 | let substs = generics.type_params_subst(f.db); |
595 | let bounds = f | 595 | let bounds = f |
596 | .db | 596 | .db |
597 | .generic_predicates(id.parent) | 597 | .generic_predicates(id.parent) |
@@ -663,7 +663,7 @@ impl HirDisplay for CallableSig { | |||
663 | } | 663 | } |
664 | write!(f, ")")?; | 664 | write!(f, ")")?; |
665 | let ret = self.ret(); | 665 | let ret = self.ret(); |
666 | if *ret != Ty::unit() { | 666 | if !ret.is_unit() { |
667 | let ret_display = | 667 | let ret_display = |
668 | ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 668 | ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
669 | write!(f, " -> {}", ret_display)?; | 669 | write!(f, " -> {}", ret_display)?; |
@@ -727,13 +727,13 @@ fn write_bounds_like_dyn_trait( | |||
727 | // existential) here, which is the only thing that's | 727 | // existential) here, which is the only thing that's |
728 | // possible in actual Rust, and hence don't print it | 728 | // possible in actual Rust, and hence don't print it |
729 | write!(f, "{}", f.db.trait_data(trait_).name)?; | 729 | write!(f, "{}", f.db.trait_data(trait_).name)?; |
730 | if let [_, params @ ..] = &*trait_ref.substitution.0 { | 730 | if let [_, params @ ..] = &*trait_ref.substitution.interned() { |
731 | if is_fn_trait { | 731 | if is_fn_trait { |
732 | if let Some(args) = | 732 | if let Some(args) = |
733 | params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) | 733 | params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) |
734 | { | 734 | { |
735 | write!(f, "(")?; | 735 | write!(f, "(")?; |
736 | f.write_joined(&*args.0, ", ")?; | 736 | f.write_joined(&*args.interned(), ", ")?; |
737 | write!(f, ")")?; | 737 | write!(f, ")")?; |
738 | } | 738 | } |
739 | } else if !params.is_empty() { | 739 | } else if !params.is_empty() { |
@@ -789,7 +789,7 @@ impl TraitRef { | |||
789 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; | 789 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; |
790 | if self.substitution.len(&Interner) > 1 { | 790 | if self.substitution.len(&Interner) > 1 { |
791 | write!(f, "<")?; | 791 | write!(f, "<")?; |
792 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; | 792 | f.write_joined(&self.substitution.interned()[1..], ", ")?; |
793 | write!(f, ">")?; | 793 | write!(f, ">")?; |
794 | } | 794 | } |
795 | Ok(()) | 795 | Ok(()) |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index b871594bd..bb885db35 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -37,12 +37,12 @@ use stdx::impl_from; | |||
37 | use syntax::SmolStr; | 37 | use syntax::SmolStr; |
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{DomainGoal, Guidance, Solution}, | 40 | DomainGoal, Guidance, InEnvironment, ProjectionTy, Solution, TraitEnvironment, TraitRef, Ty, |
41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, | 41 | TypeWalk, |
42 | }; | 42 | }; |
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, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, | 45 | to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | // This lint has a false positive here. See the link below for details. | 48 | // This lint has a false positive here. See the link below for details. |
@@ -409,16 +409,14 @@ impl<'a> InferenceContext<'a> { | |||
409 | _ => panic!("resolve_associated_type called with non-associated type"), | 409 | _ => panic!("resolve_associated_type called with non-associated type"), |
410 | }; | 410 | }; |
411 | let ty = self.table.new_type_var(); | 411 | let ty = self.table.new_type_var(); |
412 | let substs = Substitution::build_for_def(self.db, res_assoc_ty) | 412 | let trait_ref = TyBuilder::trait_ref(self.db, trait_) |
413 | .push(inner_ty) | 413 | .push(inner_ty) |
414 | .fill(params.iter().cloned()) | 414 | .fill(params.iter().cloned()) |
415 | .build(); | 415 | .build(); |
416 | let trait_ref = | ||
417 | TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() }; | ||
418 | let alias_eq = AliasEq { | 416 | let alias_eq = AliasEq { |
419 | alias: AliasTy::Projection(ProjectionTy { | 417 | alias: AliasTy::Projection(ProjectionTy { |
420 | associated_ty_id: to_assoc_type_id(res_assoc_ty), | 418 | associated_ty_id: to_assoc_type_id(res_assoc_ty), |
421 | substitution: substs, | 419 | substitution: trait_ref.substitution.clone(), |
422 | }), | 420 | }), |
423 | ty: ty.clone(), | 421 | ty: ty.clone(), |
424 | }; | 422 | }; |
@@ -489,7 +487,7 @@ impl<'a> InferenceContext<'a> { | |||
489 | } | 487 | } |
490 | TypeNs::SelfType(impl_id) => { | 488 | TypeNs::SelfType(impl_id) => { |
491 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 489 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
492 | let substs = Substitution::type_params_for_generics(self.db, &generics); | 490 | let substs = generics.type_params_subst(self.db); |
493 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | 491 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); |
494 | match unresolved { | 492 | match unresolved { |
495 | None => { | 493 | None => { |
@@ -516,10 +514,9 @@ impl<'a> InferenceContext<'a> { | |||
516 | } | 514 | } |
517 | } | 515 | } |
518 | TypeNs::TypeAliasId(it) => { | 516 | TypeNs::TypeAliasId(it) => { |
519 | let substs = Substitution::build_for_def(self.db, it) | 517 | let ty = TyBuilder::def_ty(self.db, it.into()) |
520 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 518 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
521 | .build(); | 519 | .build(); |
522 | let ty = self.db.ty(it.into()).subst(&substs); | ||
523 | let variant = ty_variant(&ty); | 520 | let variant = ty_variant(&ty); |
524 | forbid_unresolved_segments((ty, variant), unresolved) | 521 | forbid_unresolved_segments((ty, variant), unresolved) |
525 | } | 522 | } |
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs index d887e21a2..32c273afc 100644 --- a/crates/hir_ty/src/infer/coerce.rs +++ b/crates/hir_ty/src/infer/coerce.rs | |||
@@ -7,9 +7,7 @@ | |||
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::{ | 10 | use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind}; |
11 | autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind, | ||
12 | }; | ||
13 | 11 | ||
14 | use super::{InEnvironment, InferenceContext}; | 12 | use super::{InEnvironment, InferenceContext}; |
15 | 13 | ||
@@ -44,8 +42,8 @@ impl<'a> InferenceContext<'a> { | |||
44 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 | 42 | // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 |
45 | let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); | 43 | let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); |
46 | let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); | 44 | let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); |
47 | let ptr_ty1 = Ty::fn_ptr(sig1); | 45 | let ptr_ty1 = TyBuilder::fn_ptr(sig1); |
48 | let ptr_ty2 = Ty::fn_ptr(sig2); | 46 | let ptr_ty2 = TyBuilder::fn_ptr(sig2); |
49 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) | 47 | self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) |
50 | } else { | 48 | } else { |
51 | cov_mark::hit!(coerce_merge_fail_fallback); | 49 | cov_mark::hit!(coerce_merge_fail_fallback); |
@@ -95,7 +93,7 @@ impl<'a> InferenceContext<'a> { | |||
95 | (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { | 93 | (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { |
96 | None => return false, | 94 | None => return false, |
97 | Some(sig) => { | 95 | Some(sig) => { |
98 | from_ty = Ty::fn_ptr(sig); | 96 | from_ty = TyBuilder::fn_ptr(sig); |
99 | } | 97 | } |
100 | }, | 98 | }, |
101 | 99 | ||
@@ -130,18 +128,15 @@ impl<'a> InferenceContext<'a> { | |||
130 | _ => return None, | 128 | _ => return None, |
131 | }; | 129 | }; |
132 | 130 | ||
133 | let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); | 131 | let trait_ref = { |
134 | if generic_params.len() != 2 { | 132 | let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait); |
135 | // The CoerceUnsized trait should have two generic params: Self and T. | 133 | if b.remaining() != 2 { |
136 | return None; | 134 | // The CoerceUnsized trait should have two generic params: Self and T. |
137 | } | 135 | return None; |
136 | } | ||
137 | b.push(from_ty.clone()).push(to_ty.clone()).build() | ||
138 | }; | ||
138 | 139 | ||
139 | let substs = Substitution::build_for_generics(&generic_params) | ||
140 | .push(from_ty.clone()) | ||
141 | .push(to_ty.clone()) | ||
142 | .build(); | ||
143 | let trait_ref = | ||
144 | TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs }; | ||
145 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); | 140 | let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); |
146 | 141 | ||
147 | let canonicalizer = self.canonicalizer(); | 142 | let canonicalizer = self.canonicalizer(); |
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs index dd3914ec3..ccaae53e9 100644 --- a/crates/hir_ty/src/infer/expr.rs +++ b/crates/hir_ty/src/infer/expr.rs | |||
@@ -19,11 +19,11 @@ use crate::{ | |||
19 | lower::lower_to_chalk_mutability, | 19 | lower::lower_to_chalk_mutability, |
20 | method_resolution, op, | 20 | method_resolution, op, |
21 | primitive::{self, UintTy}, | 21 | primitive::{self, UintTy}, |
22 | to_assoc_type_id, to_chalk_trait_id, | 22 | to_chalk_trait_id, |
23 | traits::{chalk::from_chalk, FnTrait, InEnvironment}, | 23 | traits::{chalk::from_chalk, FnTrait}, |
24 | utils::{generics, variant_data, Generics}, | 24 | utils::{generics, variant_data, Generics}, |
25 | AdtId, Binders, CallableDefId, DomainGoal, FnPointer, FnSig, Interner, Rawness, Scalar, | 25 | AdtId, Binders, CallableDefId, FnPointer, FnSig, InEnvironment, Interner, Rawness, Scalar, |
26 | Substitution, TraitRef, Ty, TyKind, | 26 | Substitution, TraitRef, Ty, TyBuilder, TyKind, |
27 | }; | 27 | }; |
28 | 28 | ||
29 | use super::{ | 29 | use super::{ |
@@ -73,38 +73,33 @@ impl<'a> InferenceContext<'a> { | |||
73 | let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; | 73 | let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; |
74 | let output_assoc_type = | 74 | let output_assoc_type = |
75 | self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; | 75 | self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; |
76 | let generic_params = generics(self.db.upcast(), fn_once_trait.into()); | ||
77 | if generic_params.len() != 2 { | ||
78 | return None; | ||
79 | } | ||
80 | 76 | ||
81 | let mut param_builder = Substitution::builder(num_args); | ||
82 | let mut arg_tys = vec![]; | 77 | let mut arg_tys = vec![]; |
83 | for _ in 0..num_args { | 78 | let arg_ty = TyBuilder::tuple(num_args) |
84 | let arg = self.table.new_type_var(); | 79 | .fill(repeat_with(|| { |
85 | param_builder = param_builder.push(arg.clone()); | 80 | let arg = self.table.new_type_var(); |
86 | arg_tys.push(arg); | 81 | arg_tys.push(arg.clone()); |
87 | } | 82 | arg |
88 | let parameters = param_builder.build(); | 83 | })) |
89 | let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); | 84 | .build(); |
90 | let substs = | 85 | |
91 | Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); | 86 | let projection = { |
87 | let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type); | ||
88 | if b.remaining() != 2 { | ||
89 | return None; | ||
90 | } | ||
91 | b.push(ty.clone()).push(arg_ty).build() | ||
92 | }; | ||
92 | 93 | ||
93 | let trait_env = self.trait_env.env.clone(); | 94 | let trait_env = self.trait_env.env.clone(); |
94 | let implements_fn_trait: DomainGoal = | 95 | let obligation = InEnvironment { |
95 | TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } | 96 | goal: projection.trait_ref(self.db).cast(&Interner), |
96 | .cast(&Interner); | ||
97 | let goal = self.canonicalizer().canonicalize_obligation(InEnvironment { | ||
98 | goal: implements_fn_trait.clone(), | ||
99 | environment: trait_env, | 97 | environment: trait_env, |
100 | }); | 98 | }; |
101 | if self.db.trait_solve(krate, goal.value).is_some() { | 99 | let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone()); |
102 | self.push_obligation(implements_fn_trait); | 100 | if self.db.trait_solve(krate, canonical.value).is_some() { |
103 | let output_proj_ty = crate::ProjectionTy { | 101 | self.push_obligation(obligation.goal); |
104 | associated_ty_id: to_assoc_type_id(output_assoc_type), | 102 | let return_ty = self.normalize_projection_ty(projection); |
105 | substitution: substs, | ||
106 | }; | ||
107 | let return_ty = self.normalize_projection_ty(output_proj_ty); | ||
108 | Some((arg_tys, return_ty)) | 103 | Some((arg_tys, return_ty)) |
109 | } else { | 104 | } else { |
110 | None | 105 | None |
@@ -138,7 +133,7 @@ impl<'a> InferenceContext<'a> { | |||
138 | both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); | 133 | both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); |
139 | let else_ty = match else_branch { | 134 | let else_ty = match else_branch { |
140 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), | 135 | Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), |
141 | None => Ty::unit(), | 136 | None => TyBuilder::unit(), |
142 | }; | 137 | }; |
143 | both_arms_diverge &= self.diverges; | 138 | both_arms_diverge &= self.diverges; |
144 | 139 | ||
@@ -193,7 +188,7 @@ impl<'a> InferenceContext<'a> { | |||
193 | break_ty: self.table.new_type_var(), | 188 | break_ty: self.table.new_type_var(), |
194 | label: label.map(|label| self.body[label].name.clone()), | 189 | label: label.map(|label| self.body[label].name.clone()), |
195 | }); | 190 | }); |
196 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 191 | self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); |
197 | 192 | ||
198 | let ctxt = self.breakables.pop().expect("breakable stack broken"); | 193 | let ctxt = self.breakables.pop().expect("breakable stack broken"); |
199 | if ctxt.may_break { | 194 | if ctxt.may_break { |
@@ -217,11 +212,11 @@ impl<'a> InferenceContext<'a> { | |||
217 | *condition, | 212 | *condition, |
218 | &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), | 213 | &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), |
219 | ); | 214 | ); |
220 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 215 | self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); |
221 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | 216 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); |
222 | // the body may not run, so it diverging doesn't mean we diverge | 217 | // the body may not run, so it diverging doesn't mean we diverge |
223 | self.diverges = Diverges::Maybe; | 218 | self.diverges = Diverges::Maybe; |
224 | Ty::unit() | 219 | TyBuilder::unit() |
225 | } | 220 | } |
226 | Expr::For { iterable, body, pat, label } => { | 221 | Expr::For { iterable, body, pat, label } => { |
227 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); | 222 | let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); |
@@ -236,11 +231,11 @@ impl<'a> InferenceContext<'a> { | |||
236 | 231 | ||
237 | self.infer_pat(*pat, &pat_ty, BindingMode::default()); | 232 | self.infer_pat(*pat, &pat_ty, BindingMode::default()); |
238 | 233 | ||
239 | self.infer_expr(*body, &Expectation::has_type(Ty::unit())); | 234 | self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit())); |
240 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); | 235 | let _ctxt = self.breakables.pop().expect("breakable stack broken"); |
241 | // the body may not run, so it diverging doesn't mean we diverge | 236 | // the body may not run, so it diverging doesn't mean we diverge |
242 | self.diverges = Diverges::Maybe; | 237 | self.diverges = Diverges::Maybe; |
243 | Ty::unit() | 238 | TyBuilder::unit() |
244 | } | 239 | } |
245 | Expr::Lambda { body, args, ret_type, arg_types } => { | 240 | Expr::Lambda { body, args, ret_type, arg_types } => { |
246 | assert_eq!(args.len(), arg_types.len()); | 241 | assert_eq!(args.len(), arg_types.len()); |
@@ -360,7 +355,7 @@ impl<'a> InferenceContext<'a> { | |||
360 | let val_ty = if let Some(expr) = expr { | 355 | let val_ty = if let Some(expr) = expr { |
361 | self.infer_expr(*expr, &Expectation::none()) | 356 | self.infer_expr(*expr, &Expectation::none()) |
362 | } else { | 357 | } else { |
363 | Ty::unit() | 358 | TyBuilder::unit() |
364 | }; | 359 | }; |
365 | 360 | ||
366 | let last_ty = | 361 | let last_ty = |
@@ -386,7 +381,7 @@ impl<'a> InferenceContext<'a> { | |||
386 | if let Some(expr) = expr { | 381 | if let Some(expr) = expr { |
387 | self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); | 382 | self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); |
388 | } else { | 383 | } else { |
389 | let unit = Ty::unit(); | 384 | let unit = TyBuilder::unit(); |
390 | self.coerce(&unit, &self.return_ty.clone()); | 385 | self.coerce(&unit, &self.return_ty.clone()); |
391 | } | 386 | } |
392 | TyKind::Never.intern(&Interner) | 387 | TyKind::Never.intern(&Interner) |
@@ -457,11 +452,7 @@ impl<'a> InferenceContext<'a> { | |||
457 | }; | 452 | }; |
458 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { | 453 | match canonicalized.decanonicalize_ty(derefed_ty.value).kind(&Interner) { |
459 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { | 454 | TyKind::Tuple(_, substs) => name.as_tuple_index().and_then(|idx| { |
460 | substs | 455 | substs.interned().get(idx).map(|a| a.assert_ty_ref(&Interner)).cloned() |
461 | .interned(&Interner) | ||
462 | .get(idx) | ||
463 | .map(|a| a.assert_ty_ref(&Interner)) | ||
464 | .cloned() | ||
465 | }), | 456 | }), |
466 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { | 457 | TyKind::Adt(AdtId(hir_def::AdtId::StructId(s)), parameters) => { |
467 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; | 458 | let local_id = self.db.struct_data(*s).variant_data.field(name)?; |
@@ -539,17 +530,10 @@ impl<'a> InferenceContext<'a> { | |||
539 | Expr::Box { expr } => { | 530 | Expr::Box { expr } => { |
540 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); | 531 | let inner_ty = self.infer_expr_inner(*expr, &Expectation::none()); |
541 | if let Some(box_) = self.resolve_boxed_box() { | 532 | if let Some(box_) = self.resolve_boxed_box() { |
542 | let mut sb = | 533 | TyBuilder::adt(self.db, box_) |
543 | Substitution::build_for_generics(&generics(self.db.upcast(), box_.into())); | 534 | .push(inner_ty) |
544 | sb = sb.push(inner_ty); | 535 | .fill_with_defaults(self.db, || self.table.new_type_var()) |
545 | match self.db.generic_defaults(box_.into()).get(1) { | 536 | .build() |
546 | Some(alloc_ty) if !alloc_ty.value.is_unknown() && sb.remaining() > 0 => { | ||
547 | sb = sb.push(alloc_ty.value.clone()); | ||
548 | } | ||
549 | _ => (), | ||
550 | } | ||
551 | sb = sb.fill(repeat_with(|| self.table.new_type_var())); | ||
552 | Ty::adt_ty(box_, sb.build()) | ||
553 | } else { | 537 | } else { |
554 | self.err_ty() | 538 | self.err_ty() |
555 | } | 539 | } |
@@ -639,31 +623,31 @@ impl<'a> InferenceContext<'a> { | |||
639 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); | 623 | let rhs_ty = rhs.map(|e| self.infer_expr(e, &rhs_expect)); |
640 | match (range_type, lhs_ty, rhs_ty) { | 624 | match (range_type, lhs_ty, rhs_ty) { |
641 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { | 625 | (RangeOp::Exclusive, None, None) => match self.resolve_range_full() { |
642 | Some(adt) => Ty::adt_ty(adt, Substitution::empty(&Interner)), | 626 | Some(adt) => TyBuilder::adt(self.db, adt).build(), |
643 | None => self.err_ty(), | 627 | None => self.err_ty(), |
644 | }, | 628 | }, |
645 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { | 629 | (RangeOp::Exclusive, None, Some(ty)) => match self.resolve_range_to() { |
646 | Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), | 630 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), |
647 | None => self.err_ty(), | 631 | None => self.err_ty(), |
648 | }, | 632 | }, |
649 | (RangeOp::Inclusive, None, Some(ty)) => { | 633 | (RangeOp::Inclusive, None, Some(ty)) => { |
650 | match self.resolve_range_to_inclusive() { | 634 | match self.resolve_range_to_inclusive() { |
651 | Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), | 635 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), |
652 | None => self.err_ty(), | 636 | None => self.err_ty(), |
653 | } | 637 | } |
654 | } | 638 | } |
655 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { | 639 | (RangeOp::Exclusive, Some(_), Some(ty)) => match self.resolve_range() { |
656 | Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), | 640 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), |
657 | None => self.err_ty(), | 641 | None => self.err_ty(), |
658 | }, | 642 | }, |
659 | (RangeOp::Inclusive, Some(_), Some(ty)) => { | 643 | (RangeOp::Inclusive, Some(_), Some(ty)) => { |
660 | match self.resolve_range_inclusive() { | 644 | match self.resolve_range_inclusive() { |
661 | Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), | 645 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), |
662 | None => self.err_ty(), | 646 | None => self.err_ty(), |
663 | } | 647 | } |
664 | } | 648 | } |
665 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { | 649 | (RangeOp::Exclusive, Some(ty), None) => match self.resolve_range_from() { |
666 | Some(adt) => Ty::adt_ty(adt, Substitution::single(ty)), | 650 | Some(adt) => TyBuilder::adt(self.db, adt).push(ty).build(), |
667 | None => self.err_ty(), | 651 | None => self.err_ty(), |
668 | }, | 652 | }, |
669 | (RangeOp::Inclusive, _, None) => self.err_ty(), | 653 | (RangeOp::Inclusive, _, None) => self.err_ty(), |
@@ -828,8 +812,8 @@ impl<'a> InferenceContext<'a> { | |||
828 | // we don't even make an attempt at coercion | 812 | // we don't even make an attempt at coercion |
829 | self.table.new_maybe_never_var() | 813 | self.table.new_maybe_never_var() |
830 | } else { | 814 | } else { |
831 | self.coerce(&Ty::unit(), &expected.coercion_target()); | 815 | self.coerce(&TyBuilder::unit(), &expected.coercion_target()); |
832 | Ty::unit() | 816 | TyBuilder::unit() |
833 | } | 817 | } |
834 | }; | 818 | }; |
835 | ty | 819 | ty |
diff --git a/crates/hir_ty/src/infer/pat.rs b/crates/hir_ty/src/infer/pat.rs index 10df8d8cb..469f37dd9 100644 --- a/crates/hir_ty/src/infer/pat.rs +++ b/crates/hir_ty/src/infer/pat.rs | |||
@@ -13,9 +13,8 @@ use hir_expand::name::Name; | |||
13 | 13 | ||
14 | use super::{BindingMode, Expectation, InferenceContext}; | 14 | use super::{BindingMode, Expectation, InferenceContext}; |
15 | use crate::{ | 15 | use crate::{ |
16 | lower::lower_to_chalk_mutability, | 16 | lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder, |
17 | utils::{generics, variant_data}, | 17 | TyKind, |
18 | Interner, Substitution, Ty, TyKind, | ||
19 | }; | 18 | }; |
20 | 19 | ||
21 | impl<'a> InferenceContext<'a> { | 20 | impl<'a> InferenceContext<'a> { |
@@ -124,7 +123,7 @@ impl<'a> InferenceContext<'a> { | |||
124 | let ty = match &body[pat] { | 123 | let ty = match &body[pat] { |
125 | &Pat::Tuple { ref args, ellipsis } => { | 124 | &Pat::Tuple { ref args, ellipsis } => { |
126 | let expectations = match expected.as_tuple() { | 125 | let expectations = match expected.as_tuple() { |
127 | Some(parameters) => &*parameters.0, | 126 | Some(parameters) => &*parameters.interned(), |
128 | _ => &[], | 127 | _ => &[], |
129 | }; | 128 | }; |
130 | 129 | ||
@@ -240,29 +239,18 @@ impl<'a> InferenceContext<'a> { | |||
240 | let (inner_ty, alloc_ty) = match expected.as_adt() { | 239 | let (inner_ty, alloc_ty) = match expected.as_adt() { |
241 | Some((adt, subst)) if adt == box_adt => ( | 240 | Some((adt, subst)) if adt == box_adt => ( |
242 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), | 241 | subst.at(&Interner, 0).assert_ty_ref(&Interner).clone(), |
243 | subst.interned(&Interner).get(1).and_then(|a| a.ty(&Interner).cloned()), | 242 | subst.interned().get(1).and_then(|a| a.ty(&Interner).cloned()), |
244 | ), | 243 | ), |
245 | _ => (self.result.standard_types.unknown.clone(), None), | 244 | _ => (self.result.standard_types.unknown.clone(), None), |
246 | }; | 245 | }; |
247 | 246 | ||
248 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); | 247 | let inner_ty = self.infer_pat(*inner, &inner_ty, default_bm); |
249 | let mut sb = Substitution::build_for_generics(&generics( | 248 | let mut b = TyBuilder::adt(self.db, box_adt).push(inner_ty); |
250 | self.db.upcast(), | 249 | |
251 | box_adt.into(), | 250 | if let Some(alloc_ty) = alloc_ty { |
252 | )); | 251 | b = b.push(alloc_ty); |
253 | sb = sb.push(inner_ty); | ||
254 | if sb.remaining() == 1 { | ||
255 | sb = sb.push(match alloc_ty { | ||
256 | Some(alloc_ty) if !alloc_ty.is_unknown() => alloc_ty, | ||
257 | _ => match self.db.generic_defaults(box_adt.into()).get(1) { | ||
258 | Some(alloc_ty) if !alloc_ty.value.is_unknown() => { | ||
259 | alloc_ty.value.clone() | ||
260 | } | ||
261 | _ => self.table.new_type_var(), | ||
262 | }, | ||
263 | }); | ||
264 | } | 252 | } |
265 | Ty::adt_ty(box_adt, sb.build()) | 253 | b.fill_with_defaults(self.db, || self.table.new_type_var()).build() |
266 | } | 254 | } |
267 | None => self.err_ty(), | 255 | None => self.err_ty(), |
268 | }, | 256 | }, |
diff --git a/crates/hir_ty/src/infer/path.rs b/crates/hir_ty/src/infer/path.rs index 1ba15f737..637341b53 100644 --- a/crates/hir_ty/src/infer/path.rs +++ b/crates/hir_ty/src/infer/path.rs | |||
@@ -10,9 +10,7 @@ use hir_def::{ | |||
10 | }; | 10 | }; |
11 | use hir_expand::name::Name; | 11 | use hir_expand::name::Name; |
12 | 12 | ||
13 | use crate::{ | 13 | use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId}; |
14 | method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId, | ||
15 | }; | ||
16 | 14 | ||
17 | use super::{ExprOrPatId, InferenceContext, TraitRef}; | 15 | use super::{ExprOrPatId, InferenceContext, TraitRef}; |
18 | 16 | ||
@@ -82,7 +80,7 @@ impl<'a> InferenceContext<'a> { | |||
82 | } | 80 | } |
83 | ValueNs::ImplSelf(impl_id) => { | 81 | ValueNs::ImplSelf(impl_id) => { |
84 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); | 82 | let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); |
85 | let substs = Substitution::type_params_for_generics(self.db, &generics); | 83 | let substs = generics.type_params_subst(self.db); |
86 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); | 84 | let ty = self.db.impl_self_ty(impl_id).subst(&substs); |
87 | if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { | 85 | if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { |
88 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); | 86 | let ty = self.db.value_ty(struct_id.into()).subst(&substs); |
@@ -95,16 +93,13 @@ impl<'a> InferenceContext<'a> { | |||
95 | ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), | 93 | ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), |
96 | }; | 94 | }; |
97 | 95 | ||
98 | let ty = self.db.value_ty(typable); | ||
99 | // self_subst is just for the parent | ||
100 | let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); | 96 | let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); |
101 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); | 97 | let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); |
102 | let substs = ctx.substs_from_path(path, typable, true); | 98 | let substs = ctx.substs_from_path(path, typable, true); |
103 | let full_substs = Substitution::builder(substs.len(&Interner)) | 99 | let ty = TyBuilder::value_ty(self.db, typable) |
104 | .use_parent_substs(&parent_substs) | 100 | .use_parent_substs(&parent_substs) |
105 | .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) | 101 | .fill(substs.interned()[parent_substs.len(&Interner)..].iter().cloned()) |
106 | .build(); | 102 | .build(); |
107 | let ty = ty.subst(&full_substs); | ||
108 | Some(ty) | 103 | Some(ty) |
109 | } | 104 | } |
110 | 105 | ||
@@ -245,7 +240,7 @@ impl<'a> InferenceContext<'a> { | |||
245 | }; | 240 | }; |
246 | let substs = match container { | 241 | let substs = match container { |
247 | AssocContainerId::ImplId(impl_id) => { | 242 | AssocContainerId::ImplId(impl_id) => { |
248 | let impl_substs = Substitution::build_for_def(self.db, impl_id) | 243 | let impl_substs = TyBuilder::subst_for_def(self.db, impl_id) |
249 | .fill(iter::repeat_with(|| self.table.new_type_var())) | 244 | .fill(iter::repeat_with(|| self.table.new_type_var())) |
250 | .build(); | 245 | .build(); |
251 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); | 246 | let impl_self_ty = self.db.impl_self_ty(impl_id).subst(&impl_substs); |
@@ -254,18 +249,12 @@ impl<'a> InferenceContext<'a> { | |||
254 | } | 249 | } |
255 | AssocContainerId::TraitId(trait_) => { | 250 | AssocContainerId::TraitId(trait_) => { |
256 | // we're picking this method | 251 | // we're picking this method |
257 | let trait_substs = Substitution::build_for_def(self.db, trait_) | 252 | let trait_ref = TyBuilder::trait_ref(self.db, trait_) |
258 | .push(ty.clone()) | 253 | .push(ty.clone()) |
259 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) | 254 | .fill(std::iter::repeat_with(|| self.table.new_type_var())) |
260 | .build(); | 255 | .build(); |
261 | self.push_obligation( | 256 | self.push_obligation(trait_ref.clone().cast(&Interner)); |
262 | TraitRef { | 257 | Some(trait_ref.substitution) |
263 | trait_id: to_chalk_trait_id(trait_), | ||
264 | substitution: trait_substs.clone(), | ||
265 | } | ||
266 | .cast(&Interner), | ||
267 | ); | ||
268 | Some(trait_substs) | ||
269 | } | 258 | } |
270 | AssocContainerId::ModuleId(_) => None, | 259 | AssocContainerId::ModuleId(_) => None, |
271 | }; | 260 | }; |
diff --git a/crates/hir_ty/src/infer/unify.rs b/crates/hir_ty/src/infer/unify.rs index d2496db3b..b7bc48569 100644 --- a/crates/hir_ty/src/infer/unify.rs +++ b/crates/hir_ty/src/infer/unify.rs | |||
@@ -186,14 +186,11 @@ pub(crate) fn unify(tys: &Canonical<(Ty, Ty)>) -> Option<Substitution> { | |||
186 | ); | 186 | ); |
187 | } | 187 | } |
188 | } | 188 | } |
189 | Some( | 189 | Some(Substitution::from_iter( |
190 | Substitution::builder(tys.binders.len(&Interner)) | 190 | &Interner, |
191 | .fill( | 191 | vars.iter(&Interner) |
192 | vars.iter(&Interner) | 192 | .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), |
193 | .map(|v| table.resolve_ty_completely(v.assert_ty_ref(&Interner).clone())), | 193 | )) |
194 | ) | ||
195 | .build(), | ||
196 | ) | ||
197 | } | 194 | } |
198 | 195 | ||
199 | #[derive(Clone, Debug)] | 196 | #[derive(Clone, Debug)] |
@@ -287,7 +284,7 @@ impl InferenceTable { | |||
287 | substs2: &Substitution, | 284 | substs2: &Substitution, |
288 | depth: usize, | 285 | depth: usize, |
289 | ) -> bool { | 286 | ) -> bool { |
290 | substs1.0.iter().zip(substs2.0.iter()).all(|(t1, t2)| { | 287 | substs1.iter(&Interner).zip(substs2.iter(&Interner)).all(|(t1, t2)| { |
291 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) | 288 | self.unify_inner(t1.assert_ty_ref(&Interner), t2.assert_ty_ref(&Interner), depth) |
292 | }) | 289 | }) |
293 | } | 290 | } |
diff --git a/crates/hir_ty/src/lib.rs b/crates/hir_ty/src/lib.rs index 4c3d904bf..76609e2df 100644 --- a/crates/hir_ty/src/lib.rs +++ b/crates/hir_ty/src/lib.rs | |||
@@ -14,6 +14,10 @@ mod lower; | |||
14 | pub(crate) mod infer; | 14 | pub(crate) mod infer; |
15 | pub(crate) mod utils; | 15 | pub(crate) mod utils; |
16 | mod chalk_cast; | 16 | mod chalk_cast; |
17 | mod chalk_ext; | ||
18 | mod builder; | ||
19 | mod walk; | ||
20 | mod types; | ||
17 | 21 | ||
18 | pub mod display; | 22 | pub mod display; |
19 | pub mod db; | 23 | pub mod db; |
@@ -24,30 +28,30 @@ mod tests; | |||
24 | #[cfg(test)] | 28 | #[cfg(test)] |
25 | mod test_db; | 29 | mod test_db; |
26 | 30 | ||
27 | use std::{iter, mem, sync::Arc}; | 31 | use std::sync::Arc; |
28 | 32 | ||
29 | use base_db::salsa; | ||
30 | use chalk_ir::cast::{CastTo, Caster}; | ||
31 | use hir_def::{ | ||
32 | builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, | ||
33 | GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId, | ||
34 | }; | ||
35 | use itertools::Itertools; | 33 | use itertools::Itertools; |
36 | use smallvec::SmallVec; | 34 | use smallvec::SmallVec; |
37 | 35 | ||
38 | use crate::{ | 36 | use base_db::salsa; |
39 | db::HirDatabase, | 37 | use hir_def::{ |
40 | display::HirDisplay, | 38 | expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId, GenericDefId, HasModule, Lookup, |
41 | utils::{generics, make_mut_slice, Generics}, | 39 | TraitId, TypeAliasId, TypeParamId, |
42 | }; | 40 | }; |
43 | 41 | ||
42 | use crate::{db::HirDatabase, display::HirDisplay, utils::generics}; | ||
43 | |||
44 | pub use autoderef::autoderef; | 44 | pub use autoderef::autoderef; |
45 | pub use builder::TyBuilder; | ||
46 | pub use chalk_ext::TyExt; | ||
45 | pub use infer::{could_unify, InferenceResult, InferenceVar}; | 47 | pub use infer::{could_unify, InferenceResult, InferenceVar}; |
46 | pub use lower::{ | 48 | pub use lower::{ |
47 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, | 49 | associated_type_shorthand_candidates, callable_item_sig, CallableDefId, ImplTraitLoweringMode, |
48 | TyDefId, TyLoweringContext, ValueTyDefId, | 50 | TyDefId, TyLoweringContext, ValueTyDefId, |
49 | }; | 51 | }; |
50 | pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; | 52 | pub use traits::TraitEnvironment; |
53 | pub use types::*; | ||
54 | pub use walk::TypeWalk; | ||
51 | 55 | ||
52 | pub use chalk_ir::{ | 56 | pub use chalk_ir::{ |
53 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, | 57 | cast::Cast, AdtId, BoundVar, DebruijnIndex, Mutability, Safety, Scalar, TyVariableKind, |
@@ -66,41 +70,6 @@ pub type CanonicalVarKinds = chalk_ir::CanonicalVarKinds<Interner>; | |||
66 | 70 | ||
67 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; | 71 | pub type ChalkTraitId = chalk_ir::TraitId<Interner>; |
68 | 72 | ||
69 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
70 | pub enum Lifetime { | ||
71 | Parameter(LifetimeParamId), | ||
72 | Static, | ||
73 | } | ||
74 | |||
75 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
76 | pub struct OpaqueTy { | ||
77 | pub opaque_ty_id: OpaqueTyId, | ||
78 | pub substitution: Substitution, | ||
79 | } | ||
80 | |||
81 | impl TypeWalk for OpaqueTy { | ||
82 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
83 | self.substitution.walk(f); | ||
84 | } | ||
85 | |||
86 | fn walk_mut_binders( | ||
87 | &mut self, | ||
88 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
89 | binders: DebruijnIndex, | ||
90 | ) { | ||
91 | self.substitution.walk_mut_binders(f, binders); | ||
92 | } | ||
93 | } | ||
94 | |||
95 | /// A "projection" type corresponds to an (unnormalized) | ||
96 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
97 | /// trait and all its parameters are fully known. | ||
98 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
99 | pub struct ProjectionTy { | ||
100 | pub associated_ty_id: AssocTypeId, | ||
101 | pub substitution: Substitution, | ||
102 | } | ||
103 | |||
104 | impl ProjectionTy { | 73 | impl ProjectionTy { |
105 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { | 74 | pub fn trait_ref(&self, db: &dyn HirDatabase) -> TraitRef { |
106 | TraitRef { | 75 | TraitRef { |
@@ -110,7 +79,7 @@ impl ProjectionTy { | |||
110 | } | 79 | } |
111 | 80 | ||
112 | pub fn self_type_parameter(&self) -> &Ty { | 81 | pub fn self_type_parameter(&self) -> &Ty { |
113 | &self.substitution.interned(&Interner)[0].assert_ty_ref(&Interner) | 82 | &self.substitution.interned()[0].assert_ty_ref(&Interner) |
114 | } | 83 | } |
115 | 84 | ||
116 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { | 85 | fn trait_(&self, db: &dyn HirDatabase) -> TraitId { |
@@ -121,322 +90,11 @@ impl ProjectionTy { | |||
121 | } | 90 | } |
122 | } | 91 | } |
123 | 92 | ||
124 | impl TypeWalk for ProjectionTy { | ||
125 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
126 | self.substitution.walk(f); | ||
127 | } | ||
128 | |||
129 | fn walk_mut_binders( | ||
130 | &mut self, | ||
131 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
132 | binders: DebruijnIndex, | ||
133 | ) { | ||
134 | self.substitution.walk_mut_binders(f, binders); | ||
135 | } | ||
136 | } | ||
137 | |||
138 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
139 | pub struct DynTy { | ||
140 | /// The unknown self type. | ||
141 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
142 | } | ||
143 | |||
144 | pub type FnSig = chalk_ir::FnSig<Interner>; | 93 | pub type FnSig = chalk_ir::FnSig<Interner>; |
145 | 94 | ||
146 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
147 | pub struct FnPointer { | ||
148 | pub num_args: usize, | ||
149 | pub sig: FnSig, | ||
150 | pub substs: Substitution, | ||
151 | } | ||
152 | |||
153 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
154 | pub enum AliasTy { | ||
155 | /// A "projection" type corresponds to an (unnormalized) | ||
156 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
157 | /// trait and all its parameters are fully known. | ||
158 | Projection(ProjectionTy), | ||
159 | /// An opaque type (`impl Trait`). | ||
160 | /// | ||
161 | /// This is currently only used for return type impl trait; each instance of | ||
162 | /// `impl Trait` in a return type gets its own ID. | ||
163 | Opaque(OpaqueTy), | ||
164 | } | ||
165 | |||
166 | impl TypeWalk for AliasTy { | ||
167 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
168 | match self { | ||
169 | AliasTy::Projection(it) => it.walk(f), | ||
170 | AliasTy::Opaque(it) => it.walk(f), | ||
171 | } | ||
172 | } | ||
173 | |||
174 | fn walk_mut_binders( | ||
175 | &mut self, | ||
176 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
177 | binders: DebruijnIndex, | ||
178 | ) { | ||
179 | match self { | ||
180 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
181 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
182 | } | ||
183 | } | ||
184 | } | ||
185 | /// A type. | ||
186 | /// | ||
187 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
188 | /// the same thing (but in a different way). | ||
189 | /// | ||
190 | /// This should be cheap to clone. | ||
191 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
192 | pub enum TyKind { | ||
193 | /// Structures, enumerations and unions. | ||
194 | Adt(AdtId<Interner>, Substitution), | ||
195 | |||
196 | /// Represents an associated item like `Iterator::Item`. This is used | ||
197 | /// when we have tried to normalize a projection like `T::Item` but | ||
198 | /// couldn't find a better representation. In that case, we generate | ||
199 | /// an **application type** like `(Iterator::Item)<T>`. | ||
200 | AssociatedType(AssocTypeId, Substitution), | ||
201 | |||
202 | /// a scalar type like `bool` or `u32` | ||
203 | Scalar(Scalar), | ||
204 | |||
205 | /// A tuple type. For example, `(i32, bool)`. | ||
206 | Tuple(usize, Substitution), | ||
207 | |||
208 | /// An array with the given length. Written as `[T; n]`. | ||
209 | Array(Ty), | ||
210 | |||
211 | /// The pointee of an array slice. Written as `[T]`. | ||
212 | Slice(Ty), | ||
213 | |||
214 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
215 | Raw(Mutability, Ty), | ||
216 | |||
217 | /// A reference; a pointer with an associated lifetime. Written as | ||
218 | /// `&'a mut T` or `&'a T`. | ||
219 | Ref(Mutability, Ty), | ||
220 | |||
221 | /// This represents a placeholder for an opaque type in situations where we | ||
222 | /// don't know the hidden type (i.e. currently almost always). This is | ||
223 | /// analogous to the `AssociatedType` type constructor. | ||
224 | /// It is also used as the type of async block, with one type parameter | ||
225 | /// representing the Future::Output type. | ||
226 | OpaqueType(OpaqueTyId, Substitution), | ||
227 | |||
228 | /// The anonymous type of a function declaration/definition. Each | ||
229 | /// function has a unique type, which is output (for a function | ||
230 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
231 | /// | ||
232 | /// This includes tuple struct / enum variant constructors as well. | ||
233 | /// | ||
234 | /// For example the type of `bar` here: | ||
235 | /// | ||
236 | /// ``` | ||
237 | /// fn foo() -> i32 { 1 } | ||
238 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
239 | /// ``` | ||
240 | FnDef(FnDefId, Substitution), | ||
241 | |||
242 | /// The pointee of a string slice. Written as `str`. | ||
243 | Str, | ||
244 | |||
245 | /// The never type `!`. | ||
246 | Never, | ||
247 | |||
248 | /// The type of a specific closure. | ||
249 | /// | ||
250 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
251 | /// parameter. | ||
252 | Closure(ClosureId, Substitution), | ||
253 | |||
254 | /// Represents a foreign type declared in external blocks. | ||
255 | ForeignType(ForeignDefId), | ||
256 | |||
257 | /// A pointer to a function. Written as `fn() -> i32`. | ||
258 | /// | ||
259 | /// For example the type of `bar` here: | ||
260 | /// | ||
261 | /// ``` | ||
262 | /// fn foo() -> i32 { 1 } | ||
263 | /// let bar: fn() -> i32 = foo; | ||
264 | /// ``` | ||
265 | Function(FnPointer), | ||
266 | |||
267 | /// An "alias" type represents some form of type alias, such as: | ||
268 | /// - An associated type projection like `<T as Iterator>::Item` | ||
269 | /// - `impl Trait` types | ||
270 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
271 | Alias(AliasTy), | ||
272 | |||
273 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
274 | /// {}` when we're type-checking the body of that function. In this | ||
275 | /// situation, we know this stands for *some* type, but don't know the exact | ||
276 | /// type. | ||
277 | Placeholder(PlaceholderIndex), | ||
278 | |||
279 | /// A bound type variable. This is used in various places: when representing | ||
280 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
281 | /// parameters get turned into variables; during trait resolution, inference | ||
282 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
283 | /// `Self` type is represented with a bound variable as well. | ||
284 | BoundVar(BoundVar), | ||
285 | |||
286 | /// A type variable used during type checking. | ||
287 | InferenceVar(InferenceVar, TyVariableKind), | ||
288 | |||
289 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
290 | /// | ||
291 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
292 | /// represents the `Self` type inside the bounds. This is currently | ||
293 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
294 | /// didn't seem worth the overhead yet. | ||
295 | Dyn(DynTy), | ||
296 | |||
297 | /// A placeholder for a type which could not be computed; this is propagated | ||
298 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
299 | /// variables are inserted before type checking, since we want to try to | ||
300 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
301 | /// to infer as much as possible even in the presence of type errors. | ||
302 | Unknown, | ||
303 | } | ||
304 | |||
305 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
306 | pub struct Ty(Arc<TyKind>); | ||
307 | |||
308 | impl TyKind { | ||
309 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
310 | Ty(Arc::new(self)) | ||
311 | } | ||
312 | } | ||
313 | |||
314 | impl Ty { | ||
315 | pub fn kind(&self, _interner: &Interner) -> &TyKind { | ||
316 | &self.0 | ||
317 | } | ||
318 | |||
319 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
320 | Arc::make_mut(&mut self.0) | ||
321 | } | ||
322 | |||
323 | pub fn into_inner(self) -> TyKind { | ||
324 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
325 | } | ||
326 | } | ||
327 | |||
328 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
329 | pub struct GenericArg { | ||
330 | interned: GenericArgData, | ||
331 | } | ||
332 | |||
333 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
334 | pub enum GenericArgData { | ||
335 | Ty(Ty), | ||
336 | } | ||
337 | |||
338 | impl GenericArg { | ||
339 | /// Constructs a generic argument using `GenericArgData`. | ||
340 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
341 | GenericArg { interned: data } | ||
342 | } | ||
343 | |||
344 | /// Gets the interned value. | ||
345 | pub fn interned(&self) -> &GenericArgData { | ||
346 | &self.interned | ||
347 | } | ||
348 | |||
349 | /// Asserts that this is a type argument. | ||
350 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
351 | self.ty(interner).unwrap() | ||
352 | } | ||
353 | |||
354 | /// Checks whether the generic argument is a type. | ||
355 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
356 | match self.interned() { | ||
357 | GenericArgData::Ty(_) => true, | ||
358 | } | ||
359 | } | ||
360 | |||
361 | /// Returns the type if it is one, `None` otherwise. | ||
362 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
363 | match self.interned() { | ||
364 | GenericArgData::Ty(t) => Some(t), | ||
365 | } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | impl TypeWalk for GenericArg { | ||
370 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
371 | match &self.interned { | ||
372 | GenericArgData::Ty(ty) => { | ||
373 | ty.walk(f); | ||
374 | } | ||
375 | } | ||
376 | } | ||
377 | |||
378 | fn walk_mut_binders( | ||
379 | &mut self, | ||
380 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
381 | binders: DebruijnIndex, | ||
382 | ) { | ||
383 | match &mut self.interned { | ||
384 | GenericArgData::Ty(ty) => { | ||
385 | ty.walk_mut_binders(f, binders); | ||
386 | } | ||
387 | } | ||
388 | } | ||
389 | } | ||
390 | |||
391 | /// A list of substitutions for generic parameters. | ||
392 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
393 | pub struct Substitution(SmallVec<[GenericArg; 2]>); | ||
394 | |||
395 | impl TypeWalk for Substitution { | ||
396 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
397 | for t in self.0.iter() { | ||
398 | t.walk(f); | ||
399 | } | ||
400 | } | ||
401 | |||
402 | fn walk_mut_binders( | ||
403 | &mut self, | ||
404 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
405 | binders: DebruijnIndex, | ||
406 | ) { | ||
407 | for t in &mut self.0 { | ||
408 | t.walk_mut_binders(f, binders); | ||
409 | } | ||
410 | } | ||
411 | } | ||
412 | |||
413 | impl Substitution { | 95 | impl Substitution { |
414 | pub fn interned(&self, _: &Interner) -> &[GenericArg] { | ||
415 | &self.0 | ||
416 | } | ||
417 | |||
418 | pub fn len(&self, _: &Interner) -> usize { | ||
419 | self.0.len() | ||
420 | } | ||
421 | |||
422 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
423 | self.0.is_empty() | ||
424 | } | ||
425 | |||
426 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
427 | &self.0[i] | ||
428 | } | ||
429 | |||
430 | pub fn empty(_: &Interner) -> Substitution { | ||
431 | Substitution(SmallVec::new()) | ||
432 | } | ||
433 | |||
434 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
435 | self.0.iter() | ||
436 | } | ||
437 | |||
438 | pub fn single(ty: Ty) -> Substitution { | 96 | pub fn single(ty: Ty) -> Substitution { |
439 | Substitution({ | 97 | Substitution::intern({ |
440 | let mut v = SmallVec::new(); | 98 | let mut v = SmallVec::new(); |
441 | v.push(ty.cast(&Interner)); | 99 | v.push(ty.cast(&Interner)); |
442 | v | 100 | v |
@@ -444,64 +102,14 @@ impl Substitution { | |||
444 | } | 102 | } |
445 | 103 | ||
446 | pub fn prefix(&self, n: usize) -> Substitution { | 104 | pub fn prefix(&self, n: usize) -> Substitution { |
447 | Substitution(self.0[..std::cmp::min(self.0.len(), n)].into()) | 105 | Substitution::intern(self.interned()[..std::cmp::min(self.len(&Interner), n)].into()) |
448 | } | 106 | } |
449 | 107 | ||
450 | pub fn suffix(&self, n: usize) -> Substitution { | 108 | pub fn suffix(&self, n: usize) -> Substitution { |
451 | Substitution(self.0[self.0.len() - std::cmp::min(self.0.len(), n)..].into()) | 109 | Substitution::intern( |
452 | } | 110 | self.interned()[self.len(&Interner) - std::cmp::min(self.len(&Interner), n)..].into(), |
453 | |||
454 | pub fn from_iter( | ||
455 | interner: &Interner, | ||
456 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, | ||
457 | ) -> Self { | ||
458 | Substitution(elements.into_iter().casted(interner).collect()) | ||
459 | } | ||
460 | |||
461 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
462 | pub(crate) fn type_params_for_generics( | ||
463 | db: &dyn HirDatabase, | ||
464 | generic_params: &Generics, | ||
465 | ) -> Substitution { | ||
466 | Substitution::from_iter( | ||
467 | &Interner, | ||
468 | generic_params | ||
469 | .iter() | ||
470 | .map(|(id, _)| TyKind::Placeholder(to_placeholder_idx(db, id)).intern(&Interner)), | ||
471 | ) | ||
472 | } | ||
473 | |||
474 | /// Return Substs that replace each parameter by itself (i.e. `Ty::Param`). | ||
475 | pub fn type_params(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution { | ||
476 | let params = generics(db.upcast(), def.into()); | ||
477 | Substitution::type_params_for_generics(db, ¶ms) | ||
478 | } | ||
479 | |||
480 | /// Return Substs that replace each parameter by a bound variable. | ||
481 | pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution { | ||
482 | Substitution::from_iter( | ||
483 | &Interner, | ||
484 | generic_params | ||
485 | .iter() | ||
486 | .enumerate() | ||
487 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
488 | ) | 111 | ) |
489 | } | 112 | } |
490 | |||
491 | pub fn build_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> SubstsBuilder { | ||
492 | let def = def.into(); | ||
493 | let params = generics(db.upcast(), def); | ||
494 | let param_count = params.len(); | ||
495 | Substitution::builder(param_count) | ||
496 | } | ||
497 | |||
498 | pub(crate) fn build_for_generics(generic_params: &Generics) -> SubstsBuilder { | ||
499 | Substitution::builder(generic_params.len()) | ||
500 | } | ||
501 | |||
502 | fn builder(param_count: usize) -> SubstsBuilder { | ||
503 | SubstsBuilder { vec: Vec::with_capacity(param_count), param_count } | ||
504 | } | ||
505 | } | 113 | } |
506 | 114 | ||
507 | /// Return an index of a parameter in the generic type parameter list by it's id. | 115 | /// Return an index of a parameter in the generic type parameter list by it's id. |
@@ -509,58 +117,6 @@ pub fn param_idx(db: &dyn HirDatabase, id: TypeParamId) -> Option<usize> { | |||
509 | generics(db.upcast(), id.parent).param_idx(id) | 117 | generics(db.upcast(), id.parent).param_idx(id) |
510 | } | 118 | } |
511 | 119 | ||
512 | #[derive(Debug, Clone)] | ||
513 | pub struct SubstsBuilder { | ||
514 | vec: Vec<GenericArg>, | ||
515 | param_count: usize, | ||
516 | } | ||
517 | |||
518 | impl SubstsBuilder { | ||
519 | pub fn build(self) -> Substitution { | ||
520 | assert_eq!(self.vec.len(), self.param_count); | ||
521 | Substitution::from_iter(&Interner, self.vec) | ||
522 | } | ||
523 | |||
524 | pub fn push(mut self, ty: impl CastTo<GenericArg>) -> Self { | ||
525 | self.vec.push(ty.cast(&Interner)); | ||
526 | self | ||
527 | } | ||
528 | |||
529 | fn remaining(&self) -> usize { | ||
530 | self.param_count - self.vec.len() | ||
531 | } | ||
532 | |||
533 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { | ||
534 | self.fill( | ||
535 | (starting_from..) | ||
536 | .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
537 | ) | ||
538 | } | ||
539 | |||
540 | pub fn fill_with_unknown(self) -> Self { | ||
541 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
542 | } | ||
543 | |||
544 | pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self { | ||
545 | self.vec.extend(filler.take(self.remaining()).casted(&Interner)); | ||
546 | assert_eq!(self.remaining(), 0); | ||
547 | self | ||
548 | } | ||
549 | |||
550 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { | ||
551 | assert!(self.vec.is_empty()); | ||
552 | assert!(parent_substs.len(&Interner) <= self.param_count); | ||
553 | self.vec.extend(parent_substs.iter(&Interner).cloned()); | ||
554 | self | ||
555 | } | ||
556 | } | ||
557 | |||
558 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
559 | pub struct Binders<T> { | ||
560 | pub num_binders: usize, | ||
561 | pub value: T, | ||
562 | } | ||
563 | |||
564 | impl<T> Binders<T> { | 120 | impl<T> Binders<T> { |
565 | pub fn new(num_binders: usize, value: T) -> Self { | 121 | pub fn new(num_binders: usize, value: T) -> Self { |
566 | Self { num_binders, value } | 122 | Self { num_binders, value } |
@@ -608,27 +164,6 @@ impl<T: TypeWalk> Binders<T> { | |||
608 | } | 164 | } |
609 | } | 165 | } |
610 | 166 | ||
611 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
612 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
613 | self.value.walk(f); | ||
614 | } | ||
615 | |||
616 | fn walk_mut_binders( | ||
617 | &mut self, | ||
618 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
619 | binders: DebruijnIndex, | ||
620 | ) { | ||
621 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
622 | } | ||
623 | } | ||
624 | |||
625 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
626 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
627 | pub struct TraitRef { | ||
628 | pub trait_id: ChalkTraitId, | ||
629 | pub substitution: Substitution, | ||
630 | } | ||
631 | |||
632 | impl TraitRef { | 167 | impl TraitRef { |
633 | pub fn self_type_parameter(&self) -> &Ty { | 168 | pub fn self_type_parameter(&self) -> &Ty { |
634 | &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) | 169 | &self.substitution.at(&Interner, 0).assert_ty_ref(&Interner) |
@@ -639,30 +174,6 @@ impl TraitRef { | |||
639 | } | 174 | } |
640 | } | 175 | } |
641 | 176 | ||
642 | impl TypeWalk for TraitRef { | ||
643 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
644 | self.substitution.walk(f); | ||
645 | } | ||
646 | |||
647 | fn walk_mut_binders( | ||
648 | &mut self, | ||
649 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
650 | binders: DebruijnIndex, | ||
651 | ) { | ||
652 | self.substitution.walk_mut_binders(f, binders); | ||
653 | } | ||
654 | } | ||
655 | |||
656 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
657 | /// parameters of a generic item. | ||
658 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
659 | pub enum WhereClause { | ||
660 | /// The given trait needs to be implemented for its type parameters. | ||
661 | Implemented(TraitRef), | ||
662 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
663 | AliasEq(AliasEq), | ||
664 | } | ||
665 | |||
666 | impl WhereClause { | 177 | impl WhereClause { |
667 | pub fn is_implemented(&self) -> bool { | 178 | pub fn is_implemented(&self) -> bool { |
668 | matches!(self, WhereClause::Implemented(_)) | 179 | matches!(self, WhereClause::Implemented(_)) |
@@ -679,56 +190,6 @@ impl WhereClause { | |||
679 | } | 190 | } |
680 | } | 191 | } |
681 | 192 | ||
682 | impl TypeWalk for WhereClause { | ||
683 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
684 | match self { | ||
685 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
686 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
687 | } | ||
688 | } | ||
689 | |||
690 | fn walk_mut_binders( | ||
691 | &mut self, | ||
692 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
693 | binders: DebruijnIndex, | ||
694 | ) { | ||
695 | match self { | ||
696 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
697 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
698 | } | ||
699 | } | ||
700 | } | ||
701 | |||
702 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
703 | |||
704 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
705 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
706 | |||
707 | impl QuantifiedWhereClauses { | ||
708 | pub fn from_iter( | ||
709 | _interner: &Interner, | ||
710 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
711 | ) -> Self { | ||
712 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
713 | } | ||
714 | |||
715 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
716 | &self.0 | ||
717 | } | ||
718 | } | ||
719 | |||
720 | /// Basically a claim (currently not validated / checked) that the contained | ||
721 | /// type / trait ref contains no inference variables; any inference variables it | ||
722 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
723 | /// many there are and whether they were normal or float/int variables. This is | ||
724 | /// used to erase irrelevant differences between types before using them in | ||
725 | /// queries. | ||
726 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
727 | pub struct Canonical<T> { | ||
728 | pub value: T, | ||
729 | pub binders: CanonicalVarKinds, | ||
730 | } | ||
731 | |||
732 | impl<T> Canonical<T> { | 193 | impl<T> Canonical<T> { |
733 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { | 194 | pub fn new(value: T, kinds: impl IntoIterator<Item = TyVariableKind>) -> Self { |
734 | let kinds = kinds.into_iter().map(|tk| { | 195 | let kinds = kinds.into_iter().map(|tk| { |
@@ -760,12 +221,12 @@ impl CallableSig { | |||
760 | 221 | ||
761 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { | 222 | pub fn from_fn_ptr(fn_ptr: &FnPointer) -> CallableSig { |
762 | CallableSig { | 223 | CallableSig { |
763 | // FIXME: what to do about lifetime params? | 224 | // FIXME: what to do about lifetime params? -> return PolyFnSig |
764 | params_and_return: fn_ptr | 225 | params_and_return: fn_ptr |
765 | .substs | 226 | .substs |
766 | .clone() | 227 | .clone() |
767 | .shift_bound_vars_out(DebruijnIndex::ONE) | 228 | .shift_bound_vars_out(DebruijnIndex::ONE) |
768 | .interned(&Interner) | 229 | .interned() |
769 | .iter() | 230 | .iter() |
770 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) | 231 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) |
771 | .collect(), | 232 | .collect(), |
@@ -773,16 +234,6 @@ impl CallableSig { | |||
773 | } | 234 | } |
774 | } | 235 | } |
775 | 236 | ||
776 | pub fn from_substs(substs: &Substitution) -> CallableSig { | ||
777 | CallableSig { | ||
778 | params_and_return: substs | ||
779 | .iter(&Interner) | ||
780 | .map(|arg| arg.assert_ty_ref(&Interner).clone()) | ||
781 | .collect(), | ||
782 | is_varargs: false, | ||
783 | } | ||
784 | } | ||
785 | |||
786 | pub fn params(&self) -> &[Ty] { | 237 | pub fn params(&self) -> &[Ty] { |
787 | &self.params_and_return[0..self.params_and_return.len() - 1] | 238 | &self.params_and_return[0..self.params_and_return.len() - 1] |
788 | } | 239 | } |
@@ -792,59 +243,7 @@ impl CallableSig { | |||
792 | } | 243 | } |
793 | } | 244 | } |
794 | 245 | ||
795 | impl TypeWalk for CallableSig { | ||
796 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
797 | for t in self.params_and_return.iter() { | ||
798 | t.walk(f); | ||
799 | } | ||
800 | } | ||
801 | |||
802 | fn walk_mut_binders( | ||
803 | &mut self, | ||
804 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
805 | binders: DebruijnIndex, | ||
806 | ) { | ||
807 | for t in make_mut_slice(&mut self.params_and_return) { | ||
808 | t.walk_mut_binders(f, binders); | ||
809 | } | ||
810 | } | ||
811 | } | ||
812 | |||
813 | impl Ty { | 246 | impl Ty { |
814 | pub fn unit() -> Self { | ||
815 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) | ||
816 | } | ||
817 | |||
818 | pub fn adt_ty(adt: hir_def::AdtId, substs: Substitution) -> Ty { | ||
819 | TyKind::Adt(AdtId(adt), substs).intern(&Interner) | ||
820 | } | ||
821 | |||
822 | pub fn fn_ptr(sig: CallableSig) -> Self { | ||
823 | TyKind::Function(FnPointer { | ||
824 | num_args: sig.params().len(), | ||
825 | sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, | ||
826 | substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), | ||
827 | }) | ||
828 | .intern(&Interner) | ||
829 | } | ||
830 | |||
831 | pub fn builtin(builtin: BuiltinType) -> Self { | ||
832 | match builtin { | ||
833 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), | ||
834 | BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), | ||
835 | BuiltinType::Str => TyKind::Str.intern(&Interner), | ||
836 | BuiltinType::Int(t) => { | ||
837 | TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) | ||
838 | } | ||
839 | BuiltinType::Uint(t) => { | ||
840 | TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) | ||
841 | } | ||
842 | BuiltinType::Float(t) => { | ||
843 | TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) | ||
844 | } | ||
845 | } | ||
846 | } | ||
847 | |||
848 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { | 247 | pub fn as_reference(&self) -> Option<(&Ty, Mutability)> { |
849 | match self.kind(&Interner) { | 248 | match self.kind(&Interner) { |
850 | TyKind::Ref(mutability, ty) => Some((ty, *mutability)), | 249 | TyKind::Ref(mutability, ty) => Some((ty, *mutability)), |
@@ -1068,7 +467,7 @@ impl Ty { | |||
1068 | let param_data = &generic_params.types[id.local_id]; | 467 | let param_data = &generic_params.types[id.local_id]; |
1069 | match param_data.provenance { | 468 | match param_data.provenance { |
1070 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { | 469 | hir_def::generics::TypeParamProvenance::ArgumentImplTrait => { |
1071 | let substs = Substitution::type_params(db, id.parent); | 470 | let substs = TyBuilder::type_params_subst(db, id.parent); |
1072 | let predicates = db | 471 | let predicates = db |
1073 | .generic_predicates(id.parent) | 472 | .generic_predicates(id.parent) |
1074 | .into_iter() | 473 | .into_iter() |
@@ -1114,200 +513,6 @@ impl Ty { | |||
1114 | } | 513 | } |
1115 | } | 514 | } |
1116 | 515 | ||
1117 | /// This allows walking structures that contain types to do something with those | ||
1118 | /// types, similar to Chalk's `Fold` trait. | ||
1119 | pub trait TypeWalk { | ||
1120 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
1121 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
1122 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
1123 | } | ||
1124 | /// Walk the type, counting entered binders. | ||
1125 | /// | ||
1126 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
1127 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
1128 | /// substitute a certain bound variable, we can't just walk the whole type | ||
1129 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
1130 | /// things that introduce new bound variables, we have to keep track of | ||
1131 | /// that. Currently, the only thing that introduces bound variables on our | ||
1132 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
1133 | /// variable for the self type. | ||
1134 | fn walk_mut_binders( | ||
1135 | &mut self, | ||
1136 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1137 | binders: DebruijnIndex, | ||
1138 | ); | ||
1139 | |||
1140 | fn fold_binders( | ||
1141 | mut self, | ||
1142 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
1143 | binders: DebruijnIndex, | ||
1144 | ) -> Self | ||
1145 | where | ||
1146 | Self: Sized, | ||
1147 | { | ||
1148 | self.walk_mut_binders( | ||
1149 | &mut |ty_mut, binders| { | ||
1150 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1151 | *ty_mut = f(ty, binders); | ||
1152 | }, | ||
1153 | binders, | ||
1154 | ); | ||
1155 | self | ||
1156 | } | ||
1157 | |||
1158 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
1159 | where | ||
1160 | Self: Sized, | ||
1161 | { | ||
1162 | self.walk_mut(&mut |ty_mut| { | ||
1163 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
1164 | *ty_mut = f(ty); | ||
1165 | }); | ||
1166 | self | ||
1167 | } | ||
1168 | |||
1169 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1170 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
1171 | where | ||
1172 | Self: Sized, | ||
1173 | { | ||
1174 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
1175 | } | ||
1176 | |||
1177 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
1178 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
1179 | where | ||
1180 | Self: Sized, | ||
1181 | { | ||
1182 | self.walk_mut_binders( | ||
1183 | &mut |ty, binders| { | ||
1184 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
1185 | if bound.debruijn >= binders { | ||
1186 | *ty = substs.0[bound.index] | ||
1187 | .assert_ty_ref(&Interner) | ||
1188 | .clone() | ||
1189 | .shift_bound_vars(binders); | ||
1190 | } | ||
1191 | } | ||
1192 | }, | ||
1193 | depth, | ||
1194 | ); | ||
1195 | self | ||
1196 | } | ||
1197 | |||
1198 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
1199 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
1200 | where | ||
1201 | Self: Sized, | ||
1202 | { | ||
1203 | self.fold_binders( | ||
1204 | &mut |ty, binders| match ty.kind(&Interner) { | ||
1205 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1206 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
1207 | } | ||
1208 | _ => ty, | ||
1209 | }, | ||
1210 | DebruijnIndex::INNERMOST, | ||
1211 | ) | ||
1212 | } | ||
1213 | |||
1214 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
1215 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
1216 | where | ||
1217 | Self: Sized + std::fmt::Debug, | ||
1218 | { | ||
1219 | self.fold_binders( | ||
1220 | &mut |ty, binders| match ty.kind(&Interner) { | ||
1221 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
1222 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
1223 | .intern(&Interner) | ||
1224 | } | ||
1225 | _ => ty, | ||
1226 | }, | ||
1227 | DebruijnIndex::INNERMOST, | ||
1228 | ) | ||
1229 | } | ||
1230 | } | ||
1231 | |||
1232 | impl TypeWalk for Ty { | ||
1233 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1234 | match self.kind(&Interner) { | ||
1235 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1236 | for t in p_ty.substitution.iter(&Interner) { | ||
1237 | t.walk(f); | ||
1238 | } | ||
1239 | } | ||
1240 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1241 | for t in o_ty.substitution.iter(&Interner) { | ||
1242 | t.walk(f); | ||
1243 | } | ||
1244 | } | ||
1245 | TyKind::Dyn(dyn_ty) => { | ||
1246 | for p in dyn_ty.bounds.value.interned().iter() { | ||
1247 | p.walk(f); | ||
1248 | } | ||
1249 | } | ||
1250 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1251 | ty.walk(f); | ||
1252 | } | ||
1253 | _ => { | ||
1254 | if let Some(substs) = self.substs() { | ||
1255 | for t in substs.iter(&Interner) { | ||
1256 | t.walk(f); | ||
1257 | } | ||
1258 | } | ||
1259 | } | ||
1260 | } | ||
1261 | f(self); | ||
1262 | } | ||
1263 | |||
1264 | fn walk_mut_binders( | ||
1265 | &mut self, | ||
1266 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1267 | binders: DebruijnIndex, | ||
1268 | ) { | ||
1269 | match self.interned_mut() { | ||
1270 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
1271 | p_ty.substitution.walk_mut_binders(f, binders); | ||
1272 | } | ||
1273 | TyKind::Dyn(dyn_ty) => { | ||
1274 | for p in make_mut_slice(&mut dyn_ty.bounds.value.0) { | ||
1275 | p.walk_mut_binders(f, binders.shifted_in()); | ||
1276 | } | ||
1277 | } | ||
1278 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
1279 | o_ty.substitution.walk_mut_binders(f, binders); | ||
1280 | } | ||
1281 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
1282 | ty.walk_mut_binders(f, binders); | ||
1283 | } | ||
1284 | _ => { | ||
1285 | if let Some(substs) = self.substs_mut() { | ||
1286 | substs.walk_mut_binders(f, binders); | ||
1287 | } | ||
1288 | } | ||
1289 | } | ||
1290 | f(self, binders); | ||
1291 | } | ||
1292 | } | ||
1293 | |||
1294 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
1295 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
1296 | for t in self { | ||
1297 | t.walk(f); | ||
1298 | } | ||
1299 | } | ||
1300 | fn walk_mut_binders( | ||
1301 | &mut self, | ||
1302 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
1303 | binders: DebruijnIndex, | ||
1304 | ) { | ||
1305 | for t in self { | ||
1306 | t.walk_mut_binders(f, binders); | ||
1307 | } | ||
1308 | } | ||
1309 | } | ||
1310 | |||
1311 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | 516 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] |
1312 | pub enum ImplTraitId { | 517 | pub enum ImplTraitId { |
1313 | ReturnTypeImplTrait(hir_def::FunctionId, u16), | 518 | ReturnTypeImplTrait(hir_def::FunctionId, u16), |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index f595683e5..214655807 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -36,7 +36,7 @@ use crate::{ | |||
36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, | 36 | AliasEq, AliasTy, Binders, BoundVar, CallableSig, DebruijnIndex, DynTy, FnPointer, FnSig, |
37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, | 37 | ImplTraitId, OpaqueTy, PolyFnSig, ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, |
38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, | 38 | ReturnTypeImplTrait, ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, Ty, |
39 | TyKind, TypeWalk, WhereClause, | 39 | TyBuilder, TyKind, TypeWalk, WhereClause, |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #[derive(Debug)] | 42 | #[derive(Debug)] |
@@ -234,7 +234,7 @@ impl<'a> TyLoweringContext<'a> { | |||
234 | let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx); | 234 | let impl_trait_id = ImplTraitId::ReturnTypeImplTrait(func, idx); |
235 | let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); | 235 | let opaque_ty_id = self.db.intern_impl_trait_id(impl_trait_id).into(); |
236 | let generics = generics(self.db.upcast(), func.into()); | 236 | let generics = generics(self.db.upcast(), func.into()); |
237 | let parameters = Substitution::bound_vars(&generics, self.in_binders); | 237 | let parameters = generics.bound_vars_subst(self.in_binders); |
238 | TyKind::Alias(AliasTy::Opaque(OpaqueTy { | 238 | TyKind::Alias(AliasTy::Opaque(OpaqueTy { |
239 | opaque_ty_id, | 239 | opaque_ty_id, |
240 | substitution: parameters, | 240 | substitution: parameters, |
@@ -411,24 +411,16 @@ impl<'a> TyLoweringContext<'a> { | |||
411 | TypeNs::SelfType(impl_id) => { | 411 | TypeNs::SelfType(impl_id) => { |
412 | let generics = generics(self.db.upcast(), impl_id.into()); | 412 | let generics = generics(self.db.upcast(), impl_id.into()); |
413 | let substs = match self.type_param_mode { | 413 | let substs = match self.type_param_mode { |
414 | TypeParamLoweringMode::Placeholder => { | 414 | TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), |
415 | Substitution::type_params_for_generics(self.db, &generics) | 415 | TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), |
416 | } | ||
417 | TypeParamLoweringMode::Variable => { | ||
418 | Substitution::bound_vars(&generics, self.in_binders) | ||
419 | } | ||
420 | }; | 416 | }; |
421 | self.db.impl_self_ty(impl_id).subst(&substs) | 417 | self.db.impl_self_ty(impl_id).subst(&substs) |
422 | } | 418 | } |
423 | TypeNs::AdtSelfType(adt) => { | 419 | TypeNs::AdtSelfType(adt) => { |
424 | let generics = generics(self.db.upcast(), adt.into()); | 420 | let generics = generics(self.db.upcast(), adt.into()); |
425 | let substs = match self.type_param_mode { | 421 | let substs = match self.type_param_mode { |
426 | TypeParamLoweringMode::Placeholder => { | 422 | TypeParamLoweringMode::Placeholder => generics.type_params_subst(self.db), |
427 | Substitution::type_params_for_generics(self.db, &generics) | 423 | TypeParamLoweringMode::Variable => generics.bound_vars_subst(self.in_binders), |
428 | } | ||
429 | TypeParamLoweringMode::Variable => { | ||
430 | Substitution::bound_vars(&generics, self.in_binders) | ||
431 | } | ||
432 | }; | 424 | }; |
433 | self.db.ty(adt.into()).subst(&substs) | 425 | self.db.ty(adt.into()).subst(&substs) |
434 | } | 426 | } |
@@ -478,12 +470,13 @@ impl<'a> TyLoweringContext<'a> { | |||
478 | TypeParamLoweringMode::Placeholder => { | 470 | TypeParamLoweringMode::Placeholder => { |
479 | // if we're lowering to placeholders, we have to put | 471 | // if we're lowering to placeholders, we have to put |
480 | // them in now | 472 | // them in now |
481 | let s = Substitution::type_params( | 473 | let generics = generics( |
482 | self.db, | 474 | self.db.upcast(), |
483 | self.resolver.generic_def().expect( | 475 | self.resolver.generic_def().expect( |
484 | "there should be generics if there's a generic param", | 476 | "there should be generics if there's a generic param", |
485 | ), | 477 | ), |
486 | ); | 478 | ); |
479 | let s = generics.type_params_subst(self.db); | ||
487 | t.substitution.clone().subst_bound_vars(&s) | 480 | t.substitution.clone().subst_bound_vars(&s) |
488 | } | 481 | } |
489 | TypeParamLoweringMode::Variable => t.substitution.clone(), | 482 | TypeParamLoweringMode::Variable => t.substitution.clone(), |
@@ -860,10 +853,9 @@ pub fn associated_type_shorthand_candidates<R>( | |||
860 | if generics.params.types[param_id.local_id].provenance | 853 | if generics.params.types[param_id.local_id].provenance |
861 | == TypeParamProvenance::TraitSelf | 854 | == TypeParamProvenance::TraitSelf |
862 | { | 855 | { |
863 | let trait_ref = TraitRef { | 856 | let trait_ref = TyBuilder::trait_ref(db, trait_id) |
864 | trait_id: to_chalk_trait_id(trait_id), | 857 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, 0) |
865 | substitution: Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST), | 858 | .build(); |
866 | }; | ||
867 | return search(trait_ref); | 859 | return search(trait_ref); |
868 | } | 860 | } |
869 | } | 861 | } |
@@ -972,7 +964,7 @@ pub(crate) fn trait_environment_query( | |||
972 | // function default implementations (and hypothetical code | 964 | // function default implementations (and hypothetical code |
973 | // inside consts or type aliases) | 965 | // inside consts or type aliases) |
974 | cov_mark::hit!(trait_self_implements_self); | 966 | cov_mark::hit!(trait_self_implements_self); |
975 | let substs = Substitution::type_params(db, trait_id); | 967 | let substs = TyBuilder::type_params_subst(db, trait_id); |
976 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; | 968 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution: substs }; |
977 | let pred = WhereClause::Implemented(trait_ref); | 969 | let pred = WhereClause::Implemented(trait_ref); |
978 | let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); | 970 | let program_clause: chalk_ir::ProgramClause<Interner> = pred.to_chalk(db).cast(&Interner); |
@@ -1054,14 +1046,14 @@ fn fn_sig_for_fn(db: &dyn HirDatabase, def: FunctionId) -> PolyFnSig { | |||
1054 | let ret = (&ctx_ret).lower_ty(&data.ret_type); | 1046 | let ret = (&ctx_ret).lower_ty(&data.ret_type); |
1055 | let generics = generics(db.upcast(), def.into()); | 1047 | let generics = generics(db.upcast(), def.into()); |
1056 | let num_binders = generics.len(); | 1048 | let num_binders = generics.len(); |
1057 | Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs)) | 1049 | Binders::new(num_binders, CallableSig::from_params_and_return(params, ret, data.is_varargs())) |
1058 | } | 1050 | } |
1059 | 1051 | ||
1060 | /// Build the declared type of a function. This should not need to look at the | 1052 | /// Build the declared type of a function. This should not need to look at the |
1061 | /// function body. | 1053 | /// function body. |
1062 | fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { | 1054 | fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { |
1063 | let generics = generics(db.upcast(), def.into()); | 1055 | let generics = generics(db.upcast(), def.into()); |
1064 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1056 | let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); |
1065 | Binders::new( | 1057 | Binders::new( |
1066 | substs.len(&Interner), | 1058 | substs.len(&Interner), |
1067 | TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), | 1059 | TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), |
@@ -1106,7 +1098,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T | |||
1106 | return type_for_adt(db, def.into()); | 1098 | return type_for_adt(db, def.into()); |
1107 | } | 1099 | } |
1108 | let generics = generics(db.upcast(), def.into()); | 1100 | let generics = generics(db.upcast(), def.into()); |
1109 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1101 | let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); |
1110 | Binders::new( | 1102 | Binders::new( |
1111 | substs.len(&Interner), | 1103 | substs.len(&Interner), |
1112 | TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner), | 1104 | TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner), |
@@ -1133,7 +1125,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - | |||
1133 | return type_for_adt(db, def.parent.into()); | 1125 | return type_for_adt(db, def.parent.into()); |
1134 | } | 1126 | } |
1135 | let generics = generics(db.upcast(), def.parent.into()); | 1127 | let generics = generics(db.upcast(), def.parent.into()); |
1136 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1128 | let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST); |
1137 | Binders::new( | 1129 | Binders::new( |
1138 | substs.len(&Interner), | 1130 | substs.len(&Interner), |
1139 | TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner), | 1131 | TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner), |
@@ -1141,9 +1133,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) - | |||
1141 | } | 1133 | } |
1142 | 1134 | ||
1143 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { | 1135 | fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { |
1144 | let generics = generics(db.upcast(), adt.into()); | 1136 | let b = TyBuilder::adt(db, adt); |
1145 | let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); | 1137 | let num_binders = b.remaining(); |
1146 | Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) | 1138 | let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build(); |
1139 | Binders::new(num_binders, ty) | ||
1147 | } | 1140 | } |
1148 | 1141 | ||
1149 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { | 1142 | fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { |
@@ -1215,7 +1208,7 @@ impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for V | |||
1215 | /// namespace. | 1208 | /// namespace. |
1216 | pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> { | 1209 | pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> { |
1217 | match def { | 1210 | match def { |
1218 | TyDefId::BuiltinType(it) => Binders::new(0, Ty::builtin(it)), | 1211 | TyDefId::BuiltinType(it) => Binders::new(0, TyBuilder::builtin(it)), |
1219 | TyDefId::AdtId(it) => type_for_adt(db, it), | 1212 | TyDefId::AdtId(it) => type_for_adt(db, it), |
1220 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), | 1213 | TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), |
1221 | } | 1214 | } |
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs index 338851fa8..0e4a620b6 100644 --- a/crates/hir_ty/src/method_resolution.rs +++ b/crates/hir_ty/src/method_resolution.rs | |||
@@ -19,10 +19,9 @@ use crate::{ | |||
19 | db::HirDatabase, | 19 | db::HirDatabase, |
20 | from_foreign_def_id, | 20 | from_foreign_def_id, |
21 | primitive::{self, FloatTy, IntTy, UintTy}, | 21 | primitive::{self, FloatTy, IntTy, UintTy}, |
22 | to_chalk_trait_id, | ||
23 | utils::all_super_traits, | 22 | utils::all_super_traits, |
24 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, | 23 | AdtId, Canonical, CanonicalVarKinds, DebruijnIndex, FnPointer, FnSig, ForeignDefId, |
25 | InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, TraitRef, Ty, TyKind, | 24 | InEnvironment, Interner, Scalar, Substitution, TraitEnvironment, Ty, TyBuilder, TyKind, |
26 | TypeWalk, | 25 | TypeWalk, |
27 | }; | 26 | }; |
28 | 27 | ||
@@ -675,7 +674,7 @@ fn is_valid_candidate( | |||
675 | } | 674 | } |
676 | } | 675 | } |
677 | if let Some(receiver_ty) = receiver_ty { | 676 | if let Some(receiver_ty) = receiver_ty { |
678 | if !data.has_self_param { | 677 | if !data.has_self_param() { |
679 | return false; | 678 | return false; |
680 | } | 679 | } |
681 | let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { | 680 | let transformed_receiver_ty = match transform_receiver_ty(db, m, self_ty) { |
@@ -710,7 +709,7 @@ pub(crate) fn inherent_impl_substs( | |||
710 | ) -> Option<Substitution> { | 709 | ) -> Option<Substitution> { |
711 | // we create a var for each type parameter of the impl; we need to keep in | 710 | // we create a var for each type parameter of the impl; we need to keep in |
712 | // mind here that `self_ty` might have vars of its own | 711 | // mind here that `self_ty` might have vars of its own |
713 | let vars = Substitution::build_for_def(db, impl_id) | 712 | let vars = TyBuilder::subst_for_def(db, impl_id) |
714 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) | 713 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, self_ty.binders.len(&Interner)) |
715 | .build(); | 714 | .build(); |
716 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); | 715 | let self_ty_with_vars = db.impl_self_ty(impl_id).subst(&vars); |
@@ -761,13 +760,13 @@ fn transform_receiver_ty( | |||
761 | self_ty: &Canonical<Ty>, | 760 | self_ty: &Canonical<Ty>, |
762 | ) -> Option<Ty> { | 761 | ) -> Option<Ty> { |
763 | let substs = match function_id.lookup(db.upcast()).container { | 762 | let substs = match function_id.lookup(db.upcast()).container { |
764 | AssocContainerId::TraitId(_) => Substitution::build_for_def(db, function_id) | 763 | AssocContainerId::TraitId(_) => TyBuilder::subst_for_def(db, function_id) |
765 | .push(self_ty.value.clone()) | 764 | .push(self_ty.value.clone()) |
766 | .fill_with_unknown() | 765 | .fill_with_unknown() |
767 | .build(), | 766 | .build(), |
768 | AssocContainerId::ImplId(impl_id) => { | 767 | AssocContainerId::ImplId(impl_id) => { |
769 | let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; | 768 | let impl_substs = inherent_impl_substs(db, impl_id, &self_ty)?; |
770 | Substitution::build_for_def(db, function_id) | 769 | TyBuilder::subst_for_def(db, function_id) |
771 | .use_parent_substs(&impl_substs) | 770 | .use_parent_substs(&impl_substs) |
772 | .fill_with_unknown() | 771 | .fill_with_unknown() |
773 | .build() | 772 | .build() |
@@ -801,7 +800,7 @@ pub fn implements_trait_unique( | |||
801 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); | 800 | let goal = generic_implements_goal(db, env, trait_, ty.clone()); |
802 | let solution = db.trait_solve(krate, goal); | 801 | let solution = db.trait_solve(krate, goal); |
803 | 802 | ||
804 | matches!(solution, Some(crate::traits::Solution::Unique(_))) | 803 | matches!(solution, Some(crate::Solution::Unique(_))) |
805 | } | 804 | } |
806 | 805 | ||
807 | /// This creates Substs for a trait with the given Self type and type variables | 806 | /// This creates Substs for a trait with the given Self type and type variables |
@@ -813,7 +812,7 @@ fn generic_implements_goal( | |||
813 | self_ty: Canonical<Ty>, | 812 | self_ty: Canonical<Ty>, |
814 | ) -> Canonical<InEnvironment<super::DomainGoal>> { | 813 | ) -> Canonical<InEnvironment<super::DomainGoal>> { |
815 | let mut kinds = self_ty.binders.interned().to_vec(); | 814 | let mut kinds = self_ty.binders.interned().to_vec(); |
816 | let substs = super::Substitution::build_for_def(db, trait_) | 815 | let trait_ref = TyBuilder::trait_ref(db, trait_) |
817 | .push(self_ty.value) | 816 | .push(self_ty.value) |
818 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) | 817 | .fill_with_bound_vars(DebruijnIndex::INNERMOST, kinds.len()) |
819 | .build(); | 818 | .build(); |
@@ -822,9 +821,8 @@ fn generic_implements_goal( | |||
822 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), | 821 | chalk_ir::VariableKind::Ty(chalk_ir::TyVariableKind::General), |
823 | UniverseIndex::ROOT, | 822 | UniverseIndex::ROOT, |
824 | )) | 823 | )) |
825 | .take(substs.len(&Interner) - 1), | 824 | .take(trait_ref.substitution.len(&Interner) - 1), |
826 | ); | 825 | ); |
827 | let trait_ref = TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs }; | ||
828 | let obligation = trait_ref.cast(&Interner); | 826 | let obligation = trait_ref.cast(&Interner); |
829 | Canonical { | 827 | Canonical { |
830 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), | 828 | binders: CanonicalVarKinds::from_iter(&Interner, kinds), |
diff --git a/crates/hir_ty/src/op.rs b/crates/hir_ty/src/op.rs index 8533e1ed8..90dd31a35 100644 --- a/crates/hir_ty/src/op.rs +++ b/crates/hir_ty/src/op.rs | |||
@@ -2,12 +2,12 @@ | |||
2 | use chalk_ir::TyVariableKind; | 2 | use chalk_ir::TyVariableKind; |
3 | use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; | 3 | use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; |
4 | 4 | ||
5 | use crate::{Interner, Scalar, Ty, TyKind}; | 5 | use crate::{Interner, Scalar, Ty, TyBuilder, TyKind}; |
6 | 6 | ||
7 | pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { | 7 | pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { |
8 | match op { | 8 | match op { |
9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), | 9 | BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), |
10 | BinaryOp::Assignment { .. } => Ty::unit(), | 10 | BinaryOp::Assignment { .. } => TyBuilder::unit(), |
11 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { | 11 | BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { |
12 | match lhs_ty.kind(&Interner) { | 12 | match lhs_ty.kind(&Interner) { |
13 | TyKind::Scalar(Scalar::Int(_)) | 13 | TyKind::Scalar(Scalar::Int(_)) |
diff --git a/crates/hir_ty/src/tests.rs b/crates/hir_ty/src/tests.rs index ad283c1e0..ccfb88c52 100644 --- a/crates/hir_ty/src/tests.rs +++ b/crates/hir_ty/src/tests.rs | |||
@@ -288,7 +288,7 @@ fn visit_module( | |||
288 | } | 288 | } |
289 | 289 | ||
290 | fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) { | 290 | fn visit_body(db: &TestDB, body: &Body, cb: &mut dyn FnMut(DefWithBodyId)) { |
291 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 291 | for (_, def_map) in body.blocks(db) { |
292 | for (mod_id, _) in def_map.modules() { | 292 | for (mod_id, _) in def_map.modules() { |
293 | visit_module(db, &def_map, mod_id, cb); | 293 | visit_module(db, &def_map, mod_id, cb); |
294 | } | 294 | } |
diff --git a/crates/hir_ty/src/traits.rs b/crates/hir_ty/src/traits.rs index e5e8cff33..66d600bfc 100644 --- a/crates/hir_ty/src/traits.rs +++ b/crates/hir_ty/src/traits.rs | |||
@@ -8,8 +8,8 @@ use hir_def::{lang_item::LangItemTarget, TraitId}; | |||
8 | use stdx::panic_context; | 8 | use stdx::panic_context; |
9 | 9 | ||
10 | use crate::{ | 10 | use crate::{ |
11 | db::HirDatabase, AliasTy, Canonical, DebruijnIndex, HirDisplay, Substitution, Ty, TyKind, | 11 | db::HirDatabase, AliasEq, AliasTy, Canonical, DomainGoal, Guidance, HirDisplay, InEnvironment, |
12 | TypeWalk, WhereClause, | 12 | Solution, SolutionVariables, Ty, TyKind, WhereClause, |
13 | }; | 13 | }; |
14 | 14 | ||
15 | use self::chalk::{from_chalk, Interner, ToChalk}; | 15 | use self::chalk::{from_chalk, Interner, ToChalk}; |
@@ -70,55 +70,6 @@ impl Default for TraitEnvironment { | |||
70 | } | 70 | } |
71 | } | 71 | } |
72 | 72 | ||
73 | /// Something (usually a goal), along with an environment. | ||
74 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
75 | pub struct InEnvironment<T> { | ||
76 | pub environment: chalk_ir::Environment<Interner>, | ||
77 | pub goal: T, | ||
78 | } | ||
79 | |||
80 | impl<T> InEnvironment<T> { | ||
81 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { | ||
82 | InEnvironment { environment, goal: value } | ||
83 | } | ||
84 | } | ||
85 | |||
86 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
87 | /// a certain type implements a certain trait. Proving the Obligation might | ||
88 | /// result in additional information about inference variables. | ||
89 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
90 | pub enum DomainGoal { | ||
91 | Holds(WhereClause), | ||
92 | } | ||
93 | |||
94 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
95 | pub struct AliasEq { | ||
96 | pub alias: AliasTy, | ||
97 | pub ty: Ty, | ||
98 | } | ||
99 | |||
100 | impl TypeWalk for AliasEq { | ||
101 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
102 | self.ty.walk(f); | ||
103 | match &self.alias { | ||
104 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
105 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
106 | } | ||
107 | } | ||
108 | |||
109 | fn walk_mut_binders( | ||
110 | &mut self, | ||
111 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
112 | binders: DebruijnIndex, | ||
113 | ) { | ||
114 | self.ty.walk_mut_binders(f, binders); | ||
115 | match &mut self.alias { | ||
116 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
117 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
118 | } | ||
119 | } | ||
120 | } | ||
121 | |||
122 | /// Solve a trait goal using Chalk. | 73 | /// Solve a trait goal using Chalk. |
123 | pub(crate) fn trait_solve_query( | 74 | pub(crate) fn trait_solve_query( |
124 | db: &dyn HirDatabase, | 75 | db: &dyn HirDatabase, |
@@ -246,41 +197,6 @@ fn solution_from_chalk( | |||
246 | } | 197 | } |
247 | } | 198 | } |
248 | 199 | ||
249 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
250 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
251 | |||
252 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
253 | /// A (possible) solution for a proposed goal. | ||
254 | pub enum Solution { | ||
255 | /// The goal indeed holds, and there is a unique value for all existential | ||
256 | /// variables. | ||
257 | Unique(SolutionVariables), | ||
258 | |||
259 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
260 | /// for type inference. In this case, we don't return any lifetime | ||
261 | /// constraints, since we have not "committed" to any particular solution | ||
262 | /// yet. | ||
263 | Ambig(Guidance), | ||
264 | } | ||
265 | |||
266 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
267 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
268 | /// solutions), we issue a set of *guidance* back to type inference. | ||
269 | pub enum Guidance { | ||
270 | /// The existential variables *must* have the given values if the goal is | ||
271 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
272 | /// actually hold. | ||
273 | Definite(SolutionVariables), | ||
274 | |||
275 | /// There are multiple plausible values for the existentials, but the ones | ||
276 | /// here are suggested as the preferred choice heuristically. These should | ||
277 | /// be used for inference fallback only. | ||
278 | Suggested(SolutionVariables), | ||
279 | |||
280 | /// There's no useful information to feed back to type inference | ||
281 | Unknown, | ||
282 | } | ||
283 | |||
284 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] | 200 | #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)] |
285 | pub enum FnTrait { | 201 | pub enum FnTrait { |
286 | FnOnce, | 202 | FnOnce, |
diff --git a/crates/hir_ty/src/traits/chalk.rs b/crates/hir_ty/src/traits/chalk.rs index fbac51b05..541e6082f 100644 --- a/crates/hir_ty/src/traits/chalk.rs +++ b/crates/hir_ty/src/traits/chalk.rs | |||
@@ -22,7 +22,7 @@ use crate::{ | |||
22 | to_assoc_type_id, to_chalk_trait_id, | 22 | to_assoc_type_id, to_chalk_trait_id, |
23 | utils::generics, | 23 | utils::generics, |
24 | AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, | 24 | AliasEq, AliasTy, BoundVar, CallableDefId, DebruijnIndex, FnDefId, ProjectionTy, Substitution, |
25 | TraitRef, Ty, TyKind, WhereClause, | 25 | TraitRef, Ty, TyBuilder, TyKind, WhereClause, |
26 | }; | 26 | }; |
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, |
@@ -300,7 +300,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> { | |||
300 | _closure_id: chalk_ir::ClosureId<Interner>, | 300 | _closure_id: chalk_ir::ClosureId<Interner>, |
301 | _substs: &chalk_ir::Substitution<Interner>, | 301 | _substs: &chalk_ir::Substitution<Interner>, |
302 | ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { | 302 | ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { |
303 | let ty = Ty::unit().to_chalk(self.db); | 303 | let ty = TyBuilder::unit().to_chalk(self.db); |
304 | make_binders(ty, 0) | 304 | make_binders(ty, 0) |
305 | } | 305 | } |
306 | fn closure_fn_substitution( | 306 | fn closure_fn_substitution( |
@@ -387,7 +387,7 @@ pub(crate) fn associated_ty_data_query( | |||
387 | // Lower bounds -- we could/should maybe move this to a separate query in `lower` | 387 | // Lower bounds -- we could/should maybe move this to a separate query in `lower` |
388 | let type_alias_data = db.type_alias_data(type_alias); | 388 | let type_alias_data = db.type_alias_data(type_alias); |
389 | let generic_params = generics(db.upcast(), type_alias.into()); | 389 | let generic_params = generics(db.upcast(), type_alias.into()); |
390 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 390 | let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); |
391 | let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); | 391 | let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); |
392 | let ctx = crate::TyLoweringContext::new(db, &resolver) | 392 | let ctx = crate::TyLoweringContext::new(db, &resolver) |
393 | .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); | 393 | .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); |
@@ -421,7 +421,7 @@ pub(crate) fn trait_datum_query( | |||
421 | let trait_data = db.trait_data(trait_); | 421 | let trait_data = db.trait_data(trait_); |
422 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); | 422 | debug!("trait {:?} = {:?}", trait_id, trait_data.name); |
423 | let generic_params = generics(db.upcast(), trait_.into()); | 423 | let generic_params = generics(db.upcast(), trait_.into()); |
424 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 424 | let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); |
425 | let flags = rust_ir::TraitFlags { | 425 | let flags = rust_ir::TraitFlags { |
426 | auto: trait_data.is_auto, | 426 | auto: trait_data.is_auto, |
427 | upstream: trait_.lookup(db.upcast()).container.krate() != krate, | 427 | upstream: trait_.lookup(db.upcast()).container.krate() != krate, |
@@ -490,7 +490,7 @@ pub(crate) fn struct_datum_query( | |||
490 | let upstream = adt_id.module(db.upcast()).krate() != krate; | 490 | let upstream = adt_id.module(db.upcast()).krate() != krate; |
491 | let where_clauses = { | 491 | let where_clauses = { |
492 | let generic_params = generics(db.upcast(), adt_id.into()); | 492 | let generic_params = generics(db.upcast(), adt_id.into()); |
493 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 493 | let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); |
494 | convert_where_clauses(db, adt_id.into(), &bound_vars) | 494 | convert_where_clauses(db, adt_id.into(), &bound_vars) |
495 | }; | 495 | }; |
496 | let flags = rust_ir::AdtFlags { | 496 | let flags = rust_ir::AdtFlags { |
@@ -539,7 +539,7 @@ fn impl_def_datum( | |||
539 | let impl_data = db.impl_data(impl_id); | 539 | let impl_data = db.impl_data(impl_id); |
540 | 540 | ||
541 | let generic_params = generics(db.upcast(), impl_id.into()); | 541 | let generic_params = generics(db.upcast(), impl_id.into()); |
542 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 542 | let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); |
543 | let trait_ = trait_ref.hir_trait_id(); | 543 | let trait_ = trait_ref.hir_trait_id(); |
544 | let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { | 544 | let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { |
545 | rust_ir::ImplType::Local | 545 | rust_ir::ImplType::Local |
@@ -629,7 +629,7 @@ pub(crate) fn fn_def_datum_query( | |||
629 | let callable_def: CallableDefId = from_chalk(db, fn_def_id); | 629 | let callable_def: CallableDefId = from_chalk(db, fn_def_id); |
630 | let generic_params = generics(db.upcast(), callable_def.into()); | 630 | let generic_params = generics(db.upcast(), callable_def.into()); |
631 | let sig = db.callable_item_signature(callable_def); | 631 | let sig = db.callable_item_signature(callable_def); |
632 | let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); | 632 | let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST); |
633 | let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); | 633 | let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); |
634 | let bound = rust_ir::FnDefDatumBound { | 634 | let bound = rust_ir::FnDefDatumBound { |
635 | // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway | 635 | // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway |
diff --git a/crates/hir_ty/src/traits/chalk/mapping.rs b/crates/hir_ty/src/traits/chalk/mapping.rs index 452b357e8..5e4f97a46 100644 --- a/crates/hir_ty/src/traits/chalk/mapping.rs +++ b/crates/hir_ty/src/traits/chalk/mapping.rs | |||
@@ -10,11 +10,9 @@ use base_db::salsa::InternKey; | |||
10 | use hir_def::{GenericDefId, TypeAliasId}; | 10 | use hir_def::{GenericDefId, TypeAliasId}; |
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | db::HirDatabase, | 13 | db::HirDatabase, primitive::UintTy, AliasTy, CallableDefId, Canonical, DomainGoal, FnPointer, |
14 | primitive::UintTy, | 14 | GenericArg, InEnvironment, OpaqueTy, ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, |
15 | traits::{Canonical, DomainGoal}, | 15 | TraitRef, Ty, TypeWalk, WhereClause, |
16 | AliasTy, CallableDefId, FnPointer, GenericArg, InEnvironment, OpaqueTy, ProjectionTy, | ||
17 | QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TypeWalk, WhereClause, | ||
18 | }; | 16 | }; |
19 | 17 | ||
20 | use super::interner::*; | 18 | use super::interner::*; |
@@ -220,8 +218,8 @@ impl ToChalk for GenericArg { | |||
220 | type Chalk = chalk_ir::GenericArg<Interner>; | 218 | type Chalk = chalk_ir::GenericArg<Interner>; |
221 | 219 | ||
222 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { | 220 | fn to_chalk(self, db: &dyn HirDatabase) -> Self::Chalk { |
223 | match self.interned { | 221 | match self.interned() { |
224 | crate::GenericArgData::Ty(ty) => ty.to_chalk(db).cast(&Interner), | 222 | crate::GenericArgData::Ty(ty) => ty.clone().to_chalk(db).cast(&Interner), |
225 | } | 223 | } |
226 | } | 224 | } |
227 | 225 | ||
@@ -249,7 +247,7 @@ impl ToChalk for Substitution { | |||
249 | parameters: chalk_ir::Substitution<Interner>, | 247 | parameters: chalk_ir::Substitution<Interner>, |
250 | ) -> Substitution { | 248 | ) -> Substitution { |
251 | let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); | 249 | let tys = parameters.iter(&Interner).map(|p| from_chalk(db, p.clone())).collect(); |
252 | Substitution(tys) | 250 | Substitution::intern(tys) |
253 | } | 251 | } |
254 | } | 252 | } |
255 | 253 | ||
@@ -546,7 +544,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
546 | // have the expected self type | 544 | // have the expected self type |
547 | return None; | 545 | return None; |
548 | } | 546 | } |
549 | let args_no_self = trait_ref.substitution.interned(&Interner)[1..] | 547 | let args_no_self = trait_ref.substitution.interned()[1..] |
550 | .iter() | 548 | .iter() |
551 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 549 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
552 | .collect(); | 550 | .collect(); |
@@ -558,7 +556,7 @@ pub(super) fn generic_predicate_to_inline_bound( | |||
558 | return None; | 556 | return None; |
559 | } | 557 | } |
560 | let trait_ = projection_ty.trait_(db); | 558 | let trait_ = projection_ty.trait_(db); |
561 | let args_no_self = projection_ty.substitution.interned(&Interner)[1..] | 559 | let args_no_self = projection_ty.substitution.interned()[1..] |
562 | .iter() | 560 | .iter() |
563 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) | 561 | .map(|ty| ty.clone().to_chalk(db).cast(&Interner)) |
564 | .collect(); | 562 | .collect(); |
diff --git a/crates/hir_ty/src/types.rs b/crates/hir_ty/src/types.rs new file mode 100644 index 000000000..53662fcdc --- /dev/null +++ b/crates/hir_ty/src/types.rs | |||
@@ -0,0 +1,416 @@ | |||
1 | //! This is the home of `Ty` etc. until they get replaced by their chalk_ir | ||
2 | //! equivalents. | ||
3 | |||
4 | use std::sync::Arc; | ||
5 | |||
6 | use chalk_ir::{ | ||
7 | cast::{CastTo, Caster}, | ||
8 | BoundVar, Mutability, Scalar, TyVariableKind, | ||
9 | }; | ||
10 | use hir_def::LifetimeParamId; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use crate::{ | ||
14 | AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId, | ||
15 | InferenceVar, Interner, OpaqueTyId, PlaceholderIndex, | ||
16 | }; | ||
17 | |||
18 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
19 | pub enum Lifetime { | ||
20 | Parameter(LifetimeParamId), | ||
21 | Static, | ||
22 | } | ||
23 | |||
24 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
25 | pub struct OpaqueTy { | ||
26 | pub opaque_ty_id: OpaqueTyId, | ||
27 | pub substitution: Substitution, | ||
28 | } | ||
29 | |||
30 | /// A "projection" type corresponds to an (unnormalized) | ||
31 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
32 | /// trait and all its parameters are fully known. | ||
33 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
34 | pub struct ProjectionTy { | ||
35 | pub associated_ty_id: AssocTypeId, | ||
36 | pub substitution: Substitution, | ||
37 | } | ||
38 | |||
39 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
40 | pub struct DynTy { | ||
41 | /// The unknown self type. | ||
42 | pub bounds: Binders<QuantifiedWhereClauses>, | ||
43 | } | ||
44 | |||
45 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
46 | pub struct FnPointer { | ||
47 | pub num_args: usize, | ||
48 | pub sig: FnSig, | ||
49 | pub substs: Substitution, | ||
50 | } | ||
51 | |||
52 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
53 | pub enum AliasTy { | ||
54 | /// A "projection" type corresponds to an (unnormalized) | ||
55 | /// projection like `<P0 as Trait<P1..Pn>>::Foo`. Note that the | ||
56 | /// trait and all its parameters are fully known. | ||
57 | Projection(ProjectionTy), | ||
58 | /// An opaque type (`impl Trait`). | ||
59 | /// | ||
60 | /// This is currently only used for return type impl trait; each instance of | ||
61 | /// `impl Trait` in a return type gets its own ID. | ||
62 | Opaque(OpaqueTy), | ||
63 | } | ||
64 | |||
65 | /// A type. | ||
66 | /// | ||
67 | /// See also the `TyKind` enum in rustc (librustc/ty/sty.rs), which represents | ||
68 | /// the same thing (but in a different way). | ||
69 | /// | ||
70 | /// This should be cheap to clone. | ||
71 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
72 | pub enum TyKind { | ||
73 | /// Structures, enumerations and unions. | ||
74 | Adt(chalk_ir::AdtId<Interner>, Substitution), | ||
75 | |||
76 | /// Represents an associated item like `Iterator::Item`. This is used | ||
77 | /// when we have tried to normalize a projection like `T::Item` but | ||
78 | /// couldn't find a better representation. In that case, we generate | ||
79 | /// an **application type** like `(Iterator::Item)<T>`. | ||
80 | AssociatedType(AssocTypeId, Substitution), | ||
81 | |||
82 | /// a scalar type like `bool` or `u32` | ||
83 | Scalar(Scalar), | ||
84 | |||
85 | /// A tuple type. For example, `(i32, bool)`. | ||
86 | Tuple(usize, Substitution), | ||
87 | |||
88 | /// An array with the given length. Written as `[T; n]`. | ||
89 | Array(Ty), | ||
90 | |||
91 | /// The pointee of an array slice. Written as `[T]`. | ||
92 | Slice(Ty), | ||
93 | |||
94 | /// A raw pointer. Written as `*mut T` or `*const T` | ||
95 | Raw(Mutability, Ty), | ||
96 | |||
97 | /// A reference; a pointer with an associated lifetime. Written as | ||
98 | /// `&'a mut T` or `&'a T`. | ||
99 | Ref(Mutability, Ty), | ||
100 | |||
101 | /// This represents a placeholder for an opaque type in situations where we | ||
102 | /// don't know the hidden type (i.e. currently almost always). This is | ||
103 | /// analogous to the `AssociatedType` type constructor. | ||
104 | /// It is also used as the type of async block, with one type parameter | ||
105 | /// representing the Future::Output type. | ||
106 | OpaqueType(OpaqueTyId, Substitution), | ||
107 | |||
108 | /// The anonymous type of a function declaration/definition. Each | ||
109 | /// function has a unique type, which is output (for a function | ||
110 | /// named `foo` returning an `i32`) as `fn() -> i32 {foo}`. | ||
111 | /// | ||
112 | /// This includes tuple struct / enum variant constructors as well. | ||
113 | /// | ||
114 | /// For example the type of `bar` here: | ||
115 | /// | ||
116 | /// ``` | ||
117 | /// fn foo() -> i32 { 1 } | ||
118 | /// let bar = foo; // bar: fn() -> i32 {foo} | ||
119 | /// ``` | ||
120 | FnDef(FnDefId, Substitution), | ||
121 | |||
122 | /// The pointee of a string slice. Written as `str`. | ||
123 | Str, | ||
124 | |||
125 | /// The never type `!`. | ||
126 | Never, | ||
127 | |||
128 | /// The type of a specific closure. | ||
129 | /// | ||
130 | /// The closure signature is stored in a `FnPtr` type in the first type | ||
131 | /// parameter. | ||
132 | Closure(ClosureId, Substitution), | ||
133 | |||
134 | /// Represents a foreign type declared in external blocks. | ||
135 | ForeignType(ForeignDefId), | ||
136 | |||
137 | /// A pointer to a function. Written as `fn() -> i32`. | ||
138 | /// | ||
139 | /// For example the type of `bar` here: | ||
140 | /// | ||
141 | /// ``` | ||
142 | /// fn foo() -> i32 { 1 } | ||
143 | /// let bar: fn() -> i32 = foo; | ||
144 | /// ``` | ||
145 | Function(FnPointer), | ||
146 | |||
147 | /// An "alias" type represents some form of type alias, such as: | ||
148 | /// - An associated type projection like `<T as Iterator>::Item` | ||
149 | /// - `impl Trait` types | ||
150 | /// - Named type aliases like `type Foo<X> = Vec<X>` | ||
151 | Alias(AliasTy), | ||
152 | |||
153 | /// A placeholder for a type parameter; for example, `T` in `fn f<T>(x: T) | ||
154 | /// {}` when we're type-checking the body of that function. In this | ||
155 | /// situation, we know this stands for *some* type, but don't know the exact | ||
156 | /// type. | ||
157 | Placeholder(PlaceholderIndex), | ||
158 | |||
159 | /// A bound type variable. This is used in various places: when representing | ||
160 | /// some polymorphic type like the type of function `fn f<T>`, the type | ||
161 | /// parameters get turned into variables; during trait resolution, inference | ||
162 | /// variables get turned into bound variables and back; and in `Dyn` the | ||
163 | /// `Self` type is represented with a bound variable as well. | ||
164 | BoundVar(BoundVar), | ||
165 | |||
166 | /// A type variable used during type checking. | ||
167 | InferenceVar(InferenceVar, TyVariableKind), | ||
168 | |||
169 | /// A trait object (`dyn Trait` or bare `Trait` in pre-2018 Rust). | ||
170 | /// | ||
171 | /// The predicates are quantified over the `Self` type, i.e. `Ty::Bound(0)` | ||
172 | /// represents the `Self` type inside the bounds. This is currently | ||
173 | /// implicit; Chalk has the `Binders` struct to make it explicit, but it | ||
174 | /// didn't seem worth the overhead yet. | ||
175 | Dyn(DynTy), | ||
176 | |||
177 | /// A placeholder for a type which could not be computed; this is propagated | ||
178 | /// to avoid useless error messages. Doubles as a placeholder where type | ||
179 | /// variables are inserted before type checking, since we want to try to | ||
180 | /// infer a better type here anyway -- for the IDE use case, we want to try | ||
181 | /// to infer as much as possible even in the presence of type errors. | ||
182 | Unknown, | ||
183 | } | ||
184 | |||
185 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
186 | pub struct Ty(Arc<TyKind>); | ||
187 | |||
188 | impl TyKind { | ||
189 | pub fn intern(self, _interner: &Interner) -> Ty { | ||
190 | Ty(Arc::new(self)) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | impl Ty { | ||
195 | pub fn kind(&self, _interner: &Interner) -> &TyKind { | ||
196 | &self.0 | ||
197 | } | ||
198 | |||
199 | pub fn interned_mut(&mut self) -> &mut TyKind { | ||
200 | Arc::make_mut(&mut self.0) | ||
201 | } | ||
202 | |||
203 | pub fn into_inner(self) -> TyKind { | ||
204 | Arc::try_unwrap(self.0).unwrap_or_else(|a| (*a).clone()) | ||
205 | } | ||
206 | } | ||
207 | |||
208 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
209 | pub struct GenericArg { | ||
210 | interned: GenericArgData, | ||
211 | } | ||
212 | |||
213 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
214 | pub enum GenericArgData { | ||
215 | Ty(Ty), | ||
216 | } | ||
217 | |||
218 | impl GenericArg { | ||
219 | /// Constructs a generic argument using `GenericArgData`. | ||
220 | pub fn new(_interner: &Interner, data: GenericArgData) -> Self { | ||
221 | GenericArg { interned: data } | ||
222 | } | ||
223 | |||
224 | /// Gets the interned value. | ||
225 | pub fn interned(&self) -> &GenericArgData { | ||
226 | &self.interned | ||
227 | } | ||
228 | |||
229 | /// Asserts that this is a type argument. | ||
230 | pub fn assert_ty_ref(&self, interner: &Interner) -> &Ty { | ||
231 | self.ty(interner).unwrap() | ||
232 | } | ||
233 | |||
234 | /// Checks whether the generic argument is a type. | ||
235 | pub fn is_ty(&self, _interner: &Interner) -> bool { | ||
236 | match self.interned() { | ||
237 | GenericArgData::Ty(_) => true, | ||
238 | } | ||
239 | } | ||
240 | |||
241 | /// Returns the type if it is one, `None` otherwise. | ||
242 | pub fn ty(&self, _interner: &Interner) -> Option<&Ty> { | ||
243 | match self.interned() { | ||
244 | GenericArgData::Ty(t) => Some(t), | ||
245 | } | ||
246 | } | ||
247 | |||
248 | pub fn interned_mut(&mut self) -> &mut GenericArgData { | ||
249 | &mut self.interned | ||
250 | } | ||
251 | } | ||
252 | |||
253 | /// A list of substitutions for generic parameters. | ||
254 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
255 | pub struct Substitution(SmallVec<[GenericArg; 2]>); | ||
256 | |||
257 | impl Substitution { | ||
258 | pub fn interned(&self) -> &[GenericArg] { | ||
259 | &self.0 | ||
260 | } | ||
261 | |||
262 | pub fn len(&self, _: &Interner) -> usize { | ||
263 | self.0.len() | ||
264 | } | ||
265 | |||
266 | pub fn is_empty(&self, _: &Interner) -> bool { | ||
267 | self.0.is_empty() | ||
268 | } | ||
269 | |||
270 | pub fn at(&self, _: &Interner, i: usize) -> &GenericArg { | ||
271 | &self.0[i] | ||
272 | } | ||
273 | |||
274 | pub fn empty(_: &Interner) -> Substitution { | ||
275 | Substitution(SmallVec::new()) | ||
276 | } | ||
277 | |||
278 | pub fn iter(&self, _: &Interner) -> std::slice::Iter<'_, GenericArg> { | ||
279 | self.0.iter() | ||
280 | } | ||
281 | |||
282 | pub fn from_iter( | ||
283 | interner: &Interner, | ||
284 | elements: impl IntoIterator<Item = impl CastTo<GenericArg>>, | ||
285 | ) -> Self { | ||
286 | Substitution(elements.into_iter().casted(interner).collect()) | ||
287 | } | ||
288 | |||
289 | // We can hopefully add this to Chalk | ||
290 | pub fn intern(interned: SmallVec<[GenericArg; 2]>) -> Substitution { | ||
291 | Substitution(interned) | ||
292 | } | ||
293 | |||
294 | pub fn interned_mut(&mut self) -> &mut SmallVec<[GenericArg; 2]> { | ||
295 | &mut self.0 | ||
296 | } | ||
297 | } | ||
298 | |||
299 | #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)] | ||
300 | pub struct Binders<T> { | ||
301 | pub num_binders: usize, | ||
302 | pub value: T, | ||
303 | } | ||
304 | |||
305 | /// A trait with type parameters. This includes the `Self`, so this represents a concrete type implementing the trait. | ||
306 | #[derive(Clone, PartialEq, Eq, Debug, Hash)] | ||
307 | pub struct TraitRef { | ||
308 | pub trait_id: ChalkTraitId, | ||
309 | pub substitution: Substitution, | ||
310 | } | ||
311 | |||
312 | /// Like `generics::WherePredicate`, but with resolved types: A condition on the | ||
313 | /// parameters of a generic item. | ||
314 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
315 | pub enum WhereClause { | ||
316 | /// The given trait needs to be implemented for its type parameters. | ||
317 | Implemented(TraitRef), | ||
318 | /// An associated type bindings like in `Iterator<Item = T>`. | ||
319 | AliasEq(AliasEq), | ||
320 | } | ||
321 | |||
322 | pub type QuantifiedWhereClause = Binders<WhereClause>; | ||
323 | |||
324 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
325 | pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>); | ||
326 | |||
327 | impl QuantifiedWhereClauses { | ||
328 | pub fn from_iter( | ||
329 | _interner: &Interner, | ||
330 | elements: impl IntoIterator<Item = QuantifiedWhereClause>, | ||
331 | ) -> Self { | ||
332 | QuantifiedWhereClauses(elements.into_iter().collect()) | ||
333 | } | ||
334 | |||
335 | pub fn interned(&self) -> &Arc<[QuantifiedWhereClause]> { | ||
336 | &self.0 | ||
337 | } | ||
338 | |||
339 | pub fn interned_mut(&mut self) -> &mut Arc<[QuantifiedWhereClause]> { | ||
340 | &mut self.0 | ||
341 | } | ||
342 | } | ||
343 | |||
344 | /// Basically a claim (currently not validated / checked) that the contained | ||
345 | /// type / trait ref contains no inference variables; any inference variables it | ||
346 | /// contained have been replaced by bound variables, and `kinds` tells us how | ||
347 | /// many there are and whether they were normal or float/int variables. This is | ||
348 | /// used to erase irrelevant differences between types before using them in | ||
349 | /// queries. | ||
350 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | ||
351 | pub struct Canonical<T> { | ||
352 | pub value: T, | ||
353 | pub binders: CanonicalVarKinds, | ||
354 | } | ||
355 | |||
356 | /// Something (usually a goal), along with an environment. | ||
357 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
358 | pub struct InEnvironment<T> { | ||
359 | pub environment: chalk_ir::Environment<Interner>, | ||
360 | pub goal: T, | ||
361 | } | ||
362 | |||
363 | impl<T> InEnvironment<T> { | ||
364 | pub fn new(environment: chalk_ir::Environment<Interner>, value: T) -> InEnvironment<T> { | ||
365 | InEnvironment { environment, goal: value } | ||
366 | } | ||
367 | } | ||
368 | |||
369 | /// Something that needs to be proven (by Chalk) during type checking, e.g. that | ||
370 | /// a certain type implements a certain trait. Proving the Obligation might | ||
371 | /// result in additional information about inference variables. | ||
372 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
373 | pub enum DomainGoal { | ||
374 | Holds(WhereClause), | ||
375 | } | ||
376 | |||
377 | #[derive(Clone, Debug, PartialEq, Eq, Hash)] | ||
378 | pub struct AliasEq { | ||
379 | pub alias: AliasTy, | ||
380 | pub ty: Ty, | ||
381 | } | ||
382 | |||
383 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
384 | pub struct SolutionVariables(pub Canonical<Substitution>); | ||
385 | |||
386 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
387 | /// A (possible) solution for a proposed goal. | ||
388 | pub enum Solution { | ||
389 | /// The goal indeed holds, and there is a unique value for all existential | ||
390 | /// variables. | ||
391 | Unique(SolutionVariables), | ||
392 | |||
393 | /// The goal may be provable in multiple ways, but regardless we may have some guidance | ||
394 | /// for type inference. In this case, we don't return any lifetime | ||
395 | /// constraints, since we have not "committed" to any particular solution | ||
396 | /// yet. | ||
397 | Ambig(Guidance), | ||
398 | } | ||
399 | |||
400 | #[derive(Clone, Debug, PartialEq, Eq)] | ||
401 | /// When a goal holds ambiguously (e.g., because there are multiple possible | ||
402 | /// solutions), we issue a set of *guidance* back to type inference. | ||
403 | pub enum Guidance { | ||
404 | /// The existential variables *must* have the given values if the goal is | ||
405 | /// ever to hold, but that alone isn't enough to guarantee the goal will | ||
406 | /// actually hold. | ||
407 | Definite(SolutionVariables), | ||
408 | |||
409 | /// There are multiple plausible values for the existentials, but the ones | ||
410 | /// here are suggested as the preferred choice heuristically. These should | ||
411 | /// be used for inference fallback only. | ||
412 | Suggested(SolutionVariables), | ||
413 | |||
414 | /// There's no useful information to feed back to type inference | ||
415 | Unknown, | ||
416 | } | ||
diff --git a/crates/hir_ty/src/utils.rs b/crates/hir_ty/src/utils.rs index 42d7af146..df0ea4368 100644 --- a/crates/hir_ty/src/utils.rs +++ b/crates/hir_ty/src/utils.rs | |||
@@ -2,13 +2,14 @@ | |||
2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). | 2 | //! query, but can't be computed directly from `*Data` (ie, which need a `db`). |
3 | use std::sync::Arc; | 3 | use std::sync::Arc; |
4 | 4 | ||
5 | use chalk_ir::DebruijnIndex; | 5 | use chalk_ir::{BoundVar, DebruijnIndex}; |
6 | use hir_def::{ | 6 | use hir_def::{ |
7 | adt::VariantData, | 7 | adt::VariantData, |
8 | db::DefDatabase, | 8 | db::DefDatabase, |
9 | generics::{ | 9 | generics::{ |
10 | GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, | 10 | GenericParams, TypeParamData, TypeParamProvenance, WherePredicate, WherePredicateTypeTarget, |
11 | }, | 11 | }, |
12 | intern::Interned, | ||
12 | path::Path, | 13 | path::Path, |
13 | resolver::{HasResolver, TypeNs}, | 14 | resolver::{HasResolver, TypeNs}, |
14 | type_ref::TypeRef, | 15 | type_ref::TypeRef, |
@@ -16,7 +17,7 @@ use hir_def::{ | |||
16 | }; | 17 | }; |
17 | use hir_expand::name::{name, Name}; | 18 | use hir_expand::name::{name, Name}; |
18 | 19 | ||
19 | use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; | 20 | use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause}; |
20 | 21 | ||
21 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | 22 | fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { |
22 | let resolver = trait_.resolver(db); | 23 | let resolver = trait_.resolver(db); |
@@ -32,11 +33,10 @@ fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { | |||
32 | .filter_map(|pred| match pred { | 33 | .filter_map(|pred| match pred { |
33 | WherePredicate::ForLifetime { target, bound, .. } | 34 | WherePredicate::ForLifetime { target, bound, .. } |
34 | | WherePredicate::TypeBound { target, bound } => match target { | 35 | | WherePredicate::TypeBound { target, bound } => match target { |
35 | WherePredicateTypeTarget::TypeRef(TypeRef::Path(p)) | 36 | WherePredicateTypeTarget::TypeRef(type_ref) => match &**type_ref { |
36 | if p == &Path::from(name![Self]) => | 37 | TypeRef::Path(p) if p == &Path::from(name![Self]) => bound.as_path(), |
37 | { | 38 | _ => None, |
38 | bound.as_path() | 39 | }, |
39 | } | ||
40 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { | 40 | WherePredicateTypeTarget::TypeParam(local_id) if Some(*local_id) == trait_self => { |
41 | bound.as_path() | 41 | bound.as_path() |
42 | } | 42 | } |
@@ -159,7 +159,7 @@ pub(crate) fn generics(db: &dyn DefDatabase, def: GenericDefId) -> Generics { | |||
159 | #[derive(Debug)] | 159 | #[derive(Debug)] |
160 | pub(crate) struct Generics { | 160 | pub(crate) struct Generics { |
161 | def: GenericDefId, | 161 | def: GenericDefId, |
162 | pub(crate) params: Arc<GenericParams>, | 162 | pub(crate) params: Interned<GenericParams>, |
163 | parent_generics: Option<Box<Generics>>, | 163 | parent_generics: Option<Box<Generics>>, |
164 | } | 164 | } |
165 | 165 | ||
@@ -249,6 +249,26 @@ impl Generics { | |||
249 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) | 249 | self.parent_generics.as_ref().and_then(|g| g.find_param(param)) |
250 | } | 250 | } |
251 | } | 251 | } |
252 | |||
253 | /// Returns a Substitution that replaces each parameter by a bound variable. | ||
254 | pub(crate) fn bound_vars_subst(&self, debruijn: DebruijnIndex) -> Substitution { | ||
255 | Substitution::from_iter( | ||
256 | &Interner, | ||
257 | self.iter() | ||
258 | .enumerate() | ||
259 | .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
260 | ) | ||
261 | } | ||
262 | |||
263 | /// Returns a Substitution that replaces each parameter by itself (i.e. `Ty::Param`). | ||
264 | pub(crate) fn type_params_subst(&self, db: &dyn HirDatabase) -> Substitution { | ||
265 | Substitution::from_iter( | ||
266 | &Interner, | ||
267 | self.iter().map(|(id, _)| { | ||
268 | TyKind::Placeholder(crate::to_placeholder_idx(db, id)).intern(&Interner) | ||
269 | }), | ||
270 | ) | ||
271 | } | ||
252 | } | 272 | } |
253 | 273 | ||
254 | fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { | 274 | fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { |
diff --git a/crates/hir_ty/src/walk.rs b/crates/hir_ty/src/walk.rs new file mode 100644 index 000000000..bfb3f1041 --- /dev/null +++ b/crates/hir_ty/src/walk.rs | |||
@@ -0,0 +1,381 @@ | |||
1 | //! The `TypeWalk` trait (probably to be replaced by Chalk's `Fold` and | ||
2 | //! `Visit`). | ||
3 | |||
4 | use std::mem; | ||
5 | |||
6 | use chalk_ir::DebruijnIndex; | ||
7 | |||
8 | use crate::{ | ||
9 | utils::make_mut_slice, AliasEq, AliasTy, Binders, CallableSig, GenericArg, GenericArgData, | ||
10 | Interner, OpaqueTy, ProjectionTy, Substitution, TraitRef, Ty, TyKind, WhereClause, | ||
11 | }; | ||
12 | |||
13 | /// This allows walking structures that contain types to do something with those | ||
14 | /// types, similar to Chalk's `Fold` trait. | ||
15 | pub trait TypeWalk { | ||
16 | fn walk(&self, f: &mut impl FnMut(&Ty)); | ||
17 | fn walk_mut(&mut self, f: &mut impl FnMut(&mut Ty)) { | ||
18 | self.walk_mut_binders(&mut |ty, _binders| f(ty), DebruijnIndex::INNERMOST); | ||
19 | } | ||
20 | /// Walk the type, counting entered binders. | ||
21 | /// | ||
22 | /// `TyKind::Bound` variables use DeBruijn indexing, which means that 0 refers | ||
23 | /// to the innermost binder, 1 to the next, etc.. So when we want to | ||
24 | /// substitute a certain bound variable, we can't just walk the whole type | ||
25 | /// and blindly replace each instance of a certain index; when we 'enter' | ||
26 | /// things that introduce new bound variables, we have to keep track of | ||
27 | /// that. Currently, the only thing that introduces bound variables on our | ||
28 | /// side are `TyKind::Dyn` and `TyKind::Opaque`, which each introduce a bound | ||
29 | /// variable for the self type. | ||
30 | fn walk_mut_binders( | ||
31 | &mut self, | ||
32 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
33 | binders: DebruijnIndex, | ||
34 | ); | ||
35 | |||
36 | fn fold_binders( | ||
37 | mut self, | ||
38 | f: &mut impl FnMut(Ty, DebruijnIndex) -> Ty, | ||
39 | binders: DebruijnIndex, | ||
40 | ) -> Self | ||
41 | where | ||
42 | Self: Sized, | ||
43 | { | ||
44 | self.walk_mut_binders( | ||
45 | &mut |ty_mut, binders| { | ||
46 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
47 | *ty_mut = f(ty, binders); | ||
48 | }, | ||
49 | binders, | ||
50 | ); | ||
51 | self | ||
52 | } | ||
53 | |||
54 | fn fold(mut self, f: &mut impl FnMut(Ty) -> Ty) -> Self | ||
55 | where | ||
56 | Self: Sized, | ||
57 | { | ||
58 | self.walk_mut(&mut |ty_mut| { | ||
59 | let ty = mem::replace(ty_mut, TyKind::Unknown.intern(&Interner)); | ||
60 | *ty_mut = f(ty); | ||
61 | }); | ||
62 | self | ||
63 | } | ||
64 | |||
65 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
66 | fn subst_bound_vars(self, substs: &Substitution) -> Self | ||
67 | where | ||
68 | Self: Sized, | ||
69 | { | ||
70 | self.subst_bound_vars_at_depth(substs, DebruijnIndex::INNERMOST) | ||
71 | } | ||
72 | |||
73 | /// Substitutes `TyKind::Bound` vars with the given substitution. | ||
74 | fn subst_bound_vars_at_depth(mut self, substs: &Substitution, depth: DebruijnIndex) -> Self | ||
75 | where | ||
76 | Self: Sized, | ||
77 | { | ||
78 | self.walk_mut_binders( | ||
79 | &mut |ty, binders| { | ||
80 | if let &mut TyKind::BoundVar(bound) = ty.interned_mut() { | ||
81 | if bound.debruijn >= binders { | ||
82 | *ty = substs.interned()[bound.index] | ||
83 | .assert_ty_ref(&Interner) | ||
84 | .clone() | ||
85 | .shift_bound_vars(binders); | ||
86 | } | ||
87 | } | ||
88 | }, | ||
89 | depth, | ||
90 | ); | ||
91 | self | ||
92 | } | ||
93 | |||
94 | /// Shifts up debruijn indices of `TyKind::Bound` vars by `n`. | ||
95 | fn shift_bound_vars(self, n: DebruijnIndex) -> Self | ||
96 | where | ||
97 | Self: Sized, | ||
98 | { | ||
99 | self.fold_binders( | ||
100 | &mut |ty, binders| match ty.kind(&Interner) { | ||
101 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
102 | TyKind::BoundVar(bound.shifted_in_from(n)).intern(&Interner) | ||
103 | } | ||
104 | _ => ty, | ||
105 | }, | ||
106 | DebruijnIndex::INNERMOST, | ||
107 | ) | ||
108 | } | ||
109 | |||
110 | /// Shifts debruijn indices of `TyKind::Bound` vars out (down) by `n`. | ||
111 | fn shift_bound_vars_out(self, n: DebruijnIndex) -> Self | ||
112 | where | ||
113 | Self: Sized + std::fmt::Debug, | ||
114 | { | ||
115 | self.fold_binders( | ||
116 | &mut |ty, binders| match ty.kind(&Interner) { | ||
117 | TyKind::BoundVar(bound) if bound.debruijn >= binders => { | ||
118 | TyKind::BoundVar(bound.shifted_out_to(n).unwrap_or(bound.clone())) | ||
119 | .intern(&Interner) | ||
120 | } | ||
121 | _ => ty, | ||
122 | }, | ||
123 | DebruijnIndex::INNERMOST, | ||
124 | ) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl TypeWalk for Ty { | ||
129 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
130 | match self.kind(&Interner) { | ||
131 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
132 | for t in p_ty.substitution.iter(&Interner) { | ||
133 | t.walk(f); | ||
134 | } | ||
135 | } | ||
136 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
137 | for t in o_ty.substitution.iter(&Interner) { | ||
138 | t.walk(f); | ||
139 | } | ||
140 | } | ||
141 | TyKind::Dyn(dyn_ty) => { | ||
142 | for p in dyn_ty.bounds.value.interned().iter() { | ||
143 | p.walk(f); | ||
144 | } | ||
145 | } | ||
146 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
147 | ty.walk(f); | ||
148 | } | ||
149 | _ => { | ||
150 | if let Some(substs) = self.substs() { | ||
151 | for t in substs.iter(&Interner) { | ||
152 | t.walk(f); | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | f(self); | ||
158 | } | ||
159 | |||
160 | fn walk_mut_binders( | ||
161 | &mut self, | ||
162 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
163 | binders: DebruijnIndex, | ||
164 | ) { | ||
165 | match self.interned_mut() { | ||
166 | TyKind::Alias(AliasTy::Projection(p_ty)) => { | ||
167 | p_ty.substitution.walk_mut_binders(f, binders); | ||
168 | } | ||
169 | TyKind::Dyn(dyn_ty) => { | ||
170 | for p in make_mut_slice(dyn_ty.bounds.value.interned_mut()) { | ||
171 | p.walk_mut_binders(f, binders.shifted_in()); | ||
172 | } | ||
173 | } | ||
174 | TyKind::Alias(AliasTy::Opaque(o_ty)) => { | ||
175 | o_ty.substitution.walk_mut_binders(f, binders); | ||
176 | } | ||
177 | TyKind::Slice(ty) | TyKind::Array(ty) | TyKind::Ref(_, ty) | TyKind::Raw(_, ty) => { | ||
178 | ty.walk_mut_binders(f, binders); | ||
179 | } | ||
180 | _ => { | ||
181 | if let Some(substs) = self.substs_mut() { | ||
182 | substs.walk_mut_binders(f, binders); | ||
183 | } | ||
184 | } | ||
185 | } | ||
186 | f(self, binders); | ||
187 | } | ||
188 | } | ||
189 | |||
190 | impl<T: TypeWalk> TypeWalk for Vec<T> { | ||
191 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
192 | for t in self { | ||
193 | t.walk(f); | ||
194 | } | ||
195 | } | ||
196 | fn walk_mut_binders( | ||
197 | &mut self, | ||
198 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
199 | binders: DebruijnIndex, | ||
200 | ) { | ||
201 | for t in self { | ||
202 | t.walk_mut_binders(f, binders); | ||
203 | } | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl TypeWalk for OpaqueTy { | ||
208 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
209 | self.substitution.walk(f); | ||
210 | } | ||
211 | |||
212 | fn walk_mut_binders( | ||
213 | &mut self, | ||
214 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
215 | binders: DebruijnIndex, | ||
216 | ) { | ||
217 | self.substitution.walk_mut_binders(f, binders); | ||
218 | } | ||
219 | } | ||
220 | |||
221 | impl TypeWalk for ProjectionTy { | ||
222 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
223 | self.substitution.walk(f); | ||
224 | } | ||
225 | |||
226 | fn walk_mut_binders( | ||
227 | &mut self, | ||
228 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
229 | binders: DebruijnIndex, | ||
230 | ) { | ||
231 | self.substitution.walk_mut_binders(f, binders); | ||
232 | } | ||
233 | } | ||
234 | |||
235 | impl TypeWalk for AliasTy { | ||
236 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
237 | match self { | ||
238 | AliasTy::Projection(it) => it.walk(f), | ||
239 | AliasTy::Opaque(it) => it.walk(f), | ||
240 | } | ||
241 | } | ||
242 | |||
243 | fn walk_mut_binders( | ||
244 | &mut self, | ||
245 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
246 | binders: DebruijnIndex, | ||
247 | ) { | ||
248 | match self { | ||
249 | AliasTy::Projection(it) => it.walk_mut_binders(f, binders), | ||
250 | AliasTy::Opaque(it) => it.walk_mut_binders(f, binders), | ||
251 | } | ||
252 | } | ||
253 | } | ||
254 | |||
255 | impl TypeWalk for GenericArg { | ||
256 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
257 | match &self.interned() { | ||
258 | GenericArgData::Ty(ty) => { | ||
259 | ty.walk(f); | ||
260 | } | ||
261 | } | ||
262 | } | ||
263 | |||
264 | fn walk_mut_binders( | ||
265 | &mut self, | ||
266 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
267 | binders: DebruijnIndex, | ||
268 | ) { | ||
269 | match self.interned_mut() { | ||
270 | GenericArgData::Ty(ty) => { | ||
271 | ty.walk_mut_binders(f, binders); | ||
272 | } | ||
273 | } | ||
274 | } | ||
275 | } | ||
276 | |||
277 | impl TypeWalk for Substitution { | ||
278 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
279 | for t in self.iter(&Interner) { | ||
280 | t.walk(f); | ||
281 | } | ||
282 | } | ||
283 | |||
284 | fn walk_mut_binders( | ||
285 | &mut self, | ||
286 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
287 | binders: DebruijnIndex, | ||
288 | ) { | ||
289 | for t in self.interned_mut() { | ||
290 | t.walk_mut_binders(f, binders); | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | impl<T: TypeWalk> TypeWalk for Binders<T> { | ||
296 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
297 | self.value.walk(f); | ||
298 | } | ||
299 | |||
300 | fn walk_mut_binders( | ||
301 | &mut self, | ||
302 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
303 | binders: DebruijnIndex, | ||
304 | ) { | ||
305 | self.value.walk_mut_binders(f, binders.shifted_in()) | ||
306 | } | ||
307 | } | ||
308 | |||
309 | impl TypeWalk for TraitRef { | ||
310 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
311 | self.substitution.walk(f); | ||
312 | } | ||
313 | |||
314 | fn walk_mut_binders( | ||
315 | &mut self, | ||
316 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
317 | binders: DebruijnIndex, | ||
318 | ) { | ||
319 | self.substitution.walk_mut_binders(f, binders); | ||
320 | } | ||
321 | } | ||
322 | |||
323 | impl TypeWalk for WhereClause { | ||
324 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
325 | match self { | ||
326 | WhereClause::Implemented(trait_ref) => trait_ref.walk(f), | ||
327 | WhereClause::AliasEq(alias_eq) => alias_eq.walk(f), | ||
328 | } | ||
329 | } | ||
330 | |||
331 | fn walk_mut_binders( | ||
332 | &mut self, | ||
333 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
334 | binders: DebruijnIndex, | ||
335 | ) { | ||
336 | match self { | ||
337 | WhereClause::Implemented(trait_ref) => trait_ref.walk_mut_binders(f, binders), | ||
338 | WhereClause::AliasEq(alias_eq) => alias_eq.walk_mut_binders(f, binders), | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | |||
343 | impl TypeWalk for CallableSig { | ||
344 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
345 | for t in self.params_and_return.iter() { | ||
346 | t.walk(f); | ||
347 | } | ||
348 | } | ||
349 | |||
350 | fn walk_mut_binders( | ||
351 | &mut self, | ||
352 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
353 | binders: DebruijnIndex, | ||
354 | ) { | ||
355 | for t in make_mut_slice(&mut self.params_and_return) { | ||
356 | t.walk_mut_binders(f, binders); | ||
357 | } | ||
358 | } | ||
359 | } | ||
360 | |||
361 | impl TypeWalk for AliasEq { | ||
362 | fn walk(&self, f: &mut impl FnMut(&Ty)) { | ||
363 | self.ty.walk(f); | ||
364 | match &self.alias { | ||
365 | AliasTy::Projection(projection_ty) => projection_ty.walk(f), | ||
366 | AliasTy::Opaque(opaque) => opaque.walk(f), | ||
367 | } | ||
368 | } | ||
369 | |||
370 | fn walk_mut_binders( | ||
371 | &mut self, | ||
372 | f: &mut impl FnMut(&mut Ty, DebruijnIndex), | ||
373 | binders: DebruijnIndex, | ||
374 | ) { | ||
375 | self.ty.walk_mut_binders(f, binders); | ||
376 | match &mut self.alias { | ||
377 | AliasTy::Projection(projection_ty) => projection_ty.walk_mut_binders(f, binders), | ||
378 | AliasTy::Opaque(opaque) => opaque.walk_mut_binders(f, binders), | ||
379 | } | ||
380 | } | ||
381 | } | ||
diff --git a/crates/ide/src/inlay_hints.rs b/crates/ide/src/inlay_hints.rs index f73edf8b6..d5ef054d8 100644 --- a/crates/ide/src/inlay_hints.rs +++ b/crates/ide/src/inlay_hints.rs | |||
@@ -234,7 +234,7 @@ fn hint_iterator( | |||
234 | hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), | 234 | hir::AssocItem::TypeAlias(alias) if alias.name(db) == known::Item => Some(alias), |
235 | _ => None, | 235 | _ => None, |
236 | })?; | 236 | })?; |
237 | if let Some(ty) = ty.normalize_trait_assoc_type(db, iter_trait, &[], assoc_type_item) { | 237 | if let Some(ty) = ty.normalize_trait_assoc_type(db, &[], assoc_type_item) { |
238 | const LABEL_START: &str = "impl Iterator<Item = "; | 238 | const LABEL_START: &str = "impl Iterator<Item = "; |
239 | const LABEL_END: &str = ">"; | 239 | const LABEL_END: &str = ">"; |
240 | 240 | ||
diff --git a/crates/ide_assists/src/handlers/convert_into_to_from.rs b/crates/ide_assists/src/handlers/convert_into_to_from.rs new file mode 100644 index 000000000..199e1ad5c --- /dev/null +++ b/crates/ide_assists/src/handlers/convert_into_to_from.rs | |||
@@ -0,0 +1,355 @@ | |||
1 | use ide_db::{ | ||
2 | helpers::{mod_path_to_ast, FamousDefs}, | ||
3 | traits::resolve_target_trait, | ||
4 | }; | ||
5 | use syntax::ast::{self, AstNode, NameOwner}; | ||
6 | |||
7 | use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
8 | |||
9 | // Assist: convert_into_to_from | ||
10 | // | ||
11 | // Converts an Into impl to an equivalent From impl. | ||
12 | // | ||
13 | // ``` | ||
14 | // # //- /lib.rs crate:core | ||
15 | // # pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } } | ||
16 | // # //- /lib.rs crate:main deps:core | ||
17 | // # use core::convert::Into; | ||
18 | // impl $0Into<Thing> for usize { | ||
19 | // fn into(self) -> Thing { | ||
20 | // Thing { | ||
21 | // b: self.to_string(), | ||
22 | // a: self | ||
23 | // } | ||
24 | // } | ||
25 | // } | ||
26 | // ``` | ||
27 | // -> | ||
28 | // ``` | ||
29 | // # use core::convert::Into; | ||
30 | // impl From<usize> for Thing { | ||
31 | // fn from(val: usize) -> Self { | ||
32 | // Thing { | ||
33 | // b: val.to_string(), | ||
34 | // a: val | ||
35 | // } | ||
36 | // } | ||
37 | // } | ||
38 | // ``` | ||
39 | pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
40 | let impl_ = ctx.find_node_at_offset::<ast::Impl>()?; | ||
41 | let src_type = impl_.self_ty()?; | ||
42 | let ast_trait = impl_.trait_()?; | ||
43 | |||
44 | let module = ctx.sema.scope(impl_.syntax()).module()?; | ||
45 | |||
46 | let trait_ = resolve_target_trait(&ctx.sema, &impl_)?; | ||
47 | if trait_ != FamousDefs(&ctx.sema, Some(module.krate())).core_convert_Into()? { | ||
48 | return None; | ||
49 | } | ||
50 | |||
51 | let src_type_path = { | ||
52 | let src_type_path = src_type.syntax().descendants().find_map(ast::Path::cast)?; | ||
53 | let src_type_def = match ctx.sema.resolve_path(&src_type_path) { | ||
54 | Some(hir::PathResolution::Def(module_def)) => module_def, | ||
55 | _ => return None, | ||
56 | }; | ||
57 | |||
58 | mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def)?) | ||
59 | }; | ||
60 | |||
61 | let dest_type = match &ast_trait { | ||
62 | ast::Type::PathType(path) => { | ||
63 | path.path()?.segment()?.generic_arg_list()?.generic_args().next()? | ||
64 | } | ||
65 | _ => return None, | ||
66 | }; | ||
67 | |||
68 | let into_fn = impl_.assoc_item_list()?.assoc_items().find_map(|item| { | ||
69 | if let ast::AssocItem::Fn(f) = item { | ||
70 | if f.name()?.text() == "into" { | ||
71 | return Some(f); | ||
72 | } | ||
73 | }; | ||
74 | None | ||
75 | })?; | ||
76 | |||
77 | let into_fn_name = into_fn.name()?; | ||
78 | let into_fn_params = into_fn.param_list()?; | ||
79 | let into_fn_return = into_fn.ret_type()?; | ||
80 | |||
81 | let selfs = into_fn | ||
82 | .body()? | ||
83 | .syntax() | ||
84 | .descendants() | ||
85 | .filter_map(ast::NameRef::cast) | ||
86 | .filter(|name| name.text() == "self" || name.text() == "Self"); | ||
87 | |||
88 | acc.add( | ||
89 | AssistId("convert_into_to_from", AssistKind::RefactorRewrite), | ||
90 | "Convert Into to From", | ||
91 | impl_.syntax().text_range(), | ||
92 | |builder| { | ||
93 | builder.replace(src_type.syntax().text_range(), dest_type.to_string()); | ||
94 | builder.replace(ast_trait.syntax().text_range(), format!("From<{}>", src_type)); | ||
95 | builder.replace(into_fn_return.syntax().text_range(), "-> Self"); | ||
96 | builder.replace( | ||
97 | into_fn_params.syntax().text_range(), | ||
98 | format!("(val: {})", src_type.to_string()), | ||
99 | ); | ||
100 | builder.replace(into_fn_name.syntax().text_range(), "from"); | ||
101 | |||
102 | for s in selfs { | ||
103 | match s.text().as_ref() { | ||
104 | "self" => builder.replace(s.syntax().text_range(), "val"), | ||
105 | "Self" => builder.replace(s.syntax().text_range(), src_type_path.to_string()), | ||
106 | _ => {} | ||
107 | } | ||
108 | } | ||
109 | }, | ||
110 | ) | ||
111 | } | ||
112 | |||
113 | #[cfg(test)] | ||
114 | mod tests { | ||
115 | use super::*; | ||
116 | |||
117 | use crate::tests::check_assist; | ||
118 | |||
119 | #[test] | ||
120 | fn convert_into_to_from_converts_a_struct() { | ||
121 | check_convert_into_to_from( | ||
122 | r#" | ||
123 | struct Thing { | ||
124 | a: String, | ||
125 | b: usize | ||
126 | } | ||
127 | |||
128 | impl $0core::convert::Into<Thing> for usize { | ||
129 | fn into(self) -> Thing { | ||
130 | Thing { | ||
131 | b: self.to_string(), | ||
132 | a: self | ||
133 | } | ||
134 | } | ||
135 | } | ||
136 | "#, | ||
137 | r#" | ||
138 | struct Thing { | ||
139 | a: String, | ||
140 | b: usize | ||
141 | } | ||
142 | |||
143 | impl From<usize> for Thing { | ||
144 | fn from(val: usize) -> Self { | ||
145 | Thing { | ||
146 | b: val.to_string(), | ||
147 | a: val | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | "#, | ||
152 | ) | ||
153 | } | ||
154 | |||
155 | #[test] | ||
156 | fn convert_into_to_from_converts_enums() { | ||
157 | check_convert_into_to_from( | ||
158 | r#" | ||
159 | enum Thing { | ||
160 | Foo(String), | ||
161 | Bar(String) | ||
162 | } | ||
163 | |||
164 | impl $0core::convert::Into<String> for Thing { | ||
165 | fn into(self) -> String { | ||
166 | match self { | ||
167 | Self::Foo(s) => s, | ||
168 | Self::Bar(s) => s | ||
169 | } | ||
170 | } | ||
171 | } | ||
172 | "#, | ||
173 | r#" | ||
174 | enum Thing { | ||
175 | Foo(String), | ||
176 | Bar(String) | ||
177 | } | ||
178 | |||
179 | impl From<Thing> for String { | ||
180 | fn from(val: Thing) -> Self { | ||
181 | match val { | ||
182 | Thing::Foo(s) => s, | ||
183 | Thing::Bar(s) => s | ||
184 | } | ||
185 | } | ||
186 | } | ||
187 | "#, | ||
188 | ) | ||
189 | } | ||
190 | |||
191 | #[test] | ||
192 | fn convert_into_to_from_on_enum_with_lifetimes() { | ||
193 | check_convert_into_to_from( | ||
194 | r#" | ||
195 | enum Thing<'a> { | ||
196 | Foo(&'a str), | ||
197 | Bar(&'a str) | ||
198 | } | ||
199 | |||
200 | impl<'a> $0core::convert::Into<&'a str> for Thing<'a> { | ||
201 | fn into(self) -> &'a str { | ||
202 | match self { | ||
203 | Self::Foo(s) => s, | ||
204 | Self::Bar(s) => s | ||
205 | } | ||
206 | } | ||
207 | } | ||
208 | "#, | ||
209 | r#" | ||
210 | enum Thing<'a> { | ||
211 | Foo(&'a str), | ||
212 | Bar(&'a str) | ||
213 | } | ||
214 | |||
215 | impl<'a> From<Thing<'a>> for &'a str { | ||
216 | fn from(val: Thing<'a>) -> Self { | ||
217 | match val { | ||
218 | Thing::Foo(s) => s, | ||
219 | Thing::Bar(s) => s | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | "#, | ||
224 | ) | ||
225 | } | ||
226 | |||
227 | #[test] | ||
228 | fn convert_into_to_from_works_on_references() { | ||
229 | check_convert_into_to_from( | ||
230 | r#" | ||
231 | struct Thing(String); | ||
232 | |||
233 | impl $0core::convert::Into<String> for &Thing { | ||
234 | fn into(self) -> Thing { | ||
235 | self.0.clone() | ||
236 | } | ||
237 | } | ||
238 | "#, | ||
239 | r#" | ||
240 | struct Thing(String); | ||
241 | |||
242 | impl From<&Thing> for String { | ||
243 | fn from(val: &Thing) -> Self { | ||
244 | val.0.clone() | ||
245 | } | ||
246 | } | ||
247 | "#, | ||
248 | ) | ||
249 | } | ||
250 | |||
251 | #[test] | ||
252 | fn convert_into_to_from_works_on_qualified_structs() { | ||
253 | check_convert_into_to_from( | ||
254 | r#" | ||
255 | mod things { | ||
256 | pub struct Thing(String); | ||
257 | pub struct BetterThing(String); | ||
258 | } | ||
259 | |||
260 | impl $0core::convert::Into<things::BetterThing> for &things::Thing { | ||
261 | fn into(self) -> Thing { | ||
262 | things::BetterThing(self.0.clone()) | ||
263 | } | ||
264 | } | ||
265 | "#, | ||
266 | r#" | ||
267 | mod things { | ||
268 | pub struct Thing(String); | ||
269 | pub struct BetterThing(String); | ||
270 | } | ||
271 | |||
272 | impl From<&things::Thing> for things::BetterThing { | ||
273 | fn from(val: &things::Thing) -> Self { | ||
274 | things::BetterThing(val.0.clone()) | ||
275 | } | ||
276 | } | ||
277 | "#, | ||
278 | ) | ||
279 | } | ||
280 | |||
281 | #[test] | ||
282 | fn convert_into_to_from_works_on_qualified_enums() { | ||
283 | check_convert_into_to_from( | ||
284 | r#" | ||
285 | mod things { | ||
286 | pub enum Thing { | ||
287 | A(String) | ||
288 | } | ||
289 | pub struct BetterThing { | ||
290 | B(String) | ||
291 | } | ||
292 | } | ||
293 | |||
294 | impl $0core::convert::Into<things::BetterThing> for &things::Thing { | ||
295 | fn into(self) -> Thing { | ||
296 | match self { | ||
297 | Self::A(s) => things::BetterThing::B(s) | ||
298 | } | ||
299 | } | ||
300 | } | ||
301 | "#, | ||
302 | r#" | ||
303 | mod things { | ||
304 | pub enum Thing { | ||
305 | A(String) | ||
306 | } | ||
307 | pub struct BetterThing { | ||
308 | B(String) | ||
309 | } | ||
310 | } | ||
311 | |||
312 | impl From<&things::Thing> for things::BetterThing { | ||
313 | fn from(val: &things::Thing) -> Self { | ||
314 | match val { | ||
315 | things::Thing::A(s) => things::BetterThing::B(s) | ||
316 | } | ||
317 | } | ||
318 | } | ||
319 | "#, | ||
320 | ) | ||
321 | } | ||
322 | |||
323 | #[test] | ||
324 | fn convert_into_to_from_not_applicable_on_any_trait_named_into() { | ||
325 | check_assist_not_applicable( | ||
326 | r#" | ||
327 | pub trait Into<T> {{ | ||
328 | pub fn into(self) -> T; | ||
329 | }} | ||
330 | |||
331 | struct Thing { | ||
332 | a: String, | ||
333 | } | ||
334 | |||
335 | impl $0Into<Thing> for String { | ||
336 | fn into(self) -> Thing { | ||
337 | Thing { | ||
338 | a: self | ||
339 | } | ||
340 | } | ||
341 | } | ||
342 | "#, | ||
343 | ); | ||
344 | } | ||
345 | |||
346 | fn check_convert_into_to_from(before: &str, after: &str) { | ||
347 | let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE); | ||
348 | check_assist(convert_into_to_from, before, after); | ||
349 | } | ||
350 | |||
351 | fn check_assist_not_applicable(before: &str) { | ||
352 | let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE); | ||
353 | crate::tests::check_assist_not_applicable(convert_into_to_from, before); | ||
354 | } | ||
355 | } | ||
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs index 3d1dcef4c..3e2c82dac 100644 --- a/crates/ide_assists/src/lib.rs +++ b/crates/ide_assists/src/lib.rs | |||
@@ -117,6 +117,7 @@ mod handlers { | |||
117 | mod convert_integer_literal; | 117 | mod convert_integer_literal; |
118 | mod convert_comment_block; | 118 | mod convert_comment_block; |
119 | mod convert_iter_for_each_to_for; | 119 | mod convert_iter_for_each_to_for; |
120 | mod convert_into_to_from; | ||
120 | mod early_return; | 121 | mod early_return; |
121 | mod expand_glob_import; | 122 | mod expand_glob_import; |
122 | mod extract_function; | 123 | mod extract_function; |
@@ -185,6 +186,7 @@ mod handlers { | |||
185 | convert_integer_literal::convert_integer_literal, | 186 | convert_integer_literal::convert_integer_literal, |
186 | convert_comment_block::convert_comment_block, | 187 | convert_comment_block::convert_comment_block, |
187 | convert_iter_for_each_to_for::convert_iter_for_each_to_for, | 188 | convert_iter_for_each_to_for::convert_iter_for_each_to_for, |
189 | convert_into_to_from::convert_into_to_from, | ||
188 | early_return::convert_to_guarded_return, | 190 | early_return::convert_to_guarded_return, |
189 | expand_glob_import::expand_glob_import, | 191 | expand_glob_import::expand_glob_import, |
190 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, | 192 | extract_struct_from_enum_variant::extract_struct_from_enum_variant, |
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs index 03b7fb366..27a22ca10 100644 --- a/crates/ide_assists/src/tests/generated.rs +++ b/crates/ide_assists/src/tests/generated.rs | |||
@@ -206,6 +206,38 @@ const _: i32 = 0b1010; | |||
206 | } | 206 | } |
207 | 207 | ||
208 | #[test] | 208 | #[test] |
209 | fn doctest_convert_into_to_from() { | ||
210 | check_doc_test( | ||
211 | "convert_into_to_from", | ||
212 | r#####" | ||
213 | //- /lib.rs crate:core | ||
214 | pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } } | ||
215 | //- /lib.rs crate:main deps:core | ||
216 | use core::convert::Into; | ||
217 | impl $0Into<Thing> for usize { | ||
218 | fn into(self) -> Thing { | ||
219 | Thing { | ||
220 | b: self.to_string(), | ||
221 | a: self | ||
222 | } | ||
223 | } | ||
224 | } | ||
225 | "#####, | ||
226 | r#####" | ||
227 | use core::convert::Into; | ||
228 | impl From<usize> for Thing { | ||
229 | fn from(val: usize) -> Self { | ||
230 | Thing { | ||
231 | b: val.to_string(), | ||
232 | a: val | ||
233 | } | ||
234 | } | ||
235 | } | ||
236 | "#####, | ||
237 | ) | ||
238 | } | ||
239 | |||
240 | #[test] | ||
209 | fn doctest_convert_iter_for_each_to_for() { | 241 | fn doctest_convert_iter_for_each_to_for() { |
210 | check_doc_test( | 242 | check_doc_test( |
211 | "convert_iter_for_each_to_for", | 243 | "convert_iter_for_each_to_for", |
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs index 9992a92bd..66798ea3a 100644 --- a/crates/ide_db/src/helpers.rs +++ b/crates/ide_db/src/helpers.rs | |||
@@ -93,6 +93,10 @@ impl FamousDefs<'_, '_> { | |||
93 | self.find_trait("core:convert:From") | 93 | self.find_trait("core:convert:From") |
94 | } | 94 | } |
95 | 95 | ||
96 | pub fn core_convert_Into(&self) -> Option<Trait> { | ||
97 | self.find_trait("core:convert:Into") | ||
98 | } | ||
99 | |||
96 | pub fn core_option_Option(&self) -> Option<Enum> { | 100 | pub fn core_option_Option(&self) -> Option<Enum> { |
97 | self.find_enum("core:option:Option") | 101 | self.find_enum("core:option:Option") |
98 | } | 102 | } |
diff --git a/crates/ide_db/src/helpers/famous_defs_fixture.rs b/crates/ide_db/src/helpers/famous_defs_fixture.rs index d3464ae17..4d79e064e 100644 --- a/crates/ide_db/src/helpers/famous_defs_fixture.rs +++ b/crates/ide_db/src/helpers/famous_defs_fixture.rs | |||
@@ -14,6 +14,10 @@ pub mod convert { | |||
14 | pub trait From<T> { | 14 | pub trait From<T> { |
15 | fn from(t: T) -> Self; | 15 | fn from(t: T) -> Self; |
16 | } | 16 | } |
17 | |||
18 | pub trait Into<T> { | ||
19 | pub fn into(self) -> T; | ||
20 | } | ||
17 | } | 21 | } |
18 | 22 | ||
19 | pub mod default { | 23 | pub mod default { |
@@ -120,7 +124,7 @@ pub mod option { | |||
120 | pub mod prelude { | 124 | pub mod prelude { |
121 | pub use crate::{ | 125 | pub use crate::{ |
122 | cmp::Ord, | 126 | cmp::Ord, |
123 | convert::From, | 127 | convert::{From, Into}, |
124 | default::Default, | 128 | default::Default, |
125 | iter::{IntoIterator, Iterator}, | 129 | iter::{IntoIterator, Iterator}, |
126 | ops::{Fn, FnMut, FnOnce}, | 130 | ops::{Fn, FnMut, FnOnce}, |
diff --git a/crates/mbe/src/benchmark.rs b/crates/mbe/src/benchmark.rs index ba814a2e1..38707ffa5 100644 --- a/crates/mbe/src/benchmark.rs +++ b/crates/mbe/src/benchmark.rs | |||
@@ -65,7 +65,7 @@ fn macro_rules_fixtures_tt() -> FxHashMap<String, tt::Subtree> { | |||
65 | .filter_map(ast::MacroRules::cast) | 65 | .filter_map(ast::MacroRules::cast) |
66 | .map(|rule| { | 66 | .map(|rule| { |
67 | let id = rule.name().unwrap().to_string(); | 67 | let id = rule.name().unwrap().to_string(); |
68 | let (def_tt, _) = ast_to_token_tree(&rule.token_tree().unwrap()).unwrap(); | 68 | let (def_tt, _) = ast_to_token_tree(&rule.token_tree().unwrap()); |
69 | (id, def_tt) | 69 | (id, def_tt) |
70 | }) | 70 | }) |
71 | .collect() | 71 | .collect() |
diff --git a/crates/mbe/src/expander.rs b/crates/mbe/src/expander.rs index 3197c834c..bfef7f73d 100644 --- a/crates/mbe/src/expander.rs +++ b/crates/mbe/src/expander.rs | |||
@@ -159,8 +159,7 @@ mod tests { | |||
159 | let macro_definition = | 159 | let macro_definition = |
160 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); | 160 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); |
161 | 161 | ||
162 | let (definition_tt, _) = | 162 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()); |
163 | ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); | ||
164 | crate::MacroRules::parse(&definition_tt).unwrap() | 163 | crate::MacroRules::parse(&definition_tt).unwrap() |
165 | } | 164 | } |
166 | 165 | ||
@@ -169,8 +168,7 @@ mod tests { | |||
169 | let macro_invocation = | 168 | let macro_invocation = |
170 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | 169 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
171 | 170 | ||
172 | let (invocation_tt, _) = | 171 | let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()); |
173 | ast_to_token_tree(¯o_invocation.token_tree().unwrap()).unwrap(); | ||
174 | 172 | ||
175 | expand_rules(&rules.rules, &invocation_tt) | 173 | expand_rules(&rules.rules, &invocation_tt) |
176 | } | 174 | } |
diff --git a/crates/mbe/src/syntax_bridge.rs b/crates/mbe/src/syntax_bridge.rs index ae0780072..9ba98f7fb 100644 --- a/crates/mbe/src/syntax_bridge.rs +++ b/crates/mbe/src/syntax_bridge.rs | |||
@@ -43,18 +43,18 @@ pub struct TokenMap { | |||
43 | 43 | ||
44 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro | 44 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro |
45 | /// will consume). | 45 | /// will consume). |
46 | pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> Option<(tt::Subtree, TokenMap)> { | 46 | pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> (tt::Subtree, TokenMap) { |
47 | syntax_node_to_token_tree(ast.syntax()) | 47 | syntax_node_to_token_tree(ast.syntax()) |
48 | } | 48 | } |
49 | 49 | ||
50 | /// Convert the syntax node to a `TokenTree` (what macro | 50 | /// Convert the syntax node to a `TokenTree` (what macro |
51 | /// will consume). | 51 | /// will consume). |
52 | pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> { | 52 | pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> (tt::Subtree, TokenMap) { |
53 | let global_offset = node.text_range().start(); | 53 | let global_offset = node.text_range().start(); |
54 | let mut c = Convertor::new(node, global_offset); | 54 | let mut c = Convertor::new(node, global_offset); |
55 | let subtree = c.go()?; | 55 | let subtree = c.go(); |
56 | c.id_alloc.map.entries.shrink_to_fit(); | 56 | c.id_alloc.map.entries.shrink_to_fit(); |
57 | Some((subtree, c.id_alloc.map)) | 57 | (subtree, c.id_alloc.map) |
58 | } | 58 | } |
59 | 59 | ||
60 | // The following items are what `rustc` macro can be parsed into : | 60 | // The following items are what `rustc` macro can be parsed into : |
@@ -108,7 +108,7 @@ pub fn parse_to_token_tree(text: &str) -> Option<(tt::Subtree, TokenMap)> { | |||
108 | }, | 108 | }, |
109 | }; | 109 | }; |
110 | 110 | ||
111 | let subtree = conv.go()?; | 111 | let subtree = conv.go(); |
112 | Some((subtree, conv.id_alloc.map)) | 112 | Some((subtree, conv.id_alloc.map)) |
113 | } | 113 | } |
114 | 114 | ||
@@ -319,7 +319,7 @@ trait SrcToken: std::fmt::Debug { | |||
319 | trait TokenConvertor { | 319 | trait TokenConvertor { |
320 | type Token: SrcToken; | 320 | type Token: SrcToken; |
321 | 321 | ||
322 | fn go(&mut self) -> Option<tt::Subtree> { | 322 | fn go(&mut self) -> tt::Subtree { |
323 | let mut subtree = tt::Subtree::default(); | 323 | let mut subtree = tt::Subtree::default(); |
324 | subtree.delimiter = None; | 324 | subtree.delimiter = None; |
325 | while self.peek().is_some() { | 325 | while self.peek().is_some() { |
@@ -327,10 +327,10 @@ trait TokenConvertor { | |||
327 | } | 327 | } |
328 | if subtree.token_trees.len() == 1 { | 328 | if subtree.token_trees.len() == 1 { |
329 | if let tt::TokenTree::Subtree(first) = &subtree.token_trees[0] { | 329 | if let tt::TokenTree::Subtree(first) = &subtree.token_trees[0] { |
330 | return Some(first.clone()); | 330 | return first.clone(); |
331 | } | 331 | } |
332 | } | 332 | } |
333 | Some(subtree) | 333 | subtree |
334 | } | 334 | } |
335 | 335 | ||
336 | fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) { | 336 | fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) { |
@@ -858,7 +858,7 @@ mod tests { | |||
858 | // - T!['}'] | 858 | // - T!['}'] |
859 | // - WHITE_SPACE | 859 | // - WHITE_SPACE |
860 | let token_tree = ast::TokenTree::cast(token_tree).unwrap(); | 860 | let token_tree = ast::TokenTree::cast(token_tree).unwrap(); |
861 | let tt = ast_to_token_tree(&token_tree).unwrap().0; | 861 | let tt = ast_to_token_tree(&token_tree).0; |
862 | 862 | ||
863 | assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace)); | 863 | assert_eq!(tt.delimiter_kind(), Some(tt::DelimiterKind::Brace)); |
864 | } | 864 | } |
@@ -867,7 +867,7 @@ mod tests { | |||
867 | fn test_token_tree_multi_char_punct() { | 867 | fn test_token_tree_multi_char_punct() { |
868 | let source_file = ast::SourceFile::parse("struct Foo { a: x::Y }").ok().unwrap(); | 868 | let source_file = ast::SourceFile::parse("struct Foo { a: x::Y }").ok().unwrap(); |
869 | let struct_def = source_file.syntax().descendants().find_map(ast::Struct::cast).unwrap(); | 869 | let struct_def = source_file.syntax().descendants().find_map(ast::Struct::cast).unwrap(); |
870 | let tt = ast_to_token_tree(&struct_def).unwrap().0; | 870 | let tt = ast_to_token_tree(&struct_def).0; |
871 | token_tree_to_syntax_node(&tt, FragmentKind::Item).unwrap(); | 871 | token_tree_to_syntax_node(&tt, FragmentKind::Item).unwrap(); |
872 | } | 872 | } |
873 | } | 873 | } |
diff --git a/crates/mbe/src/tests.rs b/crates/mbe/src/tests.rs index 6da18ecf4..3698ff3f0 100644 --- a/crates/mbe/src/tests.rs +++ b/crates/mbe/src/tests.rs | |||
@@ -29,8 +29,7 @@ macro_rules! impl_fixture { | |||
29 | let macro_invocation = | 29 | let macro_invocation = |
30 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); | 30 | source_file.syntax().descendants().find_map(ast::MacroCall::cast).unwrap(); |
31 | 31 | ||
32 | let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()) | 32 | let (invocation_tt, _) = ast_to_token_tree(¯o_invocation.token_tree().unwrap()); |
33 | .ok_or_else(|| ExpandError::ConversionError)?; | ||
34 | 33 | ||
35 | self.rules.expand(&invocation_tt).result() | 34 | self.rules.expand(&invocation_tt).result() |
36 | } | 35 | } |
@@ -101,7 +100,7 @@ macro_rules! impl_fixture { | |||
101 | .descendants() | 100 | .descendants() |
102 | .find_map(ast::TokenTree::cast) | 101 | .find_map(ast::TokenTree::cast) |
103 | .unwrap(); | 102 | .unwrap(); |
104 | let mut wrapped = ast_to_token_tree(&wrapped).unwrap().0; | 103 | let mut wrapped = ast_to_token_tree(&wrapped).0; |
105 | wrapped.delimiter = None; | 104 | wrapped.delimiter = None; |
106 | wrapped | 105 | wrapped |
107 | }; | 106 | }; |
@@ -151,7 +150,7 @@ pub(crate) fn parse_macro_error(ra_fixture: &str) -> ParseError { | |||
151 | 150 | ||
152 | pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree { | 151 | pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree { |
153 | let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); | 152 | let source_file = ast::SourceFile::parse(ra_fixture).ok().unwrap(); |
154 | let tt = syntax_node_to_token_tree(source_file.syntax()).unwrap().0; | 153 | let tt = syntax_node_to_token_tree(source_file.syntax()).0; |
155 | 154 | ||
156 | let parsed = parse_to_token_tree(ra_fixture).unwrap().0; | 155 | let parsed = parse_to_token_tree(ra_fixture).unwrap().0; |
157 | assert_eq!(tt, parsed); | 156 | assert_eq!(tt, parsed); |
@@ -164,7 +163,7 @@ fn parse_macro_rules_to_tt(ra_fixture: &str) -> tt::Subtree { | |||
164 | let macro_definition = | 163 | let macro_definition = |
165 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); | 164 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); |
166 | 165 | ||
167 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); | 166 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()); |
168 | 167 | ||
169 | let parsed = parse_to_token_tree( | 168 | let parsed = parse_to_token_tree( |
170 | &ra_fixture[macro_definition.token_tree().unwrap().syntax().text_range()], | 169 | &ra_fixture[macro_definition.token_tree().unwrap().syntax().text_range()], |
@@ -181,7 +180,7 @@ fn parse_macro_def_to_tt(ra_fixture: &str) -> tt::Subtree { | |||
181 | let macro_definition = | 180 | let macro_definition = |
182 | source_file.syntax().descendants().find_map(ast::MacroDef::cast).unwrap(); | 181 | source_file.syntax().descendants().find_map(ast::MacroDef::cast).unwrap(); |
183 | 182 | ||
184 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.body().unwrap()).unwrap(); | 183 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.body().unwrap()); |
185 | 184 | ||
186 | let parsed = | 185 | let parsed = |
187 | parse_to_token_tree(&ra_fixture[macro_definition.body().unwrap().syntax().text_range()]) | 186 | parse_to_token_tree(&ra_fixture[macro_definition.body().unwrap().syntax().text_range()]) |
diff --git a/crates/mbe/src/tests/rule.rs b/crates/mbe/src/tests/rule.rs index bf48112b3..5c61a98fd 100644 --- a/crates/mbe/src/tests/rule.rs +++ b/crates/mbe/src/tests/rule.rs | |||
@@ -44,6 +44,6 @@ fn parse_macro_arm(arm_definition: &str) -> Result<crate::MacroRules, ParseError | |||
44 | let macro_definition = | 44 | let macro_definition = |
45 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); | 45 | source_file.syntax().descendants().find_map(ast::MacroRules::cast).unwrap(); |
46 | 46 | ||
47 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()).unwrap(); | 47 | let (definition_tt, _) = ast_to_token_tree(¯o_definition.token_tree().unwrap()); |
48 | crate::MacroRules::parse(&definition_tt) | 48 | crate::MacroRules::parse(&definition_tt) |
49 | } | 49 | } |
diff --git a/crates/rust-analyzer/src/bin/flags.rs b/crates/rust-analyzer/src/bin/flags.rs index b05fc00b9..63953098a 100644 --- a/crates/rust-analyzer/src/bin/flags.rs +++ b/crates/rust-analyzer/src/bin/flags.rs | |||
@@ -71,6 +71,8 @@ xflags::xflags! { | |||
71 | optional --load-output-dirs | 71 | optional --load-output-dirs |
72 | /// Use proc-macro-srv for proc-macro expanding. | 72 | /// Use proc-macro-srv for proc-macro expanding. |
73 | optional --with-proc-macro | 73 | optional --with-proc-macro |
74 | /// Only resolve names, don't run type inference. | ||
75 | optional --skip-inference | ||
74 | } | 76 | } |
75 | 77 | ||
76 | cmd diagnostics | 78 | cmd diagnostics |
@@ -158,6 +160,7 @@ pub struct AnalysisStats { | |||
158 | pub no_sysroot: bool, | 160 | pub no_sysroot: bool, |
159 | pub load_output_dirs: bool, | 161 | pub load_output_dirs: bool, |
160 | pub with_proc_macro: bool, | 162 | pub with_proc_macro: bool, |
163 | pub skip_inference: bool, | ||
161 | } | 164 | } |
162 | 165 | ||
163 | #[derive(Debug)] | 166 | #[derive(Debug)] |
diff --git a/crates/rust-analyzer/src/bin/main.rs b/crates/rust-analyzer/src/bin/main.rs index 3b9b9e8b4..873e82c7b 100644 --- a/crates/rust-analyzer/src/bin/main.rs +++ b/crates/rust-analyzer/src/bin/main.rs | |||
@@ -78,6 +78,7 @@ fn try_main() -> Result<()> { | |||
78 | path: cmd.path, | 78 | path: cmd.path, |
79 | load_output_dirs: cmd.load_output_dirs, | 79 | load_output_dirs: cmd.load_output_dirs, |
80 | with_proc_macro: cmd.with_proc_macro, | 80 | with_proc_macro: cmd.with_proc_macro, |
81 | skip_inference: cmd.skip_inference, | ||
81 | } | 82 | } |
82 | .run(verbosity)?, | 83 | .run(verbosity)?, |
83 | 84 | ||
diff --git a/crates/rust-analyzer/src/cargo_target_spec.rs b/crates/rust-analyzer/src/cargo_target_spec.rs index 5af0802a2..909c21532 100644 --- a/crates/rust-analyzer/src/cargo_target_spec.rs +++ b/crates/rust-analyzer/src/cargo_target_spec.rs | |||
@@ -201,7 +201,7 @@ mod tests { | |||
201 | let cfg_expr = { | 201 | let cfg_expr = { |
202 | let source_file = ast::SourceFile::parse(cfg).ok().unwrap(); | 202 | let source_file = ast::SourceFile::parse(cfg).ok().unwrap(); |
203 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 203 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
204 | let (tt, _) = ast_to_token_tree(&tt).unwrap(); | 204 | let (tt, _) = ast_to_token_tree(&tt); |
205 | CfgExpr::parse(&tt) | 205 | CfgExpr::parse(&tt) |
206 | }; | 206 | }; |
207 | 207 | ||
diff --git a/crates/rust-analyzer/src/cli/analysis_stats.rs b/crates/rust-analyzer/src/cli/analysis_stats.rs index 9c59e7ee4..18fd7ea74 100644 --- a/crates/rust-analyzer/src/cli/analysis_stats.rs +++ b/crates/rust-analyzer/src/cli/analysis_stats.rs | |||
@@ -9,10 +9,11 @@ use std::{ | |||
9 | 9 | ||
10 | use hir::{ | 10 | use hir::{ |
11 | db::{AstDatabase, DefDatabase, HirDatabase}, | 11 | db::{AstDatabase, DefDatabase, HirDatabase}, |
12 | AssocItem, Crate, 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::TypeWalk; |
16 | use ide::{AnalysisHost, RootDatabase}; | ||
16 | use ide_db::base_db::{ | 17 | use ide_db::base_db::{ |
17 | salsa::{self, ParallelDatabase}, | 18 | salsa::{self, ParallelDatabase}, |
18 | SourceDatabaseExt, | 19 | SourceDatabaseExt, |
@@ -24,6 +25,7 @@ use rayon::prelude::*; | |||
24 | use rustc_hash::FxHashSet; | 25 | use rustc_hash::FxHashSet; |
25 | use stdx::format_to; | 26 | use stdx::format_to; |
26 | use syntax::AstNode; | 27 | use syntax::AstNode; |
28 | use vfs::Vfs; | ||
27 | 29 | ||
28 | use crate::cli::{ | 30 | use crate::cli::{ |
29 | load_cargo::{load_workspace_at, LoadCargoConfig}, | 31 | load_cargo::{load_workspace_at, LoadCargoConfig}, |
@@ -51,6 +53,7 @@ pub struct AnalysisStatsCmd { | |||
51 | pub path: PathBuf, | 53 | pub path: PathBuf, |
52 | pub load_output_dirs: bool, | 54 | pub load_output_dirs: bool, |
53 | pub with_proc_macro: bool, | 55 | pub with_proc_macro: bool, |
56 | pub skip_inference: bool, | ||
54 | } | 57 | } |
55 | 58 | ||
56 | impl AnalysisStatsCmd { | 59 | impl AnalysisStatsCmd { |
@@ -128,6 +131,39 @@ impl AnalysisStatsCmd { | |||
128 | shuffle(&mut rng, &mut funcs); | 131 | shuffle(&mut rng, &mut funcs); |
129 | } | 132 | } |
130 | 133 | ||
134 | if !self.skip_inference { | ||
135 | self.run_inference(&host, db, &vfs, &funcs, verbosity); | ||
136 | } | ||
137 | |||
138 | let total_span = analysis_sw.elapsed(); | ||
139 | eprintln!("{:<20} {}", "Total:", total_span); | ||
140 | report_metric("total time", total_span.time.as_millis() as u64, "ms"); | ||
141 | if let Some(instructions) = total_span.instructions { | ||
142 | report_metric("total instructions", instructions, "#instr"); | ||
143 | } | ||
144 | if let Some(memory) = total_span.memory { | ||
145 | report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); | ||
146 | } | ||
147 | |||
148 | if env::var("RA_COUNT").is_ok() { | ||
149 | eprintln!("{}", profile::countme::get_all()); | ||
150 | } | ||
151 | |||
152 | if self.memory_usage && verbosity.is_verbose() { | ||
153 | print_memory_usage(host, vfs); | ||
154 | } | ||
155 | |||
156 | Ok(()) | ||
157 | } | ||
158 | |||
159 | fn run_inference( | ||
160 | &self, | ||
161 | host: &AnalysisHost, | ||
162 | db: &RootDatabase, | ||
163 | vfs: &Vfs, | ||
164 | funcs: &[Function], | ||
165 | verbosity: Verbosity, | ||
166 | ) { | ||
131 | let mut bar = match verbosity { | 167 | let mut bar = match verbosity { |
132 | Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(), | 168 | Verbosity::Quiet | Verbosity::Spammy => ProgressReport::hidden(), |
133 | _ if self.parallel => ProgressReport::hidden(), | 169 | _ if self.parallel => ProgressReport::hidden(), |
@@ -154,7 +190,7 @@ impl AnalysisStatsCmd { | |||
154 | let mut num_exprs_unknown = 0; | 190 | let mut num_exprs_unknown = 0; |
155 | let mut num_exprs_partially_unknown = 0; | 191 | let mut num_exprs_partially_unknown = 0; |
156 | let mut num_type_mismatches = 0; | 192 | let mut num_type_mismatches = 0; |
157 | for f in funcs { | 193 | for f in funcs.iter().copied() { |
158 | let name = f.name(db); | 194 | let name = f.name(db); |
159 | let full_name = f | 195 | let full_name = f |
160 | .module(db) | 196 | .module(db) |
@@ -296,26 +332,6 @@ impl AnalysisStatsCmd { | |||
296 | report_metric("type mismatches", num_type_mismatches, "#"); | 332 | report_metric("type mismatches", num_type_mismatches, "#"); |
297 | 333 | ||
298 | eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed()); | 334 | eprintln!("{:<20} {}", "Inference:", inference_sw.elapsed()); |
299 | |||
300 | let total_span = analysis_sw.elapsed(); | ||
301 | eprintln!("{:<20} {}", "Total:", total_span); | ||
302 | report_metric("total time", total_span.time.as_millis() as u64, "ms"); | ||
303 | if let Some(instructions) = total_span.instructions { | ||
304 | report_metric("total instructions", instructions, "#instr"); | ||
305 | } | ||
306 | if let Some(memory) = total_span.memory { | ||
307 | report_metric("total memory", memory.allocated.megabytes() as u64, "MB"); | ||
308 | } | ||
309 | |||
310 | if env::var("RA_COUNT").is_ok() { | ||
311 | eprintln!("{}", profile::countme::get_all()); | ||
312 | } | ||
313 | |||
314 | if self.memory_usage && verbosity.is_verbose() { | ||
315 | print_memory_usage(host, vfs); | ||
316 | } | ||
317 | |||
318 | Ok(()) | ||
319 | } | 335 | } |
320 | 336 | ||
321 | fn stop_watch(&self) -> StopWatch { | 337 | fn stop_watch(&self) -> StopWatch { |
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs index 53d29ddfc..4d10a2ead 100644 --- a/crates/rust-analyzer/src/handlers.rs +++ b/crates/rust-analyzer/src/handlers.rs | |||
@@ -927,19 +927,22 @@ pub(crate) fn handle_formatting( | |||
927 | let captured_stderr = String::from_utf8(output.stderr).unwrap_or_default(); | 927 | let captured_stderr = String::from_utf8(output.stderr).unwrap_or_default(); |
928 | 928 | ||
929 | if !output.status.success() { | 929 | if !output.status.success() { |
930 | match output.status.code() { | 930 | let rustfmt_not_installed = |
931 | Some(1) if !captured_stderr.contains("not installed") => { | 931 | captured_stderr.contains("not installed") || captured_stderr.contains("not available"); |
932 | |||
933 | return match output.status.code() { | ||
934 | Some(1) if !rustfmt_not_installed => { | ||
932 | // While `rustfmt` doesn't have a specific exit code for parse errors this is the | 935 | // While `rustfmt` doesn't have a specific exit code for parse errors this is the |
933 | // likely cause exiting with 1. Most Language Servers swallow parse errors on | 936 | // likely cause exiting with 1. Most Language Servers swallow parse errors on |
934 | // formatting because otherwise an error is surfaced to the user on top of the | 937 | // formatting because otherwise an error is surfaced to the user on top of the |
935 | // syntax error diagnostics they're already receiving. This is especially jarring | 938 | // syntax error diagnostics they're already receiving. This is especially jarring |
936 | // if they have format on save enabled. | 939 | // if they have format on save enabled. |
937 | log::info!("rustfmt exited with status 1, assuming parse error and ignoring"); | 940 | log::info!("rustfmt exited with status 1, assuming parse error and ignoring"); |
938 | return Ok(None); | 941 | Ok(None) |
939 | } | 942 | } |
940 | _ => { | 943 | _ => { |
941 | // Something else happened - e.g. `rustfmt` is missing or caught a signal | 944 | // Something else happened - e.g. `rustfmt` is missing or caught a signal |
942 | return Err(LspError::new( | 945 | Err(LspError::new( |
943 | -32900, | 946 | -32900, |
944 | format!( | 947 | format!( |
945 | r#"rustfmt exited with: | 948 | r#"rustfmt exited with: |
@@ -949,9 +952,9 @@ pub(crate) fn handle_formatting( | |||
949 | output.status, captured_stdout, captured_stderr, | 952 | output.status, captured_stdout, captured_stderr, |
950 | ), | 953 | ), |
951 | ) | 954 | ) |
952 | .into()); | 955 | .into()) |
953 | } | 956 | } |
954 | } | 957 | }; |
955 | } | 958 | } |
956 | 959 | ||
957 | let (new_text, new_line_endings) = LineEndings::normalize(captured_stdout); | 960 | let (new_text, new_line_endings) = LineEndings::normalize(captured_stdout); |
diff --git a/docs/dev/lsp-extensions.md b/docs/dev/lsp-extensions.md index 8a6f9f06e..73be59a82 100644 --- a/docs/dev/lsp-extensions.md +++ b/docs/dev/lsp-extensions.md | |||
@@ -602,8 +602,7 @@ interface TestInfo { | |||
602 | 602 | ||
603 | This request is sent from client to server to move item under cursor or selection in some direction. | 603 | This request is sent from client to server to move item under cursor or selection in some direction. |
604 | 604 | ||
605 | **Method:** `experimental/moveItemUp` | 605 | **Method:** `experimental/moveItem` |
606 | **Method:** `experimental/moveItemDown` | ||
607 | 606 | ||
608 | **Request:** `MoveItemParams` | 607 | **Request:** `MoveItemParams` |
609 | 608 | ||
diff --git a/docs/dev/style.md b/docs/dev/style.md index c594946be..48ce4b92a 100644 --- a/docs/dev/style.md +++ b/docs/dev/style.md | |||
@@ -842,7 +842,26 @@ Re-using originally single-purpose function often leads to bad coupling. | |||
842 | 842 | ||
843 | ## Helper Variables | 843 | ## Helper Variables |
844 | 844 | ||
845 | Introduce helper variables freely, especially for multiline conditions. | 845 | Introduce helper variables freely, especially for multiline conditions: |
846 | |||
847 | ```rust | ||
848 | // GOOD | ||
849 | let rustfmt_not_installed = | ||
850 | captured_stderr.contains("not installed") || captured_stderr.contains("not available"); | ||
851 | |||
852 | match output.status.code() { | ||
853 | Some(1) if !rustfmt_not_installed => Ok(None), | ||
854 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
855 | }; | ||
856 | |||
857 | // BAD | ||
858 | match output.status.code() { | ||
859 | Some(1) | ||
860 | if !captured_stderr.contains("not installed") | ||
861 | && !captured_stderr.contains("not available") => Ok(None), | ||
862 | _ => Err(format_err!("rustfmt failed:\n{}", captured_stderr)), | ||
863 | }; | ||
864 | ``` | ||
846 | 865 | ||
847 | **Rationale:** like blocks, single-use variables are a cognitively cheap abstraction, as they have access to all the context. | 866 | **Rationale:** like blocks, single-use variables are a cognitively cheap abstraction, as they have access to all the context. |
848 | Extra variables help during debugging, they make it easy to print/view important intermediate results. | 867 | Extra variables help during debugging, they make it easy to print/view important intermediate results. |
diff --git a/lib/arena/src/lib.rs b/lib/arena/src/lib.rs index 230a50291..1720537cb 100644 --- a/lib/arena/src/lib.rs +++ b/lib/arena/src/lib.rs | |||
@@ -90,7 +90,7 @@ impl<T> Idx<T> { | |||
90 | } | 90 | } |
91 | 91 | ||
92 | /// Yet another index-based arena. | 92 | /// Yet another index-based arena. |
93 | #[derive(Clone, PartialEq, Eq)] | 93 | #[derive(Clone, PartialEq, Eq, Hash)] |
94 | pub struct Arena<T> { | 94 | pub struct Arena<T> { |
95 | data: Vec<T>, | 95 | data: Vec<T>, |
96 | } | 96 | } |
@@ -194,6 +194,29 @@ impl<T> Arena<T> { | |||
194 | self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value)) | 194 | self.data.iter().enumerate().map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value)) |
195 | } | 195 | } |
196 | 196 | ||
197 | /// Returns an iterator over the arena’s mutable elements. | ||
198 | /// | ||
199 | /// ``` | ||
200 | /// let mut arena = la_arena::Arena::new(); | ||
201 | /// let idx1 = arena.alloc(20); | ||
202 | /// | ||
203 | /// assert_eq!(arena[idx1], 20); | ||
204 | /// | ||
205 | /// let mut iterator = arena.iter_mut(); | ||
206 | /// *iterator.next().unwrap().1 = 10; | ||
207 | /// drop(iterator); | ||
208 | /// | ||
209 | /// assert_eq!(arena[idx1], 10); | ||
210 | /// ``` | ||
211 | pub fn iter_mut( | ||
212 | &mut self, | ||
213 | ) -> impl Iterator<Item = (Idx<T>, &mut T)> + ExactSizeIterator + DoubleEndedIterator { | ||
214 | self.data | ||
215 | .iter_mut() | ||
216 | .enumerate() | ||
217 | .map(|(idx, value)| (Idx::from_raw(RawIdx(idx as u32)), value)) | ||
218 | } | ||
219 | |||
197 | /// Reallocates the arena to make it take up as little space as possible. | 220 | /// Reallocates the arena to make it take up as little space as possible. |
198 | pub fn shrink_to_fit(&mut self) { | 221 | pub fn shrink_to_fit(&mut self) { |
199 | self.data.shrink_to_fit(); | 222 | self.data.shrink_to_fit(); |