aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-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
66 files changed, 2027 insertions, 1435 deletions
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