aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock28
-rw-r--r--crates/cfg/src/tests.rs8
-rw-r--r--crates/hir/src/db.rs10
-rw-r--r--crates/hir/src/display.rs21
-rw-r--r--crates/hir/src/lib.rs46
-rw-r--r--crates/hir_def/src/attr.rs2
-rw-r--r--crates/hir_def/src/body.rs24
-rw-r--r--crates/hir_def/src/body/lower.rs12
-rw-r--r--crates/hir_def/src/child_by_source.rs2
-rw-r--r--crates/hir_def/src/data.rs57
-rw-r--r--crates/hir_def/src/db.rs3
-rw-r--r--crates/hir_def/src/generics.rs62
-rw-r--r--crates/hir_def/src/intern.rs10
-rw-r--r--crates/hir_def/src/item_scope.rs22
-rw-r--r--crates/hir_def/src/item_tree.rs95
-rw-r--r--crates/hir_def/src/item_tree/lower.rs77
-rw-r--r--crates/hir_def/src/lib.rs2
-rw-r--r--crates/hir_def/src/nameres.rs25
-rw-r--r--crates/hir_def/src/nameres/collector.rs12
-rw-r--r--crates/hir_def/src/path.rs2
-rw-r--r--crates/hir_def/src/path/lower.rs2
-rw-r--r--crates/hir_def/src/resolver.rs3
-rw-r--r--crates/hir_def/src/visibility.rs6
-rw-r--r--crates/hir_expand/src/builtin_macro.rs2
-rw-r--r--crates/hir_expand/src/db.rs14
-rw-r--r--crates/hir_expand/src/eager.rs4
-rw-r--r--crates/hir_ty/src/autoderef.rs40
-rw-r--r--crates/hir_ty/src/builder.rs219
-rw-r--r--crates/hir_ty/src/chalk_ext.rs13
-rw-r--r--crates/hir_ty/src/db.rs2
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs5
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs4
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs6
-rw-r--r--crates/hir_ty/src/display.rs28
-rw-r--r--crates/hir_ty/src/infer.rs17
-rw-r--r--crates/hir_ty/src/infer/coerce.rs29
-rw-r--r--crates/hir_ty/src/infer/expr.rs110
-rw-r--r--crates/hir_ty/src/infer/pat.rs30
-rw-r--r--crates/hir_ty/src/infer/path.rs27
-rw-r--r--crates/hir_ty/src/infer/unify.rs15
-rw-r--r--crates/hir_ty/src/lib.rs843
-rw-r--r--crates/hir_ty/src/lower.rs51
-rw-r--r--crates/hir_ty/src/method_resolution.rs18
-rw-r--r--crates/hir_ty/src/op.rs4
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/traits.rs88
-rw-r--r--crates/hir_ty/src/traits/chalk.rs14
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs18
-rw-r--r--crates/hir_ty/src/types.rs416
-rw-r--r--crates/hir_ty/src/utils.rs36
-rw-r--r--crates/hir_ty/src/walk.rs381
-rw-r--r--crates/ide/src/inlay_hints.rs2
-rw-r--r--crates/ide_assists/src/handlers/convert_into_to_from.rs355
-rw-r--r--crates/ide_assists/src/lib.rs2
-rw-r--r--crates/ide_assists/src/tests/generated.rs32
-rw-r--r--crates/ide_db/src/helpers.rs4
-rw-r--r--crates/ide_db/src/helpers/famous_defs_fixture.rs6
-rw-r--r--crates/mbe/src/benchmark.rs2
-rw-r--r--crates/mbe/src/expander.rs6
-rw-r--r--crates/mbe/src/syntax_bridge.rs20
-rw-r--r--crates/mbe/src/tests.rs11
-rw-r--r--crates/mbe/src/tests/rule.rs2
-rw-r--r--crates/rust-analyzer/src/bin/flags.rs3
-rw-r--r--crates/rust-analyzer/src/bin/main.rs1
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs60
-rw-r--r--crates/rust-analyzer/src/handlers.rs15
-rw-r--r--docs/dev/lsp-extensions.md3
-rw-r--r--docs/dev/style.md21
-rw-r--r--lib/arena/src/lib.rs25
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]]
39name = "anyhow" 39name = "anyhow"
40version = "1.0.39" 40version = "1.0.40"
41source = "registry+https://github.com/rust-lang/crates.io-index" 41source = "registry+https://github.com/rust-lang/crates.io-index"
42checksum = "81cddc5f91628367664cc7c69714ff08deee8a3efc54623011c772544d7b2767" 42checksum = "28b2cd92db5cbd74e8e5028f7e27dd7aa3090e89e4f2a197cc7c8dfb69c7063b"
43 43
44[[package]] 44[[package]]
45name = "anymap" 45name = "anymap"
@@ -49,9 +49,9 @@ checksum = "33954243bd79057c2de7338850b85983a44588021f8a5fee574a8888c6de4344"
49 49
50[[package]] 50[[package]]
51name = "arrayvec" 51name = "arrayvec"
52version = "0.6.0" 52version = "0.6.1"
53source = "registry+https://github.com/rust-lang/crates.io-index" 53source = "registry+https://github.com/rust-lang/crates.io-index"
54checksum = "682f88bd1270f264991da8922b89ee1fb520b0da73f97c9f73cda54980123017" 54checksum = "269d0f5e68353a7cab87f81e7c736adc008d279a36ebc6a05dfe01193a89f0c9"
55 55
56[[package]] 56[[package]]
57name = "atty" 57name = "atty"
@@ -797,9 +797,9 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
797 797
798[[package]] 798[[package]]
799name = "libc" 799name = "libc"
800version = "0.2.91" 800version = "0.2.92"
801source = "registry+https://github.com/rust-lang/crates.io-index" 801source = "registry+https://github.com/rust-lang/crates.io-index"
802checksum = "8916b1f6ca17130ec6568feccee27c156ad12037880833a3b842a823236502e7" 802checksum = "56d855069fafbb9b344c0f962150cd2c1187975cb1c22c1522c240d8c4986714"
803 803
804[[package]] 804[[package]]
805name = "libloading" 805name = "libloading"
@@ -822,9 +822,9 @@ dependencies = [
822 822
823[[package]] 823[[package]]
824name = "lock_api" 824name = "lock_api"
825version = "0.4.2" 825version = "0.4.3"
826source = "registry+https://github.com/rust-lang/crates.io-index" 826source = "registry+https://github.com/rust-lang/crates.io-index"
827checksum = "dd96ffd135b2fd7b973ac026d28085defbe8983df057ced3eb4f2130b0831312" 827checksum = "5a3c91c24eae6777794bb1997ad98bbb87daf92890acab859f7eaa4320333176"
828dependencies = [ 828dependencies = [
829 "scopeguard", 829 "scopeguard",
830] 830]
@@ -921,9 +921,9 @@ dependencies = [
921 921
922[[package]] 922[[package]]
923name = "memoffset" 923name = "memoffset"
924version = "0.6.1" 924version = "0.6.3"
925source = "registry+https://github.com/rust-lang/crates.io-index" 925source = "registry+https://github.com/rust-lang/crates.io-index"
926checksum = "157b4208e3059a8f9e78d559edc658e13df41410cb3ae03979c83130067fdd87" 926checksum = "f83fb6581e8ed1f85fd45c116db8405483899489e38406156c25eb743554361d"
927dependencies = [ 927dependencies = [
928 "autocfg", 928 "autocfg",
929] 929]
@@ -1157,9 +1157,9 @@ checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5"
1157 1157
1158[[package]] 1158[[package]]
1159name = "proc-macro2" 1159name = "proc-macro2"
1160version = "1.0.24" 1160version = "1.0.26"
1161source = "registry+https://github.com/rust-lang/crates.io-index" 1161source = "registry+https://github.com/rust-lang/crates.io-index"
1162checksum = "1e0704ee1a7e00d7bb417d0770ea303c1bccbabf0ef1667dae92b5967f5f8a71" 1162checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec"
1163dependencies = [ 1163dependencies = [
1164 "unicode-xid", 1164 "unicode-xid",
1165] 1165]
@@ -1577,9 +1577,9 @@ dependencies = [
1577 1577
1578[[package]] 1578[[package]]
1579name = "syn" 1579name = "syn"
1580version = "1.0.64" 1580version = "1.0.68"
1581source = "registry+https://github.com/rust-lang/crates.io-index" 1581source = "registry+https://github.com/rust-lang/crates.io-index"
1582checksum = "3fd9d1e9976102a03c542daa2eff1b43f9d72306342f3f8b3ed5fb8908195d6f" 1582checksum = "3ce15dd3ed8aa2f8eeac4716d6ef5ab58b6b9256db41d7e1a0224c2788e8fd87"
1583dependencies = [ 1583dependencies = [
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
3pub use hir_def::db::{ 3pub 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};
12pub use hir_expand::db::{ 4pub 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
14use crate::{ 14use crate::{
15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, 15 Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam,
16 Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, 16 Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant,
17}; 17};
18 18
19impl HirDisplay for Function { 19impl HirDisplay for Function {
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};
64use itertools::Itertools; 64use itertools::Itertools;
65use rustc_hash::FxHashSet; 65use 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 {
1129impl BuiltinType { 1129impl 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
323impl Index<ExprId> for Body { 343impl 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 {
160impl ChildBySource for DefWithBodyId { 160impl 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
36impl FunctionData { 31impl 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.
5use std::sync::Arc;
6 5
7use base_db::FileId; 6use base_db::FileId;
8use either::Either; 7use 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)]
30pub struct TypeParamData { 30pub 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)]
38pub struct LifetimeParamData { 38pub 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)]
44pub struct ConstParamData { 44pub 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)]
50pub enum TypeParamProvenance { 50pub 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)]
58pub struct GenericParams { 58pub 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)]
70pub enum WherePredicate { 70pub 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)]
77pub enum WherePredicateTypeTarget { 77pub 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};
14use once_cell::sync::OnceCell; 14use once_cell::sync::OnceCell;
15use rustc_hash::FxHasher; 15use rustc_hash::FxHasher;
16 16
17use crate::generics::GenericParams;
18
17type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; 19type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
18type Guard<T> = 20type 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
197impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str); 199impl_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
290impl PerNs { 312impl 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};
24use profile::Count; 24use profile::Count;
25use rustc_hash::FxHashMap; 25use rustc_hash::FxHashMap;
26use smallvec::SmallVec; 26use smallvec::SmallVec;
27use syntax::{ast, match_ast, SmolStr, SyntaxKind}; 27use syntax::{ast, match_ast, SyntaxKind};
28 28
29use crate::{ 29use 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)]
62pub struct GenericParamsId(u32);
63
64impl 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)]
70pub struct ItemTree { 63pub 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
242static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); 233static 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)]
245struct GenericParamsStorage {
246 arena: Arena<GenericParams>,
247}
248
249impl 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
263static 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)]
271struct ItemTreeData { 236struct 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
511impl 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
522impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { 475impl<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)]
531pub struct Import { 484pub 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 {
555pub struct Function { 508pub 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)]
577pub struct FunctionQualifier { 526pub(crate) struct FnFlags {
578 pub is_default: bool, 527 pub(crate) bits: u8,
579 pub is_const: bool, 528}
580 pub is_async: bool, 529impl 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)]
586pub struct Struct { 543pub 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 {
606pub struct Union { 563pub 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 {
615pub struct Enum { 572pub 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 {
644pub struct Trait { 601pub 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)]
656pub struct Impl { 613pub 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;
27pub mod keys; 27pub mod keys;
28 28
29pub mod item_tree; 29pub mod item_tree;
30pub mod intern;
30 31
31pub mod adt; 32pub mod adt;
32pub mod data; 33pub mod data;
@@ -49,7 +50,6 @@ pub mod import_map;
49 50
50#[cfg(test)] 51#[cfg(test)]
51mod test_db; 52mod test_db;
52mod intern;
53 53
54use std::{ 54use 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
414impl ModuleData { 439impl 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)]
141struct Import { 144struct 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 {
122pub struct Path { 122pub 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
27impl RawVisibility { 27impl 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.
219pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { 219pub(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(&macro_call)); 588 let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_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
203fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { 197fn 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(&macro_call.value.token_tree()?)?.0), 109 || Some(mbe::ast_to_token_tree(&macro_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
163fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { 163fn 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;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use 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
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const 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
3use std::iter;
4
5use chalk_ir::{
6 cast::{Cast, CastTo, Caster},
7 interner::HasInterner,
8 AdtId, BoundVar, DebruijnIndex, Safety, Scalar,
9};
10use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId};
11use smallvec::SmallVec;
12
13use crate::{
14 db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders,
15 CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty,
16 TyDefId, TyKind, TypeWalk, ValueTyDefId,
17};
18
19/// This is a builder for `Ty` or anything that needs a `Substitution`.
20pub struct TyBuilder<D> {
21 /// The `data` field is used to keep track of what we're building (e.g. an
22 /// ADT, a `TraitRef`, ...).
23 data: D,
24 vec: SmallVec<[GenericArg; 2]>,
25 param_count: usize,
26}
27
28impl<D> TyBuilder<D> {
29 fn new(data: D, param_count: usize) -> TyBuilder<D> {
30 TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) }
31 }
32
33 fn build_internal(self) -> (D, Substitution) {
34 assert_eq!(self.vec.len(), self.param_count);
35 // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form
36 let subst = Substitution::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
74impl TyBuilder<()> {
75 pub fn unit() -> Ty {
76 TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner)
77 }
78
79 pub fn fn_ptr(sig: CallableSig) -> Ty {
80 TyKind::Function(FnPointer {
81 num_args: sig.params().len(),
82 sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs },
83 substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()),
84 })
85 .intern(&Interner)
86 }
87
88 pub fn builtin(builtin: BuiltinType) -> Ty {
89 match builtin {
90 BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner),
91 BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner),
92 BuiltinType::Str => TyKind::Str.intern(&Interner),
93 BuiltinType::Int(t) => {
94 TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner)
95 }
96 BuiltinType::Uint(t) => {
97 TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner)
98 }
99 BuiltinType::Float(t) => {
100 TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner)
101 }
102 }
103 }
104
105 pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution {
106 let params = generics(db.upcast(), def.into());
107 params.type_params_subst(db)
108 }
109
110 pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> {
111 let def = def.into();
112 let params = generics(db.upcast(), def);
113 let param_count = params.len();
114 TyBuilder::new((), param_count)
115 }
116
117 pub fn build(self) -> Substitution {
118 let ((), subst) = self.build_internal();
119 subst
120 }
121}
122
123impl TyBuilder<hir_def::AdtId> {
124 pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> {
125 let generics = generics(db.upcast(), adt.into());
126 let param_count = generics.len();
127 TyBuilder::new(adt, param_count)
128 }
129
130 pub fn fill_with_defaults(
131 mut self,
132 db: &dyn HirDatabase,
133 mut fallback: impl FnMut() -> Ty,
134 ) -> Self {
135 let defaults = db.generic_defaults(self.data.into());
136 for default_ty in defaults.iter().skip(self.vec.len()) {
137 if default_ty.skip_binders().is_unknown() {
138 self.vec.push(fallback().cast(&Interner));
139 } else {
140 // each default can depend on the previous parameters
141 let subst_so_far = Substitution::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
154pub struct Tuple(usize);
155impl TyBuilder<Tuple> {
156 pub fn tuple(size: usize) -> TyBuilder<Tuple> {
157 TyBuilder::new(Tuple(size), size)
158 }
159
160 pub fn build(self) -> Ty {
161 let (Tuple(size), subst) = self.build_internal();
162 TyKind::Tuple(size, subst).intern(&Interner)
163 }
164}
165
166impl TyBuilder<TraitId> {
167 pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> {
168 let generics = generics(db.upcast(), trait_id.into());
169 let param_count = generics.len();
170 TyBuilder::new(trait_id, param_count)
171 }
172
173 pub fn build(self) -> TraitRef {
174 let (trait_id, substitution) = self.build_internal();
175 TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution }
176 }
177}
178
179impl TyBuilder<TypeAliasId> {
180 pub fn assoc_type_projection(
181 db: &dyn HirDatabase,
182 type_alias: TypeAliasId,
183 ) -> TyBuilder<TypeAliasId> {
184 let generics = generics(db.upcast(), type_alias.into());
185 let param_count = generics.len();
186 TyBuilder::new(type_alias, param_count)
187 }
188
189 pub fn build(self) -> ProjectionTy {
190 let (type_alias, substitution) = self.build_internal();
191 ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution }
192 }
193}
194
195impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> {
196 fn subst_binders(b: Binders<T>) -> Self {
197 let param_count = b.num_binders;
198 TyBuilder::new(b, param_count)
199 }
200
201 pub fn build(self) -> T {
202 let (b, subst) = self.build_internal();
203 b.subst(&subst)
204 }
205}
206
207impl TyBuilder<Binders<Ty>> {
208 pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> {
209 TyBuilder::subst_binders(db.ty(def.into()))
210 }
211
212 pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> {
213 TyBuilder::subst_binders(db.impl_self_ty(def))
214 }
215
216 pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> {
217 TyBuilder::subst_binders(db.value_ty(def))
218 }
219}
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs
new file mode 100644
index 000000000..b7463366b
--- /dev/null
+++ b/crates/hir_ty/src/chalk_ext.rs
@@ -0,0 +1,13 @@
1//! Various extensions traits for Chalk types.
2
3use crate::{Interner, Ty, TyKind};
4
5pub trait TyExt {
6 fn is_unit(&self) -> bool;
7}
8
9impl TyExt for Ty {
10 fn is_unit(&self) -> bool {
11 matches!(self.kind(&Interner), TyKind::Tuple(0, _))
12 }
13}
diff --git a/crates/hir_ty/src/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
21pub(crate) use hir_def::{ 21pub(crate) use hir_def::{
@@ -423,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
423 None => return, 423 None => return,
424 }; 424 };
425 425
426 if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { 426 if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty {
427 return; 427 return;
428 } 428 }
429 429
diff --git a/crates/hir_ty/src/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
25pub struct HirFormatter<'a> { 25pub 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(&parameters.0[..total_len], ", ")?; 418 f.write_joined(&parameters.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 &parameters.0[0..default_from] 493 &parameters.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;
37use syntax::SmolStr; 37use syntax::SmolStr;
38 38
39use super::{ 39use 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};
43use crate::{ 43use crate::{
44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, 44 db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode,
45 to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, 45 to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind,
46}; 46};
47 47
48// This lint has a false positive here. See the link below for details. 48// This lint has a false positive here. See the link below for details.
@@ -409,16 +409,14 @@ impl<'a> InferenceContext<'a> {
409 _ => panic!("resolve_associated_type called with non-associated type"), 409 _ => panic!("resolve_associated_type called with non-associated type"),
410 }; 410 };
411 let ty = self.table.new_type_var(); 411 let ty = self.table.new_type_var();
412 let substs = Substitution::build_for_def(self.db, res_assoc_ty) 412 let trait_ref = TyBuilder::trait_ref(self.db, trait_)
413 .push(inner_ty) 413 .push(inner_ty)
414 .fill(params.iter().cloned()) 414 .fill(params.iter().cloned())
415 .build(); 415 .build();
416 let trait_ref =
417 TraitRef { trait_id: to_chalk_trait_id(trait_), substitution: substs.clone() };
418 let alias_eq = AliasEq { 416 let alias_eq = AliasEq {
419 alias: AliasTy::Projection(ProjectionTy { 417 alias: AliasTy::Projection(ProjectionTy {
420 associated_ty_id: to_assoc_type_id(res_assoc_ty), 418 associated_ty_id: to_assoc_type_id(res_assoc_ty),
421 substitution: substs, 419 substitution: trait_ref.substitution.clone(),
422 }), 420 }),
423 ty: ty.clone(), 421 ty: ty.clone(),
424 }; 422 };
@@ -489,7 +487,7 @@ impl<'a> InferenceContext<'a> {
489 } 487 }
490 TypeNs::SelfType(impl_id) => { 488 TypeNs::SelfType(impl_id) => {
491 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 489 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
492 let substs = Substitution::type_params_for_generics(self.db, &generics); 490 let substs = generics.type_params_subst(self.db);
493 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 491 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
494 match unresolved { 492 match unresolved {
495 None => { 493 None => {
@@ -516,10 +514,9 @@ impl<'a> InferenceContext<'a> {
516 } 514 }
517 } 515 }
518 TypeNs::TypeAliasId(it) => { 516 TypeNs::TypeAliasId(it) => {
519 let substs = Substitution::build_for_def(self.db, it) 517 let ty = TyBuilder::def_ty(self.db, it.into())
520 .fill(std::iter::repeat_with(|| self.table.new_type_var())) 518 .fill(std::iter::repeat_with(|| self.table.new_type_var()))
521 .build(); 519 .build();
522 let ty = self.db.ty(it.into()).subst(&substs);
523 let variant = ty_variant(&ty); 520 let variant = ty_variant(&ty);
524 forbid_unresolved_segments((ty, variant), unresolved) 521 forbid_unresolved_segments((ty, variant), unresolved)
525 } 522 }
diff --git a/crates/hir_ty/src/infer/coerce.rs b/crates/hir_ty/src/infer/coerce.rs
index d887e21a2..32c273afc 100644
--- a/crates/hir_ty/src/infer/coerce.rs
+++ b/crates/hir_ty/src/infer/coerce.rs
@@ -7,9 +7,7 @@
7use chalk_ir::{cast::Cast, Mutability, TyVariableKind}; 7use chalk_ir::{cast::Cast, Mutability, TyVariableKind};
8use hir_def::lang_item::LangItemTarget; 8use hir_def::lang_item::LangItemTarget;
9 9
10use crate::{ 10use crate::{autoderef, Interner, Solution, Ty, TyBuilder, TyKind};
11 autoderef, to_chalk_trait_id, traits::Solution, Interner, Substitution, TraitRef, Ty, TyKind,
12};
13 11
14use super::{InEnvironment, InferenceContext}; 12use super::{InEnvironment, InferenceContext};
15 13
@@ -44,8 +42,8 @@ impl<'a> InferenceContext<'a> {
44 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916 42 // https://github.com/rust-lang/rust/blob/7b805396bf46dce972692a6846ce2ad8481c5f85/src/librustc_typeck/check/coercion.rs#L877-L916
45 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig"); 43 let sig1 = ty1.callable_sig(self.db).expect("FnDef without callable sig");
46 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig"); 44 let sig2 = ty2.callable_sig(self.db).expect("FnDef without callable sig");
47 let ptr_ty1 = Ty::fn_ptr(sig1); 45 let ptr_ty1 = TyBuilder::fn_ptr(sig1);
48 let ptr_ty2 = Ty::fn_ptr(sig2); 46 let ptr_ty2 = TyBuilder::fn_ptr(sig2);
49 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2) 47 self.coerce_merge_branch(&ptr_ty1, &ptr_ty2)
50 } else { 48 } else {
51 cov_mark::hit!(coerce_merge_fail_fallback); 49 cov_mark::hit!(coerce_merge_fail_fallback);
@@ -95,7 +93,7 @@ impl<'a> InferenceContext<'a> {
95 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) { 93 (TyKind::FnDef(..), TyKind::Function { .. }) => match from_ty.callable_sig(self.db) {
96 None => return false, 94 None => return false,
97 Some(sig) => { 95 Some(sig) => {
98 from_ty = Ty::fn_ptr(sig); 96 from_ty = TyBuilder::fn_ptr(sig);
99 } 97 }
100 }, 98 },
101 99
@@ -130,18 +128,15 @@ impl<'a> InferenceContext<'a> {
130 _ => return None, 128 _ => return None,
131 }; 129 };
132 130
133 let generic_params = crate::utils::generics(self.db.upcast(), coerce_unsized_trait.into()); 131 let trait_ref = {
134 if generic_params.len() != 2 { 132 let b = TyBuilder::trait_ref(self.db, coerce_unsized_trait);
135 // The CoerceUnsized trait should have two generic params: Self and T. 133 if b.remaining() != 2 {
136 return None; 134 // The CoerceUnsized trait should have two generic params: Self and T.
137 } 135 return None;
136 }
137 b.push(from_ty.clone()).push(to_ty.clone()).build()
138 };
138 139
139 let substs = Substitution::build_for_generics(&generic_params)
140 .push(from_ty.clone())
141 .push(to_ty.clone())
142 .build();
143 let trait_ref =
144 TraitRef { trait_id: to_chalk_trait_id(coerce_unsized_trait), substitution: substs };
145 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner)); 140 let goal = InEnvironment::new(self.trait_env.env.clone(), trait_ref.cast(&Interner));
146 141
147 let canonicalizer = self.canonicalizer(); 142 let canonicalizer = self.canonicalizer();
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index dd3914ec3..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
29use super::{ 29use super::{
@@ -73,38 +73,33 @@ impl<'a> InferenceContext<'a> {
73 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?; 73 let fn_once_trait = FnTrait::FnOnce.get_id(self.db, krate)?;
74 let output_assoc_type = 74 let output_assoc_type =
75 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?; 75 self.db.trait_data(fn_once_trait).associated_type_by_name(&name![Output])?;
76 let generic_params = generics(self.db.upcast(), fn_once_trait.into());
77 if generic_params.len() != 2 {
78 return None;
79 }
80 76
81 let mut param_builder = Substitution::builder(num_args);
82 let mut arg_tys = vec![]; 77 let mut arg_tys = vec![];
83 for _ in 0..num_args { 78 let arg_ty = TyBuilder::tuple(num_args)
84 let arg = self.table.new_type_var(); 79 .fill(repeat_with(|| {
85 param_builder = param_builder.push(arg.clone()); 80 let arg = self.table.new_type_var();
86 arg_tys.push(arg); 81 arg_tys.push(arg.clone());
87 } 82 arg
88 let parameters = param_builder.build(); 83 }))
89 let arg_ty = TyKind::Tuple(num_args, parameters).intern(&Interner); 84 .build();
90 let substs = 85
91 Substitution::build_for_generics(&generic_params).push(ty.clone()).push(arg_ty).build(); 86 let projection = {
87 let b = TyBuilder::assoc_type_projection(self.db, output_assoc_type);
88 if b.remaining() != 2 {
89 return None;
90 }
91 b.push(ty.clone()).push(arg_ty).build()
92 };
92 93
93 let trait_env = self.trait_env.env.clone(); 94 let trait_env = self.trait_env.env.clone();
94 let implements_fn_trait: DomainGoal = 95 let obligation = InEnvironment {
95 TraitRef { trait_id: to_chalk_trait_id(fn_once_trait), substitution: substs.clone() } 96 goal: projection.trait_ref(self.db).cast(&Interner),
96 .cast(&Interner);
97 let goal = self.canonicalizer().canonicalize_obligation(InEnvironment {
98 goal: implements_fn_trait.clone(),
99 environment: trait_env, 97 environment: trait_env,
100 }); 98 };
101 if self.db.trait_solve(krate, goal.value).is_some() { 99 let canonical = self.canonicalizer().canonicalize_obligation(obligation.clone());
102 self.push_obligation(implements_fn_trait); 100 if self.db.trait_solve(krate, canonical.value).is_some() {
103 let output_proj_ty = crate::ProjectionTy { 101 self.push_obligation(obligation.goal);
104 associated_ty_id: to_assoc_type_id(output_assoc_type), 102 let return_ty = self.normalize_projection_ty(projection);
105 substitution: substs,
106 };
107 let return_ty = self.normalize_projection_ty(output_proj_ty);
108 Some((arg_tys, return_ty)) 103 Some((arg_tys, return_ty))
109 } else { 104 } else {
110 None 105 None
@@ -138,7 +133,7 @@ impl<'a> InferenceContext<'a> {
138 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe); 133 both_arms_diverge &= mem::replace(&mut self.diverges, Diverges::Maybe);
139 let else_ty = match else_branch { 134 let else_ty = match else_branch {
140 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected), 135 Some(else_branch) => self.infer_expr_inner(*else_branch, &expected),
141 None => Ty::unit(), 136 None => TyBuilder::unit(),
142 }; 137 };
143 both_arms_diverge &= self.diverges; 138 both_arms_diverge &= self.diverges;
144 139
@@ -193,7 +188,7 @@ impl<'a> InferenceContext<'a> {
193 break_ty: self.table.new_type_var(), 188 break_ty: self.table.new_type_var(),
194 label: label.map(|label| self.body[label].name.clone()), 189 label: label.map(|label| self.body[label].name.clone()),
195 }); 190 });
196 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 191 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
197 192
198 let ctxt = self.breakables.pop().expect("breakable stack broken"); 193 let ctxt = self.breakables.pop().expect("breakable stack broken");
199 if ctxt.may_break { 194 if ctxt.may_break {
@@ -217,11 +212,11 @@ impl<'a> InferenceContext<'a> {
217 *condition, 212 *condition,
218 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)), 213 &Expectation::has_type(TyKind::Scalar(Scalar::Bool).intern(&Interner)),
219 ); 214 );
220 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 215 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
221 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 216 let _ctxt = self.breakables.pop().expect("breakable stack broken");
222 // the body may not run, so it diverging doesn't mean we diverge 217 // the body may not run, so it diverging doesn't mean we diverge
223 self.diverges = Diverges::Maybe; 218 self.diverges = Diverges::Maybe;
224 Ty::unit() 219 TyBuilder::unit()
225 } 220 }
226 Expr::For { iterable, body, pat, label } => { 221 Expr::For { iterable, body, pat, label } => {
227 let iterable_ty = self.infer_expr(*iterable, &Expectation::none()); 222 let iterable_ty = self.infer_expr(*iterable, &Expectation::none());
@@ -236,11 +231,11 @@ impl<'a> InferenceContext<'a> {
236 231
237 self.infer_pat(*pat, &pat_ty, BindingMode::default()); 232 self.infer_pat(*pat, &pat_ty, BindingMode::default());
238 233
239 self.infer_expr(*body, &Expectation::has_type(Ty::unit())); 234 self.infer_expr(*body, &Expectation::has_type(TyBuilder::unit()));
240 let _ctxt = self.breakables.pop().expect("breakable stack broken"); 235 let _ctxt = self.breakables.pop().expect("breakable stack broken");
241 // the body may not run, so it diverging doesn't mean we diverge 236 // the body may not run, so it diverging doesn't mean we diverge
242 self.diverges = Diverges::Maybe; 237 self.diverges = Diverges::Maybe;
243 Ty::unit() 238 TyBuilder::unit()
244 } 239 }
245 Expr::Lambda { body, args, ret_type, arg_types } => { 240 Expr::Lambda { body, args, ret_type, arg_types } => {
246 assert_eq!(args.len(), arg_types.len()); 241 assert_eq!(args.len(), arg_types.len());
@@ -360,7 +355,7 @@ impl<'a> InferenceContext<'a> {
360 let val_ty = if let Some(expr) = expr { 355 let val_ty = if let Some(expr) = expr {
361 self.infer_expr(*expr, &Expectation::none()) 356 self.infer_expr(*expr, &Expectation::none())
362 } else { 357 } else {
363 Ty::unit() 358 TyBuilder::unit()
364 }; 359 };
365 360
366 let last_ty = 361 let last_ty =
@@ -386,7 +381,7 @@ impl<'a> InferenceContext<'a> {
386 if let Some(expr) = expr { 381 if let Some(expr) = expr {
387 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone())); 382 self.infer_expr_coerce(*expr, &Expectation::has_type(self.return_ty.clone()));
388 } else { 383 } else {
389 let unit = Ty::unit(); 384 let unit = TyBuilder::unit();
390 self.coerce(&unit, &self.return_ty.clone()); 385 self.coerce(&unit, &self.return_ty.clone());
391 } 386 }
392 TyKind::Never.intern(&Interner) 387 TyKind::Never.intern(&Interner)
@@ -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
14use super::{BindingMode, Expectation, InferenceContext}; 14use super::{BindingMode, Expectation, InferenceContext};
15use crate::{ 15use crate::{
16 lower::lower_to_chalk_mutability, 16 lower::lower_to_chalk_mutability, utils::variant_data, Interner, Substitution, Ty, TyBuilder,
17 utils::{generics, variant_data}, 17 TyKind,
18 Interner, Substitution, Ty, TyKind,
19}; 18};
20 19
21impl<'a> InferenceContext<'a> { 20impl<'a> InferenceContext<'a> {
@@ -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};
11use hir_expand::name::Name; 11use hir_expand::name::Name;
12 12
13use crate::{ 13use crate::{method_resolution, Interner, Substitution, Ty, TyBuilder, TyKind, ValueTyDefId};
14 method_resolution, to_chalk_trait_id, Interner, Substitution, Ty, TyKind, ValueTyDefId,
15};
16 14
17use super::{ExprOrPatId, InferenceContext, TraitRef}; 15use super::{ExprOrPatId, InferenceContext, TraitRef};
18 16
@@ -82,7 +80,7 @@ impl<'a> InferenceContext<'a> {
82 } 80 }
83 ValueNs::ImplSelf(impl_id) => { 81 ValueNs::ImplSelf(impl_id) => {
84 let generics = crate::utils::generics(self.db.upcast(), impl_id.into()); 82 let generics = crate::utils::generics(self.db.upcast(), impl_id.into());
85 let substs = Substitution::type_params_for_generics(self.db, &generics); 83 let substs = generics.type_params_subst(self.db);
86 let ty = self.db.impl_self_ty(impl_id).subst(&substs); 84 let ty = self.db.impl_self_ty(impl_id).subst(&substs);
87 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() { 85 if let Some((AdtId::StructId(struct_id), substs)) = ty.as_adt() {
88 let ty = self.db.value_ty(struct_id.into()).subst(&substs); 86 let ty = self.db.value_ty(struct_id.into()).subst(&substs);
@@ -95,16 +93,13 @@ impl<'a> InferenceContext<'a> {
95 ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)), 93 ValueNs::GenericParam(it) => return Some(self.db.const_param_ty(it)),
96 }; 94 };
97 95
98 let ty = self.db.value_ty(typable);
99 // self_subst is just for the parent
100 let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner)); 96 let parent_substs = self_subst.unwrap_or_else(|| Substitution::empty(&Interner));
101 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver); 97 let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver);
102 let substs = ctx.substs_from_path(path, typable, true); 98 let substs = ctx.substs_from_path(path, typable, true);
103 let full_substs = Substitution::builder(substs.len(&Interner)) 99 let ty = TyBuilder::value_ty(self.db, typable)
104 .use_parent_substs(&parent_substs) 100 .use_parent_substs(&parent_substs)
105 .fill(substs.interned(&Interner)[parent_substs.len(&Interner)..].iter().cloned()) 101 .fill(substs.interned()[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;
14pub(crate) mod infer; 14pub(crate) mod infer;
15pub(crate) mod utils; 15pub(crate) mod utils;
16mod chalk_cast; 16mod chalk_cast;
17mod chalk_ext;
18mod builder;
19mod walk;
20mod types;
17 21
18pub mod display; 22pub mod display;
19pub mod db; 23pub mod db;
@@ -24,30 +28,30 @@ mod tests;
24#[cfg(test)] 28#[cfg(test)]
25mod test_db; 29mod test_db;
26 30
27use std::{iter, mem, sync::Arc}; 31use std::sync::Arc;
28 32
29use base_db::salsa;
30use chalk_ir::cast::{CastTo, Caster};
31use hir_def::{
32 builtin_type::BuiltinType, expr::ExprId, type_ref::Rawness, AssocContainerId, FunctionId,
33 GenericDefId, HasModule, LifetimeParamId, Lookup, TraitId, TypeAliasId, TypeParamId,
34};
35use itertools::Itertools; 33use itertools::Itertools;
36use smallvec::SmallVec; 34use smallvec::SmallVec;
37 35
38use crate::{ 36use base_db::salsa;
39 db::HirDatabase, 37use 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
42use crate::{db::HirDatabase, display::HirDisplay, utils::generics};
43
44pub use autoderef::autoderef; 44pub use autoderef::autoderef;
45pub use builder::TyBuilder;
46pub use chalk_ext::TyExt;
45pub use infer::{could_unify, InferenceResult, InferenceVar}; 47pub use infer::{could_unify, InferenceResult, InferenceVar};
46pub use lower::{ 48pub 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};
50pub use traits::{AliasEq, DomainGoal, InEnvironment, TraitEnvironment}; 52pub use traits::TraitEnvironment;
53pub use types::*;
54pub use walk::TypeWalk;
51 55
52pub use chalk_ir::{ 56pub 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
67pub type ChalkTraitId = chalk_ir::TraitId<Interner>; 71pub type ChalkTraitId = chalk_ir::TraitId<Interner>;
68 72
69#[derive(Clone, PartialEq, Eq, Debug, Hash)]
70pub enum Lifetime {
71 Parameter(LifetimeParamId),
72 Static,
73}
74
75#[derive(Clone, PartialEq, Eq, Debug, Hash)]
76pub struct OpaqueTy {
77 pub opaque_ty_id: OpaqueTyId,
78 pub substitution: Substitution,
79}
80
81impl 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)]
99pub struct ProjectionTy {
100 pub associated_ty_id: AssocTypeId,
101 pub substitution: Substitution,
102}
103
104impl ProjectionTy { 73impl 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
124impl 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)]
139pub struct DynTy {
140 /// The unknown self type.
141 pub bounds: Binders<QuantifiedWhereClauses>,
142}
143
144pub type FnSig = chalk_ir::FnSig<Interner>; 93pub type FnSig = chalk_ir::FnSig<Interner>;
145 94
146#[derive(Clone, PartialEq, Eq, Debug, Hash)]
147pub struct FnPointer {
148 pub num_args: usize,
149 pub sig: FnSig,
150 pub substs: Substitution,
151}
152
153#[derive(Clone, PartialEq, Eq, Debug, Hash)]
154pub 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
166impl 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)]
192pub 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)]
306pub struct Ty(Arc<TyKind>);
307
308impl TyKind {
309 pub fn intern(self, _interner: &Interner) -> Ty {
310 Ty(Arc::new(self))
311 }
312}
313
314impl 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)]
329pub struct GenericArg {
330 interned: GenericArgData,
331}
332
333#[derive(Clone, PartialEq, Eq, Debug, Hash)]
334pub enum GenericArgData {
335 Ty(Ty),
336}
337
338impl 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
369impl 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)]
393pub struct Substitution(SmallVec<[GenericArg; 2]>);
394
395impl 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
413impl Substitution { 95impl 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, &params)
478 }
479
480 /// Return Substs that replace each parameter by a bound variable.
481 pub(crate) fn bound_vars(generic_params: &Generics, debruijn: DebruijnIndex) -> Substitution {
482 Substitution::from_iter(
483 &Interner,
484 generic_params
485 .iter()
486 .enumerate()
487 .map(|(idx, _)| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
488 ) 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)]
513pub struct SubstsBuilder {
514 vec: Vec<GenericArg>,
515 param_count: usize,
516}
517
518impl SubstsBuilder {
519 pub fn build(self) -> Substitution {
520 assert_eq!(self.vec.len(), self.param_count);
521 Substitution::from_iter(&Interner, self.vec)
522 }
523
524 pub fn push(mut self, ty: impl CastTo<GenericArg>) -> Self {
525 self.vec.push(ty.cast(&Interner));
526 self
527 }
528
529 fn remaining(&self) -> usize {
530 self.param_count - self.vec.len()
531 }
532
533 pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self {
534 self.fill(
535 (starting_from..)
536 .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)),
537 )
538 }
539
540 pub fn fill_with_unknown(self) -> Self {
541 self.fill(iter::repeat(TyKind::Unknown.intern(&Interner)))
542 }
543
544 pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self {
545 self.vec.extend(filler.take(self.remaining()).casted(&Interner));
546 assert_eq!(self.remaining(), 0);
547 self
548 }
549
550 pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self {
551 assert!(self.vec.is_empty());
552 assert!(parent_substs.len(&Interner) <= self.param_count);
553 self.vec.extend(parent_substs.iter(&Interner).cloned());
554 self
555 }
556}
557
558#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
559pub struct Binders<T> {
560 pub num_binders: usize,
561 pub value: T,
562}
563
564impl<T> Binders<T> { 120impl<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
611impl<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)]
627pub struct TraitRef {
628 pub trait_id: ChalkTraitId,
629 pub substitution: Substitution,
630}
631
632impl TraitRef { 167impl 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
642impl 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)]
659pub 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
666impl WhereClause { 177impl 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
682impl 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
702pub type QuantifiedWhereClause = Binders<WhereClause>;
703
704#[derive(Debug, Clone, PartialEq, Eq, Hash)]
705pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
706
707impl 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)]
727pub struct Canonical<T> {
728 pub value: T,
729 pub binders: CanonicalVarKinds,
730}
731
732impl<T> Canonical<T> { 193impl<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
795impl 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
813impl Ty { 246impl 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.
1119pub 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
1232impl 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
1294impl<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)]
1312pub enum ImplTraitId { 517pub 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.
1062fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> { 1054fn type_for_fn(db: &dyn HirDatabase, def: FunctionId) -> Binders<Ty> {
1063 let generics = generics(db.upcast(), def.into()); 1055 let generics = generics(db.upcast(), def.into());
1064 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1056 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1065 Binders::new( 1057 Binders::new(
1066 substs.len(&Interner), 1058 substs.len(&Interner),
1067 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner), 1059 TyKind::FnDef(CallableDefId::FunctionId(def).to_chalk(db), substs).intern(&Interner),
@@ -1106,7 +1098,7 @@ fn type_for_struct_constructor(db: &dyn HirDatabase, def: StructId) -> Binders<T
1106 return type_for_adt(db, def.into()); 1098 return type_for_adt(db, def.into());
1107 } 1099 }
1108 let generics = generics(db.upcast(), def.into()); 1100 let generics = generics(db.upcast(), def.into());
1109 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1101 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1110 Binders::new( 1102 Binders::new(
1111 substs.len(&Interner), 1103 substs.len(&Interner),
1112 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner), 1104 TyKind::FnDef(CallableDefId::StructId(def).to_chalk(db), substs).intern(&Interner),
@@ -1133,7 +1125,7 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1133 return type_for_adt(db, def.parent.into()); 1125 return type_for_adt(db, def.parent.into());
1134 } 1126 }
1135 let generics = generics(db.upcast(), def.parent.into()); 1127 let generics = generics(db.upcast(), def.parent.into());
1136 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1128 let substs = generics.bound_vars_subst(DebruijnIndex::INNERMOST);
1137 Binders::new( 1129 Binders::new(
1138 substs.len(&Interner), 1130 substs.len(&Interner),
1139 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner), 1131 TyKind::FnDef(CallableDefId::EnumVariantId(def).to_chalk(db), substs).intern(&Interner),
@@ -1141,9 +1133,10 @@ fn type_for_enum_variant_constructor(db: &dyn HirDatabase, def: EnumVariantId) -
1141} 1133}
1142 1134
1143fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> { 1135fn type_for_adt(db: &dyn HirDatabase, adt: AdtId) -> Binders<Ty> {
1144 let generics = generics(db.upcast(), adt.into()); 1136 let b = TyBuilder::adt(db, adt);
1145 let substs = Substitution::bound_vars(&generics, DebruijnIndex::INNERMOST); 1137 let num_binders = b.remaining();
1146 Binders::new(substs.len(&Interner), Ty::adt_ty(adt, substs)) 1138 let ty = b.fill_with_bound_vars(DebruijnIndex::INNERMOST, 0).build();
1139 Binders::new(num_binders, ty)
1147} 1140}
1148 1141
1149fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> { 1142fn type_for_type_alias(db: &dyn HirDatabase, t: TypeAliasId) -> Binders<Ty> {
@@ -1215,7 +1208,7 @@ impl_from!(FunctionId, StructId, UnionId, EnumVariantId, ConstId, StaticId for V
1215/// namespace. 1208/// namespace.
1216pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> { 1209pub(crate) fn ty_query(db: &dyn HirDatabase, def: TyDefId) -> Binders<Ty> {
1217 match def { 1210 match def {
1218 TyDefId::BuiltinType(it) => Binders::new(0, Ty::builtin(it)), 1211 TyDefId::BuiltinType(it) => Binders::new(0, TyBuilder::builtin(it)),
1219 TyDefId::AdtId(it) => type_for_adt(db, it), 1212 TyDefId::AdtId(it) => type_for_adt(db, it),
1220 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it), 1213 TyDefId::TypeAliasId(it) => type_for_type_alias(db, it),
1221 } 1214 }
diff --git a/crates/hir_ty/src/method_resolution.rs b/crates/hir_ty/src/method_resolution.rs
index 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 @@
2use chalk_ir::TyVariableKind; 2use chalk_ir::TyVariableKind;
3use hir_def::expr::{ArithOp, BinaryOp, CmpOp}; 3use hir_def::expr::{ArithOp, BinaryOp, CmpOp};
4 4
5use crate::{Interner, Scalar, Ty, TyKind}; 5use crate::{Interner, Scalar, Ty, TyBuilder, TyKind};
6 6
7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty { 7pub(super) fn binary_op_return_ty(op: BinaryOp, lhs_ty: Ty, rhs_ty: Ty) -> Ty {
8 match op { 8 match op {
9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner), 9 BinaryOp::LogicOp(_) | BinaryOp::CmpOp(_) => TyKind::Scalar(Scalar::Bool).intern(&Interner),
10 BinaryOp::Assignment { .. } => Ty::unit(), 10 BinaryOp::Assignment { .. } => TyBuilder::unit(),
11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => { 11 BinaryOp::ArithOp(ArithOp::Shl) | BinaryOp::ArithOp(ArithOp::Shr) => {
12 match lhs_ty.kind(&Interner) { 12 match lhs_ty.kind(&Interner) {
13 TyKind::Scalar(Scalar::Int(_)) 13 TyKind::Scalar(Scalar::Int(_))
diff --git a/crates/hir_ty/src/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};
8use stdx::panic_context; 8use stdx::panic_context;
9 9
10use crate::{ 10use 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
15use self::chalk::{from_chalk, Interner, ToChalk}; 15use 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)]
75pub struct InEnvironment<T> {
76 pub environment: chalk_ir::Environment<Interner>,
77 pub goal: T,
78}
79
80impl<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)]
90pub enum DomainGoal {
91 Holds(WhereClause),
92}
93
94#[derive(Clone, Debug, PartialEq, Eq, Hash)]
95pub struct AliasEq {
96 pub alias: AliasTy,
97 pub ty: Ty,
98}
99
100impl 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.
123pub(crate) fn trait_solve_query( 74pub(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)]
250pub struct SolutionVariables(pub Canonical<Substitution>);
251
252#[derive(Clone, Debug, PartialEq, Eq)]
253/// A (possible) solution for a proposed goal.
254pub 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.
269pub 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)]
285pub enum FnTrait { 201pub 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};
27use mapping::{ 27use mapping::{
28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue, 28 convert_where_clauses, generic_predicate_to_inline_bound, make_binders, TypeAliasAsValue,
@@ -300,7 +300,7 @@ impl<'a> chalk_solve::RustIrDatabase<Interner> for ChalkContext<'a> {
300 _closure_id: chalk_ir::ClosureId<Interner>, 300 _closure_id: chalk_ir::ClosureId<Interner>,
301 _substs: &chalk_ir::Substitution<Interner>, 301 _substs: &chalk_ir::Substitution<Interner>,
302 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> { 302 ) -> chalk_ir::Binders<chalk_ir::Ty<Interner>> {
303 let ty = Ty::unit().to_chalk(self.db); 303 let ty = TyBuilder::unit().to_chalk(self.db);
304 make_binders(ty, 0) 304 make_binders(ty, 0)
305 } 305 }
306 fn closure_fn_substitution( 306 fn closure_fn_substitution(
@@ -387,7 +387,7 @@ pub(crate) fn associated_ty_data_query(
387 // Lower bounds -- we could/should maybe move this to a separate query in `lower` 387 // Lower bounds -- we could/should maybe move this to a separate query in `lower`
388 let type_alias_data = db.type_alias_data(type_alias); 388 let type_alias_data = db.type_alias_data(type_alias);
389 let generic_params = generics(db.upcast(), type_alias.into()); 389 let generic_params = generics(db.upcast(), type_alias.into());
390 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 390 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast()); 391 let resolver = hir_def::resolver::HasResolver::resolver(type_alias, db.upcast());
392 let ctx = crate::TyLoweringContext::new(db, &resolver) 392 let ctx = crate::TyLoweringContext::new(db, &resolver)
393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable); 393 .with_type_param_mode(crate::lower::TypeParamLoweringMode::Variable);
@@ -421,7 +421,7 @@ pub(crate) fn trait_datum_query(
421 let trait_data = db.trait_data(trait_); 421 let trait_data = db.trait_data(trait_);
422 debug!("trait {:?} = {:?}", trait_id, trait_data.name); 422 debug!("trait {:?} = {:?}", trait_id, trait_data.name);
423 let generic_params = generics(db.upcast(), trait_.into()); 423 let generic_params = generics(db.upcast(), trait_.into());
424 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 424 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
425 let flags = rust_ir::TraitFlags { 425 let flags = rust_ir::TraitFlags {
426 auto: trait_data.is_auto, 426 auto: trait_data.is_auto,
427 upstream: trait_.lookup(db.upcast()).container.krate() != krate, 427 upstream: trait_.lookup(db.upcast()).container.krate() != krate,
@@ -490,7 +490,7 @@ pub(crate) fn struct_datum_query(
490 let upstream = adt_id.module(db.upcast()).krate() != krate; 490 let upstream = adt_id.module(db.upcast()).krate() != krate;
491 let where_clauses = { 491 let where_clauses = {
492 let generic_params = generics(db.upcast(), adt_id.into()); 492 let generic_params = generics(db.upcast(), adt_id.into());
493 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 493 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
494 convert_where_clauses(db, adt_id.into(), &bound_vars) 494 convert_where_clauses(db, adt_id.into(), &bound_vars)
495 }; 495 };
496 let flags = rust_ir::AdtFlags { 496 let flags = rust_ir::AdtFlags {
@@ -539,7 +539,7 @@ fn impl_def_datum(
539 let impl_data = db.impl_data(impl_id); 539 let impl_data = db.impl_data(impl_id);
540 540
541 let generic_params = generics(db.upcast(), impl_id.into()); 541 let generic_params = generics(db.upcast(), impl_id.into());
542 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 542 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
543 let trait_ = trait_ref.hir_trait_id(); 543 let trait_ = trait_ref.hir_trait_id();
544 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate { 544 let impl_type = if impl_id.lookup(db.upcast()).container.krate() == krate {
545 rust_ir::ImplType::Local 545 rust_ir::ImplType::Local
@@ -629,7 +629,7 @@ pub(crate) fn fn_def_datum_query(
629 let callable_def: CallableDefId = from_chalk(db, fn_def_id); 629 let callable_def: CallableDefId = from_chalk(db, fn_def_id);
630 let generic_params = generics(db.upcast(), callable_def.into()); 630 let generic_params = generics(db.upcast(), callable_def.into());
631 let sig = db.callable_item_signature(callable_def); 631 let sig = db.callable_item_signature(callable_def);
632 let bound_vars = Substitution::bound_vars(&generic_params, DebruijnIndex::INNERMOST); 632 let bound_vars = generic_params.bound_vars_subst(DebruijnIndex::INNERMOST);
633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars); 633 let where_clauses = convert_where_clauses(db, callable_def.into(), &bound_vars);
634 let bound = rust_ir::FnDefDatumBound { 634 let bound = rust_ir::FnDefDatumBound {
635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway 635 // Note: Chalk doesn't actually use this information yet as far as I am aware, but we provide it anyway
diff --git a/crates/hir_ty/src/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;
10use hir_def::{GenericDefId, TypeAliasId}; 10use hir_def::{GenericDefId, TypeAliasId};
11 11
12use crate::{ 12use 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
20use super::interner::*; 18use 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
4use std::sync::Arc;
5
6use chalk_ir::{
7 cast::{CastTo, Caster},
8 BoundVar, Mutability, Scalar, TyVariableKind,
9};
10use hir_def::LifetimeParamId;
11use smallvec::SmallVec;
12
13use crate::{
14 AssocTypeId, CanonicalVarKinds, ChalkTraitId, ClosureId, FnDefId, FnSig, ForeignDefId,
15 InferenceVar, Interner, OpaqueTyId, PlaceholderIndex,
16};
17
18#[derive(Clone, PartialEq, Eq, Debug, Hash)]
19pub enum Lifetime {
20 Parameter(LifetimeParamId),
21 Static,
22}
23
24#[derive(Clone, PartialEq, Eq, Debug, Hash)]
25pub 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)]
34pub struct ProjectionTy {
35 pub associated_ty_id: AssocTypeId,
36 pub substitution: Substitution,
37}
38
39#[derive(Clone, PartialEq, Eq, Debug, Hash)]
40pub struct DynTy {
41 /// The unknown self type.
42 pub bounds: Binders<QuantifiedWhereClauses>,
43}
44
45#[derive(Clone, PartialEq, Eq, Debug, Hash)]
46pub struct FnPointer {
47 pub num_args: usize,
48 pub sig: FnSig,
49 pub substs: Substitution,
50}
51
52#[derive(Clone, PartialEq, Eq, Debug, Hash)]
53pub 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)]
72pub 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)]
186pub struct Ty(Arc<TyKind>);
187
188impl TyKind {
189 pub fn intern(self, _interner: &Interner) -> Ty {
190 Ty(Arc::new(self))
191 }
192}
193
194impl 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)]
209pub struct GenericArg {
210 interned: GenericArgData,
211}
212
213#[derive(Clone, PartialEq, Eq, Debug, Hash)]
214pub enum GenericArgData {
215 Ty(Ty),
216}
217
218impl 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)]
255pub struct Substitution(SmallVec<[GenericArg; 2]>);
256
257impl 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)]
300pub 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)]
307pub 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)]
315pub 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
322pub type QuantifiedWhereClause = Binders<WhereClause>;
323
324#[derive(Debug, Clone, PartialEq, Eq, Hash)]
325pub struct QuantifiedWhereClauses(Arc<[QuantifiedWhereClause]>);
326
327impl 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)]
351pub 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)]
358pub struct InEnvironment<T> {
359 pub environment: chalk_ir::Environment<Interner>,
360 pub goal: T,
361}
362
363impl<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)]
373pub enum DomainGoal {
374 Holds(WhereClause),
375}
376
377#[derive(Clone, Debug, PartialEq, Eq, Hash)]
378pub struct AliasEq {
379 pub alias: AliasTy,
380 pub ty: Ty,
381}
382
383#[derive(Clone, Debug, PartialEq, Eq)]
384pub struct SolutionVariables(pub Canonical<Substitution>);
385
386#[derive(Clone, Debug, PartialEq, Eq)]
387/// A (possible) solution for a proposed goal.
388pub 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.
403pub 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`).
3use std::sync::Arc; 3use std::sync::Arc;
4 4
5use chalk_ir::DebruijnIndex; 5use chalk_ir::{BoundVar, DebruijnIndex};
6use hir_def::{ 6use hir_def::{
7 adt::VariantData, 7 adt::VariantData,
8 db::DefDatabase, 8 db::DefDatabase,
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};
17use hir_expand::name::{name, Name}; 18use hir_expand::name::{name, Name};
18 19
19use crate::{db::HirDatabase, TraitRef, TypeWalk, WhereClause}; 20use crate::{db::HirDatabase, Interner, Substitution, TraitRef, TyKind, TypeWalk, WhereClause};
20 21
21fn direct_super_traits(db: &dyn DefDatabase, trait_: TraitId) -> Vec<TraitId> { 22fn 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)]
160pub(crate) struct Generics { 160pub(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
254fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> { 274fn parent_generic_def(db: &dyn DefDatabase, def: GenericDefId) -> Option<GenericDefId> {
diff --git a/crates/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
4use std::mem;
5
6use chalk_ir::DebruijnIndex;
7
8use 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.
15pub 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
128impl 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
190impl<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
207impl 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
221impl 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
235impl 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
255impl 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
277impl 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
295impl<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
309impl 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
323impl 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
343impl 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
361impl 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 @@
1use ide_db::{
2 helpers::{mod_path_to_ast, FamousDefs},
3 traits::resolve_target_trait,
4};
5use syntax::ast::{self, AstNode, NameOwner};
6
7use crate::{AssistContext, AssistId, AssistKind, Assists};
8
9// Assist: convert_into_to_from
10//
11// Converts an Into impl to an equivalent From impl.
12//
13// ```
14// # //- /lib.rs crate:core
15// # pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
16// # //- /lib.rs crate:main deps:core
17// # use core::convert::Into;
18// impl $0Into<Thing> for usize {
19// fn into(self) -> Thing {
20// Thing {
21// b: self.to_string(),
22// a: self
23// }
24// }
25// }
26// ```
27// ->
28// ```
29// # use core::convert::Into;
30// impl From<usize> for Thing {
31// fn from(val: usize) -> Self {
32// Thing {
33// b: val.to_string(),
34// a: val
35// }
36// }
37// }
38// ```
39pub(crate) fn convert_into_to_from(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
40 let impl_ = ctx.find_node_at_offset::<ast::Impl>()?;
41 let src_type = impl_.self_ty()?;
42 let ast_trait = impl_.trait_()?;
43
44 let module = ctx.sema.scope(impl_.syntax()).module()?;
45
46 let trait_ = resolve_target_trait(&ctx.sema, &impl_)?;
47 if trait_ != FamousDefs(&ctx.sema, Some(module.krate())).core_convert_Into()? {
48 return None;
49 }
50
51 let src_type_path = {
52 let src_type_path = src_type.syntax().descendants().find_map(ast::Path::cast)?;
53 let src_type_def = match ctx.sema.resolve_path(&src_type_path) {
54 Some(hir::PathResolution::Def(module_def)) => module_def,
55 _ => return None,
56 };
57
58 mod_path_to_ast(&module.find_use_path(ctx.db(), src_type_def)?)
59 };
60
61 let dest_type = match &ast_trait {
62 ast::Type::PathType(path) => {
63 path.path()?.segment()?.generic_arg_list()?.generic_args().next()?
64 }
65 _ => return None,
66 };
67
68 let into_fn = impl_.assoc_item_list()?.assoc_items().find_map(|item| {
69 if let ast::AssocItem::Fn(f) = item {
70 if f.name()?.text() == "into" {
71 return Some(f);
72 }
73 };
74 None
75 })?;
76
77 let into_fn_name = into_fn.name()?;
78 let into_fn_params = into_fn.param_list()?;
79 let into_fn_return = into_fn.ret_type()?;
80
81 let selfs = into_fn
82 .body()?
83 .syntax()
84 .descendants()
85 .filter_map(ast::NameRef::cast)
86 .filter(|name| name.text() == "self" || name.text() == "Self");
87
88 acc.add(
89 AssistId("convert_into_to_from", AssistKind::RefactorRewrite),
90 "Convert Into to From",
91 impl_.syntax().text_range(),
92 |builder| {
93 builder.replace(src_type.syntax().text_range(), dest_type.to_string());
94 builder.replace(ast_trait.syntax().text_range(), format!("From<{}>", src_type));
95 builder.replace(into_fn_return.syntax().text_range(), "-> Self");
96 builder.replace(
97 into_fn_params.syntax().text_range(),
98 format!("(val: {})", src_type.to_string()),
99 );
100 builder.replace(into_fn_name.syntax().text_range(), "from");
101
102 for s in selfs {
103 match s.text().as_ref() {
104 "self" => builder.replace(s.syntax().text_range(), "val"),
105 "Self" => builder.replace(s.syntax().text_range(), src_type_path.to_string()),
106 _ => {}
107 }
108 }
109 },
110 )
111}
112
113#[cfg(test)]
114mod tests {
115 use super::*;
116
117 use crate::tests::check_assist;
118
119 #[test]
120 fn convert_into_to_from_converts_a_struct() {
121 check_convert_into_to_from(
122 r#"
123struct Thing {
124 a: String,
125 b: usize
126}
127
128impl $0core::convert::Into<Thing> for usize {
129 fn into(self) -> Thing {
130 Thing {
131 b: self.to_string(),
132 a: self
133 }
134 }
135}
136"#,
137 r#"
138struct Thing {
139 a: String,
140 b: usize
141}
142
143impl From<usize> for Thing {
144 fn from(val: usize) -> Self {
145 Thing {
146 b: val.to_string(),
147 a: val
148 }
149 }
150}
151"#,
152 )
153 }
154
155 #[test]
156 fn convert_into_to_from_converts_enums() {
157 check_convert_into_to_from(
158 r#"
159enum Thing {
160 Foo(String),
161 Bar(String)
162}
163
164impl $0core::convert::Into<String> for Thing {
165 fn into(self) -> String {
166 match self {
167 Self::Foo(s) => s,
168 Self::Bar(s) => s
169 }
170 }
171}
172"#,
173 r#"
174enum Thing {
175 Foo(String),
176 Bar(String)
177}
178
179impl From<Thing> for String {
180 fn from(val: Thing) -> Self {
181 match val {
182 Thing::Foo(s) => s,
183 Thing::Bar(s) => s
184 }
185 }
186}
187"#,
188 )
189 }
190
191 #[test]
192 fn convert_into_to_from_on_enum_with_lifetimes() {
193 check_convert_into_to_from(
194 r#"
195enum Thing<'a> {
196 Foo(&'a str),
197 Bar(&'a str)
198}
199
200impl<'a> $0core::convert::Into<&'a str> for Thing<'a> {
201 fn into(self) -> &'a str {
202 match self {
203 Self::Foo(s) => s,
204 Self::Bar(s) => s
205 }
206 }
207}
208"#,
209 r#"
210enum Thing<'a> {
211 Foo(&'a str),
212 Bar(&'a str)
213}
214
215impl<'a> From<Thing<'a>> for &'a str {
216 fn from(val: Thing<'a>) -> Self {
217 match val {
218 Thing::Foo(s) => s,
219 Thing::Bar(s) => s
220 }
221 }
222}
223"#,
224 )
225 }
226
227 #[test]
228 fn convert_into_to_from_works_on_references() {
229 check_convert_into_to_from(
230 r#"
231struct Thing(String);
232
233impl $0core::convert::Into<String> for &Thing {
234 fn into(self) -> Thing {
235 self.0.clone()
236 }
237}
238"#,
239 r#"
240struct Thing(String);
241
242impl From<&Thing> for String {
243 fn from(val: &Thing) -> Self {
244 val.0.clone()
245 }
246}
247"#,
248 )
249 }
250
251 #[test]
252 fn convert_into_to_from_works_on_qualified_structs() {
253 check_convert_into_to_from(
254 r#"
255mod things {
256 pub struct Thing(String);
257 pub struct BetterThing(String);
258}
259
260impl $0core::convert::Into<things::BetterThing> for &things::Thing {
261 fn into(self) -> Thing {
262 things::BetterThing(self.0.clone())
263 }
264}
265"#,
266 r#"
267mod things {
268 pub struct Thing(String);
269 pub struct BetterThing(String);
270}
271
272impl From<&things::Thing> for things::BetterThing {
273 fn from(val: &things::Thing) -> Self {
274 things::BetterThing(val.0.clone())
275 }
276}
277"#,
278 )
279 }
280
281 #[test]
282 fn convert_into_to_from_works_on_qualified_enums() {
283 check_convert_into_to_from(
284 r#"
285mod things {
286 pub enum Thing {
287 A(String)
288 }
289 pub struct BetterThing {
290 B(String)
291 }
292}
293
294impl $0core::convert::Into<things::BetterThing> for &things::Thing {
295 fn into(self) -> Thing {
296 match self {
297 Self::A(s) => things::BetterThing::B(s)
298 }
299 }
300}
301"#,
302 r#"
303mod things {
304 pub enum Thing {
305 A(String)
306 }
307 pub struct BetterThing {
308 B(String)
309 }
310}
311
312impl From<&things::Thing> for things::BetterThing {
313 fn from(val: &things::Thing) -> Self {
314 match val {
315 things::Thing::A(s) => things::BetterThing::B(s)
316 }
317 }
318}
319"#,
320 )
321 }
322
323 #[test]
324 fn convert_into_to_from_not_applicable_on_any_trait_named_into() {
325 check_assist_not_applicable(
326 r#"
327pub trait Into<T> {{
328 pub fn into(self) -> T;
329}}
330
331struct Thing {
332 a: String,
333}
334
335impl $0Into<Thing> for String {
336 fn into(self) -> Thing {
337 Thing {
338 a: self
339 }
340 }
341}
342"#,
343 );
344 }
345
346 fn check_convert_into_to_from(before: &str, after: &str) {
347 let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
348 check_assist(convert_into_to_from, before, after);
349 }
350
351 fn check_assist_not_applicable(before: &str) {
352 let before = &format!("//- /main.rs crate:main deps:core{}{}", before, FamousDefs::FIXTURE);
353 crate::tests::check_assist_not_applicable(convert_into_to_from, before);
354 }
355}
diff --git a/crates/ide_assists/src/lib.rs b/crates/ide_assists/src/lib.rs
index 3d1dcef4c..3e2c82dac 100644
--- a/crates/ide_assists/src/lib.rs
+++ b/crates/ide_assists/src/lib.rs
@@ -117,6 +117,7 @@ mod handlers {
117 mod convert_integer_literal; 117 mod convert_integer_literal;
118 mod convert_comment_block; 118 mod convert_comment_block;
119 mod convert_iter_for_each_to_for; 119 mod convert_iter_for_each_to_for;
120 mod convert_into_to_from;
120 mod early_return; 121 mod early_return;
121 mod expand_glob_import; 122 mod expand_glob_import;
122 mod extract_function; 123 mod extract_function;
@@ -185,6 +186,7 @@ mod handlers {
185 convert_integer_literal::convert_integer_literal, 186 convert_integer_literal::convert_integer_literal,
186 convert_comment_block::convert_comment_block, 187 convert_comment_block::convert_comment_block,
187 convert_iter_for_each_to_for::convert_iter_for_each_to_for, 188 convert_iter_for_each_to_for::convert_iter_for_each_to_for,
189 convert_into_to_from::convert_into_to_from,
188 early_return::convert_to_guarded_return, 190 early_return::convert_to_guarded_return,
189 expand_glob_import::expand_glob_import, 191 expand_glob_import::expand_glob_import,
190 extract_struct_from_enum_variant::extract_struct_from_enum_variant, 192 extract_struct_from_enum_variant::extract_struct_from_enum_variant,
diff --git a/crates/ide_assists/src/tests/generated.rs b/crates/ide_assists/src/tests/generated.rs
index 03b7fb366..27a22ca10 100644
--- a/crates/ide_assists/src/tests/generated.rs
+++ b/crates/ide_assists/src/tests/generated.rs
@@ -206,6 +206,38 @@ const _: i32 = 0b1010;
206} 206}
207 207
208#[test] 208#[test]
209fn doctest_convert_into_to_from() {
210 check_doc_test(
211 "convert_into_to_from",
212 r#####"
213//- /lib.rs crate:core
214pub mod convert { pub trait Into<T> { pub fn into(self) -> T; } }
215//- /lib.rs crate:main deps:core
216use core::convert::Into;
217impl $0Into<Thing> for usize {
218 fn into(self) -> Thing {
219 Thing {
220 b: self.to_string(),
221 a: self
222 }
223 }
224}
225"#####,
226 r#####"
227use core::convert::Into;
228impl From<usize> for Thing {
229 fn from(val: usize) -> Self {
230 Thing {
231 b: val.to_string(),
232 a: val
233 }
234 }
235}
236"#####,
237 )
238}
239
240#[test]
209fn doctest_convert_iter_for_each_to_for() { 241fn doctest_convert_iter_for_each_to_for() {
210 check_doc_test( 242 check_doc_test(
211 "convert_iter_for_each_to_for", 243 "convert_iter_for_each_to_for",
diff --git a/crates/ide_db/src/helpers.rs b/crates/ide_db/src/helpers.rs
index 9992a92bd..66798ea3a 100644
--- a/crates/ide_db/src/helpers.rs
+++ b/crates/ide_db/src/helpers.rs
@@ -93,6 +93,10 @@ impl FamousDefs<'_, '_> {
93 self.find_trait("core:convert:From") 93 self.find_trait("core:convert:From")
94 } 94 }
95 95
96 pub fn core_convert_Into(&self) -> Option<Trait> {
97 self.find_trait("core:convert:Into")
98 }
99
96 pub fn core_option_Option(&self) -> Option<Enum> { 100 pub fn core_option_Option(&self) -> Option<Enum> {
97 self.find_enum("core:option:Option") 101 self.find_enum("core:option:Option")
98 } 102 }
diff --git a/crates/ide_db/src/helpers/famous_defs_fixture.rs b/crates/ide_db/src/helpers/famous_defs_fixture.rs
index d3464ae17..4d79e064e 100644
--- a/crates/ide_db/src/helpers/famous_defs_fixture.rs
+++ b/crates/ide_db/src/helpers/famous_defs_fixture.rs
@@ -14,6 +14,10 @@ pub mod convert {
14 pub trait From<T> { 14 pub trait From<T> {
15 fn from(t: T) -> Self; 15 fn from(t: T) -> Self;
16 } 16 }
17
18 pub trait Into<T> {
19 pub fn into(self) -> T;
20 }
17} 21}
18 22
19pub mod default { 23pub mod default {
@@ -120,7 +124,7 @@ pub mod option {
120pub mod prelude { 124pub mod prelude {
121 pub use crate::{ 125 pub use crate::{
122 cmp::Ord, 126 cmp::Ord,
123 convert::From, 127 convert::{From, Into},
124 default::Default, 128 default::Default,
125 iter::{IntoIterator, Iterator}, 129 iter::{IntoIterator, Iterator},
126 ops::{Fn, FnMut, FnOnce}, 130 ops::{Fn, FnMut, FnOnce},
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(&macro_definition.token_tree().unwrap());
163 ast_to_token_tree(&macro_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(&macro_invocation.token_tree().unwrap());
173 ast_to_token_tree(&macro_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).
46pub fn ast_to_token_tree(ast: &impl ast::AstNode) -> Option<(tt::Subtree, TokenMap)> { 46pub 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).
52pub fn syntax_node_to_token_tree(node: &SyntaxNode) -> Option<(tt::Subtree, TokenMap)> { 52pub 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 {
319trait TokenConvertor { 319trait 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(&macro_invocation.token_tree().unwrap()) 32 let (invocation_tt, _) = ast_to_token_tree(&macro_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
152pub(crate) fn parse_to_token_tree_by_syntax(ra_fixture: &str) -> tt::Subtree { 151pub(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(&macro_definition.token_tree().unwrap()).unwrap(); 166 let (definition_tt, _) = ast_to_token_tree(&macro_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(&macro_definition.body().unwrap()).unwrap(); 183 let (definition_tt, _) = ast_to_token_tree(&macro_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(&macro_definition.token_tree().unwrap()).unwrap(); 47 let (definition_tt, _) = ast_to_token_tree(&macro_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
10use hir::{ 10use 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};
14use hir_def::FunctionId; 14use hir_def::FunctionId;
15use hir_ty::TypeWalk; 15use hir_ty::TypeWalk;
16use ide::{AnalysisHost, RootDatabase};
16use ide_db::base_db::{ 17use ide_db::base_db::{
17 salsa::{self, ParallelDatabase}, 18 salsa::{self, ParallelDatabase},
18 SourceDatabaseExt, 19 SourceDatabaseExt,
@@ -24,6 +25,7 @@ use rayon::prelude::*;
24use rustc_hash::FxHashSet; 25use rustc_hash::FxHashSet;
25use stdx::format_to; 26use stdx::format_to;
26use syntax::AstNode; 27use syntax::AstNode;
28use vfs::Vfs;
27 29
28use crate::cli::{ 30use 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
56impl AnalysisStatsCmd { 59impl 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
603This request is sent from client to server to move item under cursor or selection in some direction. 603This 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
845Introduce helper variables freely, especially for multiline conditions. 845Introduce helper variables freely, especially for multiline conditions:
846
847```rust
848// GOOD
849let rustfmt_not_installed =
850 captured_stderr.contains("not installed") || captured_stderr.contains("not available");
851
852match 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
858match 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.
848Extra variables help during debugging, they make it easy to print/view important intermediate results. 867Extra 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)]
94pub struct Arena<T> { 94pub 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();