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.rs23
-rw-r--r--crates/hir/src/lib.rs106
-rw-r--r--crates/hir_def/Cargo.toml2
-rw-r--r--crates/hir_def/src/adt.rs9
-rw-r--r--crates/hir_def/src/attr.rs9
-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.rs86
-rw-r--r--crates/hir_def/src/intern.rs197
-rw-r--r--crates/hir_def/src/item_scope.rs22
-rw-r--r--crates/hir_def/src/item_tree.rs127
-rw-r--r--crates/hir_def/src/item_tree/lower.rs93
-rw-r--r--crates/hir_def/src/lib.rs1
-rw-r--r--crates/hir_def/src/nameres.rs25
-rw-r--r--crates/hir_def/src/nameres/collector.rs56
-rw-r--r--crates/hir_def/src/nameres/tests/diagnostics.rs20
-rw-r--r--crates/hir_def/src/path.rs14
-rw-r--r--crates/hir_def/src/path/lower.rs8
-rw-r--r--crates/hir_def/src/test_db.rs13
-rw-r--r--crates/hir_expand/src/builtin_macro.rs27
-rw-r--r--crates/hir_expand/src/db.rs14
-rw-r--r--crates/hir_expand/src/eager.rs4
-rw-r--r--crates/hir_expand/src/name.rs2
-rw-r--r--crates/hir_expand/src/quote.rs1
-rw-r--r--crates/hir_ty/src/autoderef.rs47
-rw-r--r--crates/hir_ty/src/builder.rs219
-rw-r--r--crates/hir_ty/src/chalk_cast.rs22
-rw-r--r--crates/hir_ty/src/chalk_ext.rs13
-rw-r--r--crates/hir_ty/src/diagnostics/decl_check.rs5
-rw-r--r--crates/hir_ty/src/diagnostics/expr.rs10
-rw-r--r--crates/hir_ty/src/diagnostics/match_check.rs7
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs8
-rw-r--r--crates/hir_ty/src/display.rs75
-rw-r--r--crates/hir_ty/src/infer.rs21
-rw-r--r--crates/hir_ty/src/infer/coerce.rs39
-rw-r--r--crates/hir_ty/src/infer/expr.rs136
-rw-r--r--crates/hir_ty/src/infer/pat.rs45
-rw-r--r--crates/hir_ty/src/infer/path.rs33
-rw-r--r--crates/hir_ty/src/infer/unify.rs72
-rw-r--r--crates/hir_ty/src/lib.rs323
-rw-r--r--crates/hir_ty/src/lower.rs137
-rw-r--r--crates/hir_ty/src/method_resolution.rs33
-rw-r--r--crates/hir_ty/src/op.rs12
-rw-r--r--crates/hir_ty/src/tests.rs2
-rw-r--r--crates/hir_ty/src/traits.rs2
-rw-r--r--crates/hir_ty/src/traits/chalk.rs26
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs39
-rw-r--r--crates/hir_ty/src/utils.rs24
-rw-r--r--crates/ide/src/hover.rs42
-rw-r--r--crates/ide/src/inlay_hints.rs2
-rw-r--r--crates/ide/src/join_lines.rs18
-rw-r--r--crates/mbe/src/benchmark.rs2
-rw-r--r--crates/mbe/src/expander.rs6
-rw-r--r--crates/mbe/src/lib.rs6
-rw-r--r--crates/mbe/src/syntax_bridge.rs23
-rw-r--r--crates/mbe/src/tests.rs11
-rw-r--r--crates/mbe/src/tests/expand.rs15
-rw-r--r--crates/mbe/src/tests/rule.rs2
-rw-r--r--crates/mbe/src/tt_iter.rs11
-rw-r--r--crates/rust-analyzer/src/bin/main.rs2
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs2
64 files changed, 1499 insertions, 908 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 97a78ca25..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,10 +87,10 @@ 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 {
95 TypeRef::ImplTrait(bounds) => match &bounds[0] { 94 TypeRef::ImplTrait(bounds) => match &bounds[0] {
96 TypeBound::Path(path) => { 95 TypeBound::Path(path) => {
97 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings 96 path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings
@@ -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 97f162315..19901ed33 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -55,11 +55,10 @@ 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,
59 traits::{FnTrait, Solution, SolutionVariables}, 58 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, Substitution,
62 Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, 61 TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause,
63}; 62};
64use itertools::Itertools; 63use itertools::Itertools;
65use rustc_hash::FxHashSet; 64use rustc_hash::FxHashSet;
@@ -515,7 +514,7 @@ impl Field {
515 VariantDef::Union(it) => it.id.into(), 514 VariantDef::Union(it) => it.id.into(),
516 VariantDef::Variant(it) => it.parent.id.into(), 515 VariantDef::Variant(it) => it.parent.id.into(),
517 }; 516 };
518 let substs = Substitution::type_params(db, generic_def_id); 517 let substs = TyBuilder::type_params_subst(db, generic_def_id);
519 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 518 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) 519 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
521 } 520 }
@@ -832,7 +831,7 @@ impl Function {
832 } 831 }
833 832
834 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { 833 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
835 if !db.function_data(self.id).has_self_param { 834 if !db.function_data(self.id).has_self_param() {
836 return None; 835 return None;
837 } 836 }
838 Some(SelfParam { func: self.id }) 837 Some(SelfParam { func: self.id })
@@ -864,7 +863,7 @@ impl Function {
864 } 863 }
865 864
866 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 865 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
867 db.function_data(self.id).qualifier.is_unsafe 866 db.function_data(self.id).is_unsafe()
868 } 867 }
869 868
870 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 869 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -878,7 +877,7 @@ impl Function {
878 /// 877 ///
879 /// This is false in the case of required (not provided) trait methods. 878 /// This is false in the case of required (not provided) trait methods.
880 pub fn has_body(self, db: &dyn HirDatabase) -> bool { 879 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
881 db.function_data(self.id).has_body 880 db.function_data(self.id).has_body()
882 } 881 }
883 882
884 /// A textual representation of the HIR of this function for debugging purposes. 883 /// A textual representation of the HIR of this function for debugging purposes.
@@ -957,7 +956,7 @@ impl SelfParam {
957 func_data 956 func_data
958 .params 957 .params
959 .first() 958 .first()
960 .map(|param| match *param { 959 .map(|param| match &**param {
961 TypeRef::Reference(.., mutability) => match mutability { 960 TypeRef::Reference(.., mutability) => match mutability {
962 hir_def::type_ref::Mutability::Shared => Access::Shared, 961 hir_def::type_ref::Mutability::Shared => Access::Shared,
963 hir_def::type_ref::Mutability::Mut => Access::Exclusive, 962 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
@@ -1011,7 +1010,7 @@ impl Const {
1011 } 1010 }
1012 1011
1013 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { 1012 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
1014 db.const_data(self.id).type_ref.clone() 1013 db.const_data(self.id).type_ref.as_ref().clone()
1015 } 1014 }
1016} 1015}
1017 1016
@@ -1101,7 +1100,7 @@ impl TypeAlias {
1101 } 1100 }
1102 1101
1103 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1102 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1104 db.type_alias_data(self.id).type_ref.clone() 1103 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1105 } 1104 }
1106 1105
1107 pub fn ty(self, db: &dyn HirDatabase) -> Type { 1106 pub fn ty(self, db: &dyn HirDatabase) -> Type {
@@ -1129,7 +1128,7 @@ pub struct BuiltinType {
1129impl BuiltinType { 1128impl BuiltinType {
1130 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { 1129 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
1131 let resolver = module.id.resolver(db.upcast()); 1130 let resolver = module.id.resolver(db.upcast());
1132 Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) 1131 Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
1133 .expect("crate not present in resolver") 1132 .expect("crate not present in resolver")
1134 } 1133 }
1135 1134
@@ -1502,7 +1501,7 @@ impl TypeParam {
1502 let resolver = self.id.parent.resolver(db.upcast()); 1501 let resolver = self.id.parent.resolver(db.upcast());
1503 let krate = self.id.parent.module(db.upcast()).krate(); 1502 let krate = self.id.parent.module(db.upcast()).krate();
1504 let ty = params.get(local_idx)?.clone(); 1503 let ty = params.get(local_idx)?.clone();
1505 let subst = Substitution::type_params(db, self.id.parent); 1504 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1506 let ty = ty.subst(&subst.prefix(local_idx)); 1505 let ty = ty.subst(&subst.prefix(local_idx));
1507 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1506 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1508 } 1507 }
@@ -1615,7 +1614,7 @@ impl Impl {
1615 // FIXME: the return type is wrong. This should be a hir version of 1614 // FIXME: the return type is wrong. This should be a hir version of
1616 // `TraitRef` (ie, resolved `TypeRef`). 1615 // `TraitRef` (ie, resolved `TypeRef`).
1617 pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> { 1616 pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
1618 db.impl_data(self.id).target_trait.clone() 1617 db.impl_data(self.id).target_trait.as_deref().cloned()
1619 } 1618 }
1620 1619
1621 pub fn self_ty(self, db: &dyn HirDatabase) -> Type { 1620 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
@@ -1703,30 +1702,29 @@ impl Type {
1703 fn from_def( 1702 fn from_def(
1704 db: &dyn HirDatabase, 1703 db: &dyn HirDatabase,
1705 krate: CrateId, 1704 krate: CrateId,
1706 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, 1705 def: impl HasResolver + Into<TyDefId>,
1707 ) -> Type { 1706 ) -> Type {
1708 let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); 1707 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) 1708 Type::new(db, krate, def, ty)
1711 } 1709 }
1712 1710
1713 pub fn is_unit(&self) -> bool { 1711 pub fn is_unit(&self) -> bool {
1714 matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) 1712 matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..))
1715 } 1713 }
1716 pub fn is_bool(&self) -> bool { 1714 pub fn is_bool(&self) -> bool {
1717 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) 1715 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool))
1718 } 1716 }
1719 1717
1720 pub fn is_mutable_reference(&self) -> bool { 1718 pub fn is_mutable_reference(&self) -> bool {
1721 matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) 1719 matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1722 } 1720 }
1723 1721
1724 pub fn is_usize(&self) -> bool { 1722 pub fn is_usize(&self) -> bool {
1725 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) 1723 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
1726 } 1724 }
1727 1725
1728 pub fn remove_ref(&self) -> Option<Type> { 1726 pub fn remove_ref(&self) -> Option<Type> {
1729 match &self.ty.interned(&Interner) { 1727 match &self.ty.kind(&Interner) {
1730 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), 1728 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
1731 _ => None, 1729 _ => None,
1732 } 1730 }
@@ -1785,13 +1783,10 @@ impl Type {
1785 } 1783 }
1786 1784
1787 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1785 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1788 let trait_ref = hir_ty::TraitRef { 1786 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
1789 trait_id: hir_ty::to_chalk_trait_id(trait_.id), 1787 .push(self.ty.clone())
1790 substitution: Substitution::build_for_def(db, trait_.id) 1788 .fill(args.iter().map(|t| t.ty.clone()))
1791 .push(self.ty.clone()) 1789 .build();
1792 .fill(args.iter().map(|t| t.ty.clone()))
1793 .build(),
1794 };
1795 1790
1796 let goal = Canonical { 1791 let goal = Canonical {
1797 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), 1792 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@@ -1804,11 +1799,10 @@ impl Type {
1804 pub fn normalize_trait_assoc_type( 1799 pub fn normalize_trait_assoc_type(
1805 &self, 1800 &self,
1806 db: &dyn HirDatabase, 1801 db: &dyn HirDatabase,
1807 trait_: Trait,
1808 args: &[Type], 1802 args: &[Type],
1809 alias: TypeAlias, 1803 alias: TypeAlias,
1810 ) -> Option<Type> { 1804 ) -> Option<Type> {
1811 let subst = Substitution::build_for_def(db, trait_.id) 1805 let projection = TyBuilder::assoc_type_projection(db, alias.id)
1812 .push(self.ty.clone()) 1806 .push(self.ty.clone())
1813 .fill(args.iter().map(|t| t.ty.clone())) 1807 .fill(args.iter().map(|t| t.ty.clone()))
1814 .build(); 1808 .build();
@@ -1816,10 +1810,7 @@ impl Type {
1816 InEnvironment::new( 1810 InEnvironment::new(
1817 self.env.env.clone(), 1811 self.env.env.clone(),
1818 AliasEq { 1812 AliasEq {
1819 alias: AliasTy::Projection(ProjectionTy { 1813 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)) 1814 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
1824 .intern(&Interner), 1815 .intern(&Interner),
1825 } 1816 }
@@ -1829,9 +1820,11 @@ impl Type {
1829 ); 1820 );
1830 1821
1831 match db.trait_solve(self.krate, goal)? { 1822 match db.trait_solve(self.krate, goal)? {
1832 Solution::Unique(SolutionVariables(subst)) => { 1823 Solution::Unique(SolutionVariables(subst)) => subst
1833 subst.value.first().map(|ty| self.derived(ty.clone())) 1824 .value
1834 } 1825 .interned(&Interner)
1826 .first()
1827 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1835 Solution::Ambig(_) => None, 1828 Solution::Ambig(_) => None,
1836 } 1829 }
1837 } 1830 }
@@ -1853,15 +1846,15 @@ impl Type {
1853 } 1846 }
1854 1847
1855 pub fn is_closure(&self) -> bool { 1848 pub fn is_closure(&self) -> bool {
1856 matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) 1849 matches!(&self.ty.kind(&Interner), TyKind::Closure { .. })
1857 } 1850 }
1858 1851
1859 pub fn is_fn(&self) -> bool { 1852 pub fn is_fn(&self) -> bool {
1860 matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) 1853 matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
1861 } 1854 }
1862 1855
1863 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { 1856 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1864 let adt_id = match self.ty.interned(&Interner) { 1857 let adt_id = match self.ty.kind(&Interner) {
1865 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, 1858 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
1866 _ => return false, 1859 _ => return false,
1867 }; 1860 };
@@ -1874,14 +1867,14 @@ impl Type {
1874 } 1867 }
1875 1868
1876 pub fn is_raw_ptr(&self) -> bool { 1869 pub fn is_raw_ptr(&self) -> bool {
1877 matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) 1870 matches!(&self.ty.kind(&Interner), TyKind::Raw(..))
1878 } 1871 }
1879 1872
1880 pub fn contains_unknown(&self) -> bool { 1873 pub fn contains_unknown(&self) -> bool {
1881 return go(&self.ty); 1874 return go(&self.ty);
1882 1875
1883 fn go(ty: &Ty) -> bool { 1876 fn go(ty: &Ty) -> bool {
1884 match ty.interned(&Interner) { 1877 match ty.kind(&Interner) {
1885 TyKind::Unknown => true, 1878 TyKind::Unknown => true,
1886 1879
1887 TyKind::Adt(_, substs) 1880 TyKind::Adt(_, substs)
@@ -1889,7 +1882,9 @@ impl Type {
1889 | TyKind::Tuple(_, substs) 1882 | TyKind::Tuple(_, substs)
1890 | TyKind::OpaqueType(_, substs) 1883 | TyKind::OpaqueType(_, substs)
1891 | TyKind::FnDef(_, substs) 1884 | TyKind::FnDef(_, substs)
1892 | TyKind::Closure(_, substs) => substs.iter().any(go), 1885 | TyKind::Closure(_, substs) => {
1886 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
1887 }
1893 1888
1894 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { 1889 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
1895 go(ty) 1890 go(ty)
@@ -1910,7 +1905,7 @@ impl Type {
1910 } 1905 }
1911 1906
1912 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { 1907 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1913 let (variant_id, substs) = match self.ty.interned(&Interner) { 1908 let (variant_id, substs) = match self.ty.kind(&Interner) {
1914 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), 1909 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
1915 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), 1910 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
1916 _ => return Vec::new(), 1911 _ => return Vec::new(),
@@ -1927,8 +1922,11 @@ impl Type {
1927 } 1922 }
1928 1923
1929 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { 1924 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1930 if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { 1925 if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) {
1931 substs.iter().map(|ty| self.derived(ty.clone())).collect() 1926 substs
1927 .iter(&Interner)
1928 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone()))
1929 .collect()
1932 } else { 1930 } else {
1933 Vec::new() 1931 Vec::new()
1934 } 1932 }
@@ -1973,8 +1971,9 @@ impl Type {
1973 .strip_references() 1971 .strip_references()
1974 .substs() 1972 .substs()
1975 .into_iter() 1973 .into_iter()
1976 .flat_map(|substs| substs.iter()) 1974 .flat_map(|substs| substs.iter(&Interner))
1977 .map(move |ty| self.derived(ty.clone())) 1975 .filter_map(|arg| arg.ty(&Interner).cloned())
1976 .map(move |ty| self.derived(ty))
1978 } 1977 }
1979 1978
1980 pub fn iterate_method_candidates<T>( 1979 pub fn iterate_method_candidates<T>(
@@ -2080,7 +2079,7 @@ impl Type {
2080 substs: &Substitution, 2079 substs: &Substitution,
2081 cb: &mut impl FnMut(Type), 2080 cb: &mut impl FnMut(Type),
2082 ) { 2081 ) {
2083 for ty in substs.iter() { 2082 for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) {
2084 walk_type(db, &type_.derived(ty.clone()), cb); 2083 walk_type(db, &type_.derived(ty.clone()), cb);
2085 } 2084 }
2086 } 2085 }
@@ -2096,7 +2095,12 @@ impl Type {
2096 WhereClause::Implemented(trait_ref) => { 2095 WhereClause::Implemented(trait_ref) => {
2097 cb(type_.clone()); 2096 cb(type_.clone());
2098 // skip the self type. it's likely the type we just got the bounds from 2097 // skip the self type. it's likely the type we just got the bounds from
2099 for ty in trait_ref.substitution.iter().skip(1) { 2098 for ty in trait_ref
2099 .substitution
2100 .iter(&Interner)
2101 .skip(1)
2102 .filter_map(|a| a.ty(&Interner))
2103 {
2100 walk_type(db, &type_.derived(ty.clone()), cb); 2104 walk_type(db, &type_.derived(ty.clone()), cb);
2101 } 2105 }
2102 } 2106 }
@@ -2107,7 +2111,7 @@ impl Type {
2107 2111
2108 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 2112 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
2109 let ty = type_.ty.strip_references(); 2113 let ty = type_.ty.strip_references();
2110 match ty.interned(&Interner) { 2114 match ty.kind(&Interner) {
2111 TyKind::Adt(..) => { 2115 TyKind::Adt(..) => {
2112 cb(type_.derived(ty.clone())); 2116 cb(type_.derived(ty.clone()));
2113 } 2117 }
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml
index 475d337f3..60adb655c 100644
--- a/crates/hir_def/Cargo.toml
+++ b/crates/hir_def/Cargo.toml
@@ -10,7 +10,9 @@ edition = "2018"
10doctest = false 10doctest = false
11 11
12[dependencies] 12[dependencies]
13bitflags = "1.2.1"
13cov-mark = { version = "1.1", features = ["thread-local"] } 14cov-mark = { version = "1.1", features = ["thread-local"] }
15dashmap = { version = "4.0.2", features = ["raw-api"] }
14log = "0.4.8" 16log = "0.4.8"
15once_cell = "1.3.1" 17once_cell = "1.3.1"
16rustc-hash = "1.1.0" 18rustc-hash = "1.1.0"
diff --git a/crates/hir_def/src/adt.rs b/crates/hir_def/src/adt.rs
index 58e35353b..402fb1d8d 100644
--- a/crates/hir_def/src/adt.rs
+++ b/crates/hir_def/src/adt.rs
@@ -15,6 +15,7 @@ use tt::{Delimiter, DelimiterKind, Leaf, Subtree, TokenTree};
15use crate::{ 15use crate::{
16 body::{CfgExpander, LowerCtx}, 16 body::{CfgExpander, LowerCtx},
17 db::DefDatabase, 17 db::DefDatabase,
18 intern::Interned,
18 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId}, 19 item_tree::{AttrOwner, Field, Fields, ItemTree, ModItem, RawVisibilityId},
19 src::HasChildSource, 20 src::HasChildSource,
20 src::HasSource, 21 src::HasSource,
@@ -58,7 +59,7 @@ pub enum VariantData {
58#[derive(Debug, Clone, PartialEq, Eq)] 59#[derive(Debug, Clone, PartialEq, Eq)]
59pub struct FieldData { 60pub struct FieldData {
60 pub name: Name, 61 pub name: Name,
61 pub type_ref: TypeRef, 62 pub type_ref: Interned<TypeRef>,
62 pub visibility: RawVisibility, 63 pub visibility: RawVisibility,
63} 64}
64 65
@@ -292,7 +293,7 @@ fn lower_struct(
292 || Either::Left(fd.clone()), 293 || Either::Left(fd.clone()),
293 || FieldData { 294 || FieldData {
294 name: Name::new_tuple_field(i), 295 name: Name::new_tuple_field(i),
295 type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), 296 type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
296 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 297 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
297 }, 298 },
298 ); 299 );
@@ -309,7 +310,7 @@ fn lower_struct(
309 || Either::Right(fd.clone()), 310 || Either::Right(fd.clone()),
310 || FieldData { 311 || FieldData {
311 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), 312 name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing),
312 type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), 313 type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())),
313 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), 314 visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())),
314 }, 315 },
315 ); 316 );
@@ -358,7 +359,7 @@ fn lower_field(
358) -> FieldData { 359) -> FieldData {
359 FieldData { 360 FieldData {
360 name: field.name.clone(), 361 name: field.name.clone(),
361 type_ref: item_tree[field.type_ref].clone(), 362 type_ref: field.type_ref.clone(),
362 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), 363 visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(),
363 } 364 }
364} 365}
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs
index 52a2bce9b..442c5fb5b 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -18,6 +18,7 @@ use tt::Subtree;
18 18
19use crate::{ 19use crate::{
20 db::DefDatabase, 20 db::DefDatabase,
21 intern::Interned,
21 item_tree::{ItemTreeId, ItemTreeNode}, 22 item_tree::{ItemTreeId, ItemTreeNode},
22 nameres::ModuleSource, 23 nameres::ModuleSource,
23 path::{ModPath, PathKind}, 24 path::{ModPath, PathKind},
@@ -98,7 +99,7 @@ impl RawAttrs {
98 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 99 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
99 index: i as u32, 100 index: i as u32,
100 input: Some(AttrInput::Literal(SmolStr::new(doc))), 101 input: Some(AttrInput::Literal(SmolStr::new(doc))),
101 path: ModPath::from(hir_expand::name!(doc)), 102 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
102 }), 103 }),
103 }) 104 })
104 .collect::<Arc<_>>(); 105 .collect::<Arc<_>>();
@@ -510,7 +511,7 @@ impl AttrSourceMap {
510#[derive(Debug, Clone, PartialEq, Eq)] 511#[derive(Debug, Clone, PartialEq, Eq)]
511pub struct Attr { 512pub struct Attr {
512 index: u32, 513 index: u32,
513 pub(crate) path: ModPath, 514 pub(crate) path: Interned<ModPath>,
514 pub(crate) input: Option<AttrInput>, 515 pub(crate) input: Option<AttrInput>,
515} 516}
516 517
@@ -524,7 +525,7 @@ pub enum AttrInput {
524 525
525impl Attr { 526impl Attr {
526 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 527 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> {
527 let path = ModPath::from_src(ast.path()?, hygiene)?; 528 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
528 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 529 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
529 let value = match lit.kind() { 530 let value = match lit.kind() {
530 ast::LiteralKind::String(string) => string.value()?.into(), 531 ast::LiteralKind::String(string) => string.value()?.into(),
@@ -532,7 +533,7 @@ impl Attr {
532 }; 533 };
533 Some(AttrInput::Literal(value)) 534 Some(AttrInput::Literal(value))
534 } else if let Some(tt) = ast.token_tree() { 535 } else if let Some(tt) = ast.token_tree() {
535 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) 536 Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0))
536 } else { 537 } else {
537 None 538 None
538 }; 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 214bcc648..b409fb45c 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -9,7 +9,8 @@ use crate::{
9 attr::Attrs, 9 attr::Attrs,
10 body::Expander, 10 body::Expander,
11 db::DefDatabase, 11 db::DefDatabase,
12 item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, 12 intern::Interned,
13 item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param},
13 type_ref::{TraitRef, TypeBound, TypeRef}, 14 type_ref::{TraitRef, TypeBound, TypeRef},
14 visibility::RawVisibility, 15 visibility::RawVisibility,
15 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, 16 AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
@@ -19,17 +20,12 @@ use crate::{
19#[derive(Debug, Clone, PartialEq, Eq)] 20#[derive(Debug, Clone, PartialEq, Eq)]
20pub struct FunctionData { 21pub struct FunctionData {
21 pub name: Name, 22 pub name: Name,
22 pub params: Vec<TypeRef>, 23 pub params: Vec<Interned<TypeRef>>,
23 pub ret_type: TypeRef, 24 pub ret_type: Interned<TypeRef>,
24 pub attrs: Attrs, 25 pub attrs: Attrs,
25 /// True if the first param is `self`. This is relevant to decide whether this
26 /// can be called as a method.
27 pub has_self_param: bool,
28 pub has_body: bool,
29 pub qualifier: FunctionQualifier,
30 pub is_in_extern_block: bool,
31 pub is_varargs: bool,
32 pub visibility: RawVisibility, 26 pub visibility: RawVisibility,
27 pub abi: Option<Interned<str>>,
28 flags: FnFlags,
33} 29}
34 30
35impl FunctionData { 31impl FunctionData {
@@ -52,31 +48,67 @@ impl FunctionData {
52 .next_back() 48 .next_back()
53 .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); 49 .map_or(false, |param| matches!(item_tree[param], Param::Varargs));
54 50
51 let mut flags = func.flags;
52 if is_varargs {
53 flags |= FnFlags::IS_VARARGS;
54 }
55
55 Arc::new(FunctionData { 56 Arc::new(FunctionData {
56 name: func.name.clone(), 57 name: func.name.clone(),
57 params: enabled_params 58 params: enabled_params
58 .clone() 59 .clone()
59 .filter_map(|id| match &item_tree[id] { 60 .filter_map(|id| match &item_tree[id] {
60 Param::Normal(ty) => Some(item_tree[*ty].clone()), 61 Param::Normal(ty) => Some(ty.clone()),
61 Param::Varargs => None, 62 Param::Varargs => None,
62 }) 63 })
63 .collect(), 64 .collect(),
64 ret_type: item_tree[func.ret_type].clone(), 65 ret_type: func.ret_type.clone(),
65 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()),
66 has_self_param: func.has_self_param,
67 has_body: func.has_body,
68 qualifier: func.qualifier.clone(),
69 is_in_extern_block: func.is_in_extern_block,
70 is_varargs,
71 visibility: item_tree[func.visibility].clone(), 67 visibility: item_tree[func.visibility].clone(),
68 abi: func.abi.clone(),
69 flags,
72 }) 70 })
73 } 71 }
72
73 pub fn has_body(&self) -> bool {
74 self.flags.contains(FnFlags::HAS_BODY)
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.contains(FnFlags::HAS_SELF_PARAM)
81 }
82
83 pub fn is_default(&self) -> bool {
84 self.flags.contains(FnFlags::IS_DEFAULT)
85 }
86
87 pub fn is_const(&self) -> bool {
88 self.flags.contains(FnFlags::IS_CONST)
89 }
90
91 pub fn is_async(&self) -> bool {
92 self.flags.contains(FnFlags::IS_ASYNC)
93 }
94
95 pub fn is_unsafe(&self) -> bool {
96 self.flags.contains(FnFlags::IS_UNSAFE)
97 }
98
99 pub fn is_in_extern_block(&self) -> bool {
100 self.flags.contains(FnFlags::IS_IN_EXTERN_BLOCK)
101 }
102
103 pub fn is_varargs(&self) -> bool {
104 self.flags.contains(FnFlags::IS_VARARGS)
105 }
74} 106}
75 107
76#[derive(Debug, Clone, PartialEq, Eq)] 108#[derive(Debug, Clone, PartialEq, Eq)]
77pub struct TypeAliasData { 109pub struct TypeAliasData {
78 pub name: Name, 110 pub name: Name,
79 pub type_ref: Option<TypeRef>, 111 pub type_ref: Option<Interned<TypeRef>>,
80 pub visibility: RawVisibility, 112 pub visibility: RawVisibility,
81 pub is_extern: bool, 113 pub is_extern: bool,
82 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl). 114 /// Bounds restricting the type alias itself (eg. `type Ty: Bound;` in a trait or impl).
@@ -94,7 +126,7 @@ impl TypeAliasData {
94 126
95 Arc::new(TypeAliasData { 127 Arc::new(TypeAliasData {
96 name: typ.name.clone(), 128 name: typ.name.clone(),
97 type_ref: typ.type_ref.map(|id| item_tree[id].clone()), 129 type_ref: typ.type_ref.clone(),
98 visibility: item_tree[typ.visibility].clone(), 130 visibility: item_tree[typ.visibility].clone(),
99 is_extern: typ.is_extern, 131 is_extern: typ.is_extern,
100 bounds: typ.bounds.to_vec(), 132 bounds: typ.bounds.to_vec(),
@@ -156,8 +188,8 @@ impl TraitData {
156 188
157#[derive(Debug, Clone, PartialEq, Eq)] 189#[derive(Debug, Clone, PartialEq, Eq)]
158pub struct ImplData { 190pub struct ImplData {
159 pub target_trait: Option<TraitRef>, 191 pub target_trait: Option<Interned<TraitRef>>,
160 pub self_ty: TypeRef, 192 pub self_ty: Interned<TypeRef>,
161 pub items: Vec<AssocItemId>, 193 pub items: Vec<AssocItemId>,
162 pub is_negative: bool, 194 pub is_negative: bool,
163} 195}
@@ -169,8 +201,8 @@ impl ImplData {
169 201
170 let item_tree = impl_loc.id.item_tree(db); 202 let item_tree = impl_loc.id.item_tree(db);
171 let impl_def = &item_tree[impl_loc.id.value]; 203 let impl_def = &item_tree[impl_loc.id.value];
172 let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); 204 let target_trait = impl_def.target_trait.clone();
173 let self_ty = item_tree[impl_def.self_ty].clone(); 205 let self_ty = impl_def.self_ty.clone();
174 let is_negative = impl_def.is_negative; 206 let is_negative = impl_def.is_negative;
175 let module_id = impl_loc.container; 207 let module_id = impl_loc.container;
176 let container = AssocContainerId::ImplId(id); 208 let container = AssocContainerId::ImplId(id);
@@ -195,7 +227,7 @@ impl ImplData {
195pub struct ConstData { 227pub struct ConstData {
196 /// const _: () = (); 228 /// const _: () = ();
197 pub name: Option<Name>, 229 pub name: Option<Name>,
198 pub type_ref: TypeRef, 230 pub type_ref: Interned<TypeRef>,
199 pub visibility: RawVisibility, 231 pub visibility: RawVisibility,
200} 232}
201 233
@@ -207,7 +239,7 @@ impl ConstData {
207 239
208 Arc::new(ConstData { 240 Arc::new(ConstData {
209 name: konst.name.clone(), 241 name: konst.name.clone(),
210 type_ref: item_tree[konst.type_ref].clone(), 242 type_ref: konst.type_ref.clone(),
211 visibility: item_tree[konst.visibility].clone(), 243 visibility: item_tree[konst.visibility].clone(),
212 }) 244 })
213 } 245 }
@@ -216,7 +248,7 @@ impl ConstData {
216#[derive(Debug, Clone, PartialEq, Eq)] 248#[derive(Debug, Clone, PartialEq, Eq)]
217pub struct StaticData { 249pub struct StaticData {
218 pub name: Option<Name>, 250 pub name: Option<Name>,
219 pub type_ref: TypeRef, 251 pub type_ref: Interned<TypeRef>,
220 pub visibility: RawVisibility, 252 pub visibility: RawVisibility,
221 pub mutable: bool, 253 pub mutable: bool,
222 pub is_extern: bool, 254 pub is_extern: bool,
@@ -230,7 +262,7 @@ impl StaticData {
230 262
231 Arc::new(StaticData { 263 Arc::new(StaticData {
232 name: Some(statik.name.clone()), 264 name: Some(statik.name.clone()),
233 type_ref: item_tree[statik.type_ref].clone(), 265 type_ref: statik.type_ref.clone(),
234 visibility: item_tree[statik.visibility].clone(), 266 visibility: item_tree[statik.visibility].clone(),
235 mutable: statik.mutable, 267 mutable: statik.mutable,
236 is_extern: statik.is_extern, 268 is_extern: statik.is_extern,
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs
new file mode 100644
index 000000000..d163f633f
--- /dev/null
+++ b/crates/hir_def/src/intern.rs
@@ -0,0 +1,197 @@
1//! Global `Arc`-based object interning infrastructure.
2//!
3//! Eventually this should probably be replaced with salsa-based interning.
4
5use std::{
6 collections::HashMap,
7 fmt::{self, Debug},
8 hash::{BuildHasherDefault, Hash},
9 ops::Deref,
10 sync::Arc,
11};
12
13use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue};
14use once_cell::sync::OnceCell;
15use rustc_hash::FxHasher;
16
17type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
18type Guard<T> =
19 RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>;
20
21#[derive(Hash)]
22pub struct Interned<T: Internable + ?Sized> {
23 arc: Arc<T>,
24}
25
26impl<T: Internable> Interned<T> {
27 pub fn new(obj: T) -> Self {
28 match Interned::lookup(&obj) {
29 Ok(this) => this,
30 Err(shard) => {
31 let arc = Arc::new(obj);
32 Self::alloc(arc, shard)
33 }
34 }
35 }
36}
37
38impl<T: Internable + ?Sized> Interned<T> {
39 fn lookup(obj: &T) -> Result<Self, Guard<T>> {
40 let storage = T::storage().get();
41 let shard_idx = storage.determine_map(obj);
42 let shard = &storage.shards()[shard_idx];
43 let shard = shard.write();
44
45 // Atomically,
46 // - check if `obj` is already in the map
47 // - if so, clone its `Arc` and return it
48 // - if not, box it up, insert it, and return a clone
49 // This needs to be atomic (locking the shard) to avoid races with other thread, which could
50 // insert the same object between us looking it up and inserting it.
51
52 // FIXME: avoid double lookup/hashing by using raw entry API (once stable, or when
53 // hashbrown can be plugged into dashmap)
54 match shard.get_key_value(obj) {
55 Some((arc, _)) => Ok(Self { arc: arc.clone() }),
56 None => Err(shard),
57 }
58 }
59
60 fn alloc(arc: Arc<T>, mut shard: Guard<T>) -> Self {
61 let arc2 = arc.clone();
62
63 shard.insert(arc2, SharedValue::new(()));
64
65 Self { arc }
66 }
67}
68
69impl Interned<str> {
70 pub fn new_str(s: &str) -> Self {
71 match Interned::lookup(s) {
72 Ok(this) => this,
73 Err(shard) => {
74 let arc = Arc::<str>::from(s);
75 Self::alloc(arc, shard)
76 }
77 }
78 }
79}
80
81impl<T: Internable + ?Sized> Drop for Interned<T> {
82 #[inline]
83 fn drop(&mut self) {
84 // When the last `Ref` is dropped, remove the object from the global map.
85 if Arc::strong_count(&self.arc) == 2 {
86 // Only `self` and the global map point to the object.
87
88 self.drop_slow();
89 }
90 }
91}
92
93impl<T: Internable + ?Sized> Interned<T> {
94 #[cold]
95 fn drop_slow(&mut self) {
96 let storage = T::storage().get();
97 let shard_idx = storage.determine_map(&self.arc);
98 let shard = &storage.shards()[shard_idx];
99 let mut shard = shard.write();
100
101 // FIXME: avoid double lookup
102 let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely");
103
104 if Arc::strong_count(arc) != 2 {
105 // Another thread has interned another copy
106 return;
107 }
108
109 shard.remove(&self.arc);
110
111 // Shrink the backing storage if the shard is less than 50% occupied.
112 if shard.len() * 2 < shard.capacity() {
113 shard.shrink_to_fit();
114 }
115 }
116}
117
118/// Compares interned `Ref`s using pointer equality.
119impl<T: Internable> PartialEq for Interned<T> {
120 // NOTE: No `?Sized` because `ptr_eq` doesn't work right with trait objects.
121
122 #[inline]
123 fn eq(&self, other: &Self) -> bool {
124 Arc::ptr_eq(&self.arc, &other.arc)
125 }
126}
127
128impl<T: Internable> Eq for Interned<T> {}
129
130impl PartialEq for Interned<str> {
131 fn eq(&self, other: &Self) -> bool {
132 Arc::ptr_eq(&self.arc, &other.arc)
133 }
134}
135
136impl Eq for Interned<str> {}
137
138impl<T: Internable + ?Sized> AsRef<T> for Interned<T> {
139 #[inline]
140 fn as_ref(&self) -> &T {
141 &self.arc
142 }
143}
144
145impl<T: Internable + ?Sized> Deref for Interned<T> {
146 type Target = T;
147
148 #[inline]
149 fn deref(&self) -> &Self::Target {
150 &self.arc
151 }
152}
153
154impl<T: Internable + ?Sized> Clone for Interned<T> {
155 fn clone(&self) -> Self {
156 Self { arc: self.arc.clone() }
157 }
158}
159
160impl<T: Debug + Internable + ?Sized> Debug for Interned<T> {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 (*self.arc).fmt(f)
163 }
164}
165
166pub struct InternStorage<T: ?Sized> {
167 map: OnceCell<InternMap<T>>,
168}
169
170impl<T: ?Sized> InternStorage<T> {
171 pub const fn new() -> Self {
172 Self { map: OnceCell::new() }
173 }
174}
175
176impl<T: Internable + ?Sized> InternStorage<T> {
177 fn get(&self) -> &InternMap<T> {
178 self.map.get_or_init(DashMap::default)
179 }
180}
181
182pub trait Internable: Hash + Eq + 'static {
183 fn storage() -> &'static InternStorage<Self>;
184}
185
186macro_rules! impl_internable {
187 ( $($t:path),+ $(,)? ) => { $(
188 impl Internable for $t {
189 fn storage() -> &'static InternStorage<Self> {
190 static STORAGE: InternStorage<$t> = InternStorage::new();
191 &STORAGE
192 }
193 }
194 )+ };
195}
196
197impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str);
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 5449bbf5d..c6d700977 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -24,12 +24,13 @@ 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},
31 db::DefDatabase, 31 db::DefDatabase,
32 generics::GenericParams, 32 generics::GenericParams,
33 intern::Interned,
33 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, 34 path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
34 type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, 35 type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
35 visibility::RawVisibility, 36 visibility::RawVisibility,
@@ -146,8 +147,6 @@ impl ItemTree {
146 macro_defs, 147 macro_defs,
147 vis, 148 vis,
148 generics, 149 generics,
149 type_refs,
150 trait_refs,
151 inner_items, 150 inner_items,
152 } = &mut **data; 151 } = &mut **data;
153 152
@@ -172,9 +171,6 @@ impl ItemTree {
172 171
173 vis.arena.shrink_to_fit(); 172 vis.arena.shrink_to_fit();
174 generics.arena.shrink_to_fit(); 173 generics.arena.shrink_to_fit();
175 type_refs.arena.shrink_to_fit();
176 type_refs.map.shrink_to_fit();
177 trait_refs.map.shrink_to_fit();
178 174
179 inner_items.shrink_to_fit(); 175 inner_items.shrink_to_fit();
180 } 176 }
@@ -271,58 +267,6 @@ static EMPTY_GENERICS: GenericParams = GenericParams {
271 where_predicates: Vec::new(), 267 where_predicates: Vec::new(),
272}; 268};
273 269
274/// `TypeRef` interner.
275#[derive(Default, Debug, Eq, PartialEq)]
276struct TypeRefStorage {
277 arena: Arena<Arc<TypeRef>>,
278 map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>,
279}
280
281impl TypeRefStorage {
282 // Note: We lie about the `Idx<TypeRef>` to hide the interner details.
283
284 fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> {
285 if let Some(id) = self.map.get(&ty) {
286 return Idx::from_raw(id.into_raw());
287 }
288
289 let ty = Arc::new(ty);
290 let idx = self.arena.alloc(ty.clone());
291 self.map.insert(ty, idx);
292 Idx::from_raw(idx.into_raw())
293 }
294
295 fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef {
296 &self.arena[Idx::from_raw(id.into_raw())]
297 }
298}
299
300/// `TraitRef` interner.
301#[derive(Default, Debug, Eq, PartialEq)]
302struct TraitRefStorage {
303 arena: Arena<Arc<TraitRef>>,
304 map: FxHashMap<Arc<TraitRef>, Idx<Arc<TraitRef>>>,
305}
306
307impl TraitRefStorage {
308 // Note: We lie about the `Idx<TraitRef>` to hide the interner details.
309
310 fn intern(&mut self, ty: TraitRef) -> Idx<TraitRef> {
311 if let Some(id) = self.map.get(&ty) {
312 return Idx::from_raw(id.into_raw());
313 }
314
315 let ty = Arc::new(ty);
316 let idx = self.arena.alloc(ty.clone());
317 self.map.insert(ty, idx);
318 Idx::from_raw(idx.into_raw())
319 }
320
321 fn lookup(&self, id: Idx<TraitRef>) -> &TraitRef {
322 &self.arena[Idx::from_raw(id.into_raw())]
323 }
324}
325
326#[derive(Default, Debug, Eq, PartialEq)] 270#[derive(Default, Debug, Eq, PartialEq)]
327struct ItemTreeData { 271struct ItemTreeData {
328 imports: Arena<Import>, 272 imports: Arena<Import>,
@@ -346,8 +290,6 @@ struct ItemTreeData {
346 290
347 vis: ItemVisibilities, 291 vis: ItemVisibilities,
348 generics: GenericParamsStorage, 292 generics: GenericParamsStorage,
349 type_refs: TypeRefStorage,
350 trait_refs: TraitRefStorage,
351 293
352 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, 294 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
353} 295}
@@ -577,22 +519,6 @@ impl Index<GenericParamsId> for ItemTree {
577 } 519 }
578} 520}
579 521
580impl Index<Idx<TypeRef>> for ItemTree {
581 type Output = TypeRef;
582
583 fn index(&self, id: Idx<TypeRef>) -> &Self::Output {
584 self.data().type_refs.lookup(id)
585 }
586}
587
588impl Index<Idx<TraitRef>> for ItemTree {
589 type Output = TraitRef;
590
591 fn index(&self, id: Idx<TraitRef>) -> &Self::Output {
592 self.data().trait_refs.lookup(id)
593 }
594}
595
596impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { 522impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
597 type Output = N; 523 type Output = N;
598 fn index(&self, id: FileItemTreeId<N>) -> &N { 524 fn index(&self, id: FileItemTreeId<N>) -> &N {
@@ -603,7 +529,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
603/// A desugared `use` import. 529/// A desugared `use` import.
604#[derive(Debug, Clone, Eq, PartialEq)] 530#[derive(Debug, Clone, Eq, PartialEq)]
605pub struct Import { 531pub struct Import {
606 pub path: ModPath, 532 pub path: Interned<ModPath>,
607 pub alias: Option<ImportAlias>, 533 pub alias: Option<ImportAlias>,
608 pub visibility: RawVisibilityId, 534 pub visibility: RawVisibilityId,
609 pub is_glob: bool, 535 pub is_glob: bool,
@@ -630,30 +556,33 @@ pub struct Function {
630 pub name: Name, 556 pub name: Name,
631 pub visibility: RawVisibilityId, 557 pub visibility: RawVisibilityId,
632 pub generic_params: GenericParamsId, 558 pub generic_params: GenericParamsId,
633 pub has_self_param: bool, 559 pub abi: Option<Interned<str>>,
634 pub has_body: bool,
635 pub qualifier: FunctionQualifier,
636 /// Whether the function is located in an `extern` block (*not* whether it is an
637 /// `extern "abi" fn`).
638 pub is_in_extern_block: bool,
639 pub params: IdRange<Param>, 560 pub params: IdRange<Param>,
640 pub ret_type: Idx<TypeRef>, 561 pub ret_type: Interned<TypeRef>,
641 pub ast_id: FileAstId<ast::Fn>, 562 pub ast_id: FileAstId<ast::Fn>,
563 pub(crate) flags: FnFlags,
642} 564}
643 565
644#[derive(Debug, Clone, Eq, PartialEq)] 566#[derive(Debug, Clone, Eq, PartialEq)]
645pub enum Param { 567pub enum Param {
646 Normal(Idx<TypeRef>), 568 Normal(Interned<TypeRef>),
647 Varargs, 569 Varargs,
648} 570}
649 571
650#[derive(Debug, Clone, PartialEq, Eq)] 572bitflags::bitflags! {
651pub struct FunctionQualifier { 573 /// NOTE: Shared with `FunctionData`
652 pub is_default: bool, 574 pub(crate) struct FnFlags: u8 {
653 pub is_const: bool, 575 const HAS_SELF_PARAM = 1 << 0;
654 pub is_async: bool, 576 const HAS_BODY = 1 << 1;
655 pub is_unsafe: bool, 577 const IS_DEFAULT = 1 << 2;
656 pub abi: Option<SmolStr>, 578 const IS_CONST = 1 << 3;
579 const IS_ASYNC = 1 << 4;
580 const IS_UNSAFE = 1 << 5;
581 /// Whether the function is located in an `extern` block (*not* whether it is an
582 /// `extern "abi" fn`).
583 const IS_IN_EXTERN_BLOCK = 1 << 6;
584 const IS_VARARGS = 1 << 7;
585 }
657} 586}
658 587
659#[derive(Debug, Clone, Eq, PartialEq)] 588#[derive(Debug, Clone, Eq, PartialEq)]
@@ -699,7 +628,7 @@ pub struct Const {
699 /// const _: () = (); 628 /// const _: () = ();
700 pub name: Option<Name>, 629 pub name: Option<Name>,
701 pub visibility: RawVisibilityId, 630 pub visibility: RawVisibilityId,
702 pub type_ref: Idx<TypeRef>, 631 pub type_ref: Interned<TypeRef>,
703 pub ast_id: FileAstId<ast::Const>, 632 pub ast_id: FileAstId<ast::Const>,
704} 633}
705 634
@@ -710,7 +639,7 @@ pub struct Static {
710 pub mutable: bool, 639 pub mutable: bool,
711 /// Whether the static is in an `extern` block. 640 /// Whether the static is in an `extern` block.
712 pub is_extern: bool, 641 pub is_extern: bool,
713 pub type_ref: Idx<TypeRef>, 642 pub type_ref: Interned<TypeRef>,
714 pub ast_id: FileAstId<ast::Static>, 643 pub ast_id: FileAstId<ast::Static>,
715} 644}
716 645
@@ -729,8 +658,8 @@ pub struct Trait {
729#[derive(Debug, Clone, Eq, PartialEq)] 658#[derive(Debug, Clone, Eq, PartialEq)]
730pub struct Impl { 659pub struct Impl {
731 pub generic_params: GenericParamsId, 660 pub generic_params: GenericParamsId,
732 pub target_trait: Option<Idx<TraitRef>>, 661 pub target_trait: Option<Interned<TraitRef>>,
733 pub self_ty: Idx<TypeRef>, 662 pub self_ty: Interned<TypeRef>,
734 pub is_negative: bool, 663 pub is_negative: bool,
735 pub items: Box<[AssocItem]>, 664 pub items: Box<[AssocItem]>,
736 pub ast_id: FileAstId<ast::Impl>, 665 pub ast_id: FileAstId<ast::Impl>,
@@ -743,7 +672,7 @@ pub struct TypeAlias {
743 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. 672 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
744 pub bounds: Box<[TypeBound]>, 673 pub bounds: Box<[TypeBound]>,
745 pub generic_params: GenericParamsId, 674 pub generic_params: GenericParamsId,
746 pub type_ref: Option<Idx<TypeRef>>, 675 pub type_ref: Option<Interned<TypeRef>>,
747 pub is_extern: bool, 676 pub is_extern: bool,
748 pub ast_id: FileAstId<ast::TypeAlias>, 677 pub ast_id: FileAstId<ast::TypeAlias>,
749} 678}
@@ -768,7 +697,7 @@ pub enum ModKind {
768#[derive(Debug, Clone, Eq, PartialEq)] 697#[derive(Debug, Clone, Eq, PartialEq)]
769pub struct MacroCall { 698pub struct MacroCall {
770 /// Path to the called macro. 699 /// Path to the called macro.
771 pub path: ModPath, 700 pub path: Interned<ModPath>,
772 pub ast_id: FileAstId<ast::MacroCall>, 701 pub ast_id: FileAstId<ast::MacroCall>,
773} 702}
774 703
@@ -933,6 +862,6 @@ pub enum Fields {
933#[derive(Debug, Clone, PartialEq, Eq)] 862#[derive(Debug, Clone, PartialEq, Eq)]
934pub struct Field { 863pub struct Field {
935 pub name: Name, 864 pub name: Name,
936 pub type_ref: Idx<TypeRef>, 865 pub type_ref: Interned<TypeRef>,
937 pub visibility: RawVisibilityId, 866 pub visibility: RawVisibilityId,
938} 867}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 124dcc866..39e8403b0 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -362,7 +362,7 @@ impl Ctx {
362 } 362 }
363 } 363 }
364 }; 364 };
365 let ty = self.data().type_refs.intern(self_type); 365 let ty = Interned::new(self_type);
366 let idx = self.data().params.alloc(Param::Normal(ty)); 366 let idx = self.data().params.alloc(Param::Normal(ty));
367 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); 367 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene));
368 has_self_param = true; 368 has_self_param = true;
@@ -372,7 +372,7 @@ impl Ctx {
372 Some(_) => self.data().params.alloc(Param::Varargs), 372 Some(_) => self.data().params.alloc(Param::Varargs),
373 None => { 373 None => {
374 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); 374 let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty());
375 let ty = self.data().type_refs.intern(type_ref); 375 let ty = Interned::new(type_ref);
376 self.data().params.alloc(Param::Normal(ty)) 376 self.data().params.alloc(Param::Normal(ty))
377 } 377 }
378 }; 378 };
@@ -395,41 +395,51 @@ impl Ctx {
395 ret_type 395 ret_type
396 }; 396 };
397 397
398 let ret_type = self.data().type_refs.intern(ret_type); 398 let abi = func.abi().map(|abi| {
399 399 // FIXME: Abi::abi() -> Option<SyntaxToken>?
400 let has_body = func.body().is_some(); 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 });
401 411
402 let ast_id = self.source_ast_id_map.ast_id(func); 412 let ast_id = self.source_ast_id_map.ast_id(func);
403 let qualifier = FunctionQualifier { 413
404 is_default: func.default_token().is_some(), 414 let mut flags = FnFlags::empty();
405 is_const: func.const_token().is_some(), 415 if func.body().is_some() {
406 is_async: func.async_token().is_some(), 416 flags |= FnFlags::HAS_BODY;
407 is_unsafe: func.unsafe_token().is_some(), 417 }
408 abi: func.abi().map(|abi| { 418 if has_self_param {
409 // FIXME: Abi::abi() -> Option<SyntaxToken>? 419 flags |= FnFlags::HAS_SELF_PARAM;
410 match abi.syntax().last_token() { 420 }
411 Some(tok) if tok.kind() == SyntaxKind::STRING => { 421 if func.default_token().is_some() {
412 // FIXME: Better way to unescape? 422 flags |= FnFlags::IS_DEFAULT;
413 tok.text().trim_matches('"').into() 423 }
414 } 424 if func.const_token().is_some() {
415 _ => { 425 flags |= FnFlags::IS_CONST;
416 // `extern` default to be `extern "C"`. 426 }
417 "C".into() 427 if func.async_token().is_some() {
418 } 428 flags |= FnFlags::IS_ASYNC;
419 } 429 }
420 }), 430 if func.unsafe_token().is_some() {
421 }; 431 flags |= FnFlags::IS_UNSAFE;
432 }
433
422 let mut res = Function { 434 let mut res = Function {
423 name, 435 name,
424 visibility, 436 visibility,
425 generic_params: GenericParamsId::EMPTY, 437 generic_params: GenericParamsId::EMPTY,
426 has_self_param, 438 abi,
427 has_body,
428 qualifier,
429 is_in_extern_block: false,
430 params, 439 params,
431 ret_type, 440 ret_type: Interned::new(ret_type),
432 ast_id, 441 ast_id,
442 flags,
433 }; 443 };
434 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); 444 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
435 445
@@ -579,7 +589,7 @@ impl Ctx {
579 &self.hygiene, 589 &self.hygiene,
580 |path, _use_tree, is_glob, alias| { 590 |path, _use_tree, is_glob, alias| {
581 imports.push(id(tree.imports.alloc(Import { 591 imports.push(id(tree.imports.alloc(Import {
582 path, 592 path: Interned::new(path),
583 alias, 593 alias,
584 visibility, 594 visibility,
585 is_glob, 595 is_glob,
@@ -608,7 +618,7 @@ impl Ctx {
608 } 618 }
609 619
610 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 620 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
611 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 621 let path = Interned::new(ModPath::from_src(m.path()?, &self.hygiene)?);
612 let ast_id = self.source_ast_id_map.ast_id(m); 622 let ast_id = self.source_ast_id_map.ast_id(m);
613 let res = MacroCall { path, ast_id }; 623 let res = MacroCall { path, ast_id };
614 Some(id(self.data().macro_calls.alloc(res))) 624 Some(id(self.data().macro_calls.alloc(res)))
@@ -642,8 +652,10 @@ impl Ctx {
642 ast::ExternItem::Fn(ast) => { 652 ast::ExternItem::Fn(ast) => {
643 let func_id = self.lower_function(&ast)?; 653 let func_id = self.lower_function(&ast)?;
644 let func = &mut self.data().functions[func_id.index]; 654 let func = &mut self.data().functions[func_id.index];
645 func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); 655 if is_intrinsic_fn_unsafe(&func.name) {
646 func.is_in_extern_block = true; 656 func.flags |= FnFlags::IS_UNSAFE;
657 }
658 func.flags |= FnFlags::IS_IN_EXTERN_BLOCK;
647 func_id.into() 659 func_id.into()
648 } 660 }
649 ast::ExternItem::Static(ast) => { 661 ast::ExternItem::Static(ast) => {
@@ -694,8 +706,7 @@ impl Ctx {
694 generics.fill(&self.body_ctx, sm, node); 706 generics.fill(&self.body_ctx, sm, node);
695 // lower `impl Trait` in arguments 707 // lower `impl Trait` in arguments
696 for id in func.params.clone() { 708 for id in func.params.clone() {
697 if let Param::Normal(ty) = self.data().params[id] { 709 if let Param::Normal(ty) = &self.data().params[id] {
698 let ty = self.data().type_refs.lookup(ty);
699 generics.fill_implicit_impl_trait_args(ty); 710 generics.fill_implicit_impl_trait_args(ty);
700 } 711 }
701 } 712 }
@@ -749,20 +760,20 @@ impl Ctx {
749 self.data().vis.alloc(vis) 760 self.data().vis.alloc(vis)
750 } 761 }
751 762
752 fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Idx<TraitRef>> { 763 fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Interned<TraitRef>> {
753 let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?; 764 let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
754 Some(self.data().trait_refs.intern(trait_ref)) 765 Some(Interned::new(trait_ref))
755 } 766 }
756 767
757 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { 768 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Interned<TypeRef> {
758 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); 769 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
759 self.data().type_refs.intern(tyref) 770 Interned::new(tyref)
760 } 771 }
761 772
762 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { 773 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Interned<TypeRef> {
763 match type_ref.map(|ty| self.lower_type_ref(&ty)) { 774 match type_ref.map(|ty| self.lower_type_ref(&ty)) {
764 Some(it) => it, 775 Some(it) => it,
765 None => self.data().type_refs.intern(TypeRef::Error), 776 None => Interned::new(TypeRef::Error),
766 } 777 }
767 } 778 }
768 779
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index c9e07de86..f408e510a 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -49,6 +49,7 @@ pub mod import_map;
49 49
50#[cfg(test)] 50#[cfg(test)]
51mod test_db; 51mod test_db;
52mod intern;
52 53
53use std::{ 54use std::{
54 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 d58135ec9..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,
@@ -54,20 +55,22 @@ pub(super) fn collect_defs(
54) -> DefMap { 55) -> DefMap {
55 let crate_graph = db.crate_graph(); 56 let crate_graph = db.crate_graph();
56 57
57 // populate external prelude 58 if block.is_none() {
58 for dep in &crate_graph[def_map.krate].dependencies { 59 // populate external prelude
59 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id); 60 for dep in &crate_graph[def_map.krate].dependencies {
60 let dep_def_map = db.crate_def_map(dep.crate_id); 61 log::debug!("crate dep {:?} -> {:?}", dep.name, dep.crate_id);
61 def_map 62 let dep_def_map = db.crate_def_map(dep.crate_id);
62 .extern_prelude 63 def_map
63 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into()); 64 .extern_prelude
64 65 .insert(dep.as_name(), dep_def_map.module_id(dep_def_map.root).into());
65 // look for the prelude 66
66 // If the dependency defines a prelude, we overwrite an already defined 67 // look for the prelude
67 // prelude. This is necessary to import the "std" prelude if a crate 68 // If the dependency defines a prelude, we overwrite an already defined
68 // depends on both "core" and "std". 69 // prelude. This is necessary to import the "std" prelude if a crate
69 if dep_def_map.prelude.is_some() { 70 // depends on both "core" and "std".
70 def_map.prelude = dep_def_map.prelude; 71 if dep_def_map.prelude.is_some() {
72 def_map.prelude = dep_def_map.prelude;
73 }
71 } 74 }
72 } 75 }
73 76
@@ -106,7 +109,9 @@ pub(super) fn collect_defs(
106 } 109 }
107 } 110 }
108 collector.collect(); 111 collector.collect();
109 collector.finish() 112 let mut def_map = collector.finish();
113 def_map.shrink_to_fit();
114 def_map
110} 115}
111 116
112#[derive(Copy, Clone, Debug, Eq, PartialEq)] 117#[derive(Copy, Clone, Debug, Eq, PartialEq)]
@@ -137,7 +142,7 @@ enum ImportSource {
137 142
138#[derive(Clone, Debug, Eq, PartialEq)] 143#[derive(Clone, Debug, Eq, PartialEq)]
139struct Import { 144struct Import {
140 path: ModPath, 145 path: Interned<ModPath>,
141 alias: Option<ImportAlias>, 146 alias: Option<ImportAlias>,
142 visibility: RawVisibility, 147 visibility: RawVisibility,
143 is_glob: bool, 148 is_glob: bool,
@@ -179,7 +184,10 @@ impl Import {
179 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into()); 184 let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
180 let visibility = &tree[it.visibility]; 185 let visibility = &tree[it.visibility];
181 Self { 186 Self {
182 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 )),
183 alias: it.alias.clone(), 191 alias: it.alias.clone(),
184 visibility: visibility.clone(), 192 visibility: visibility.clone(),
185 is_glob: false, 193 is_glob: false,
@@ -1400,8 +1408,18 @@ impl ModCollector<'_, '_> {
1400 1408
1401 // Case 1: builtin macros 1409 // Case 1: builtin macros
1402 if attrs.by_key("rustc_builtin_macro").exists() { 1410 if attrs.by_key("rustc_builtin_macro").exists() {
1411 // `#[rustc_builtin_macro = "builtin_name"]` overrides the `macro_rules!` name.
1412 let name;
1413 let name = match attrs.by_key("rustc_builtin_macro").string_value() {
1414 Some(it) => {
1415 // FIXME: a hacky way to create a Name from string.
1416 name = tt::Ident { text: it.clone(), id: tt::TokenId::unspecified() }.as_name();
1417 &name
1418 }
1419 None => &mac.name,
1420 };
1403 let krate = self.def_collector.def_map.krate; 1421 let krate = self.def_collector.def_map.krate;
1404 if let Some(macro_id) = find_builtin_macro(&mac.name, krate, ast_id) { 1422 if let Some(macro_id) = find_builtin_macro(name, krate, ast_id) {
1405 self.def_collector.define_macro_rules( 1423 self.def_collector.define_macro_rules(
1406 self.module_id, 1424 self.module_id,
1407 mac.name.clone(), 1425 mac.name.clone(),
@@ -1464,7 +1482,7 @@ impl ModCollector<'_, '_> {
1464 } 1482 }
1465 1483
1466 fn collect_macro_call(&mut self, mac: &MacroCall) { 1484 fn collect_macro_call(&mut self, mac: &MacroCall) {
1467 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, mac.path.clone()); 1485 let mut ast_id = AstIdWithPath::new(self.file_id, mac.ast_id, (*mac.path).clone());
1468 1486
1469 // Case 1: try to resolve in legacy scope and expand macro_rules 1487 // Case 1: try to resolve in legacy scope and expand macro_rules
1470 let mut error = None; 1488 let mut error = None;
diff --git a/crates/hir_def/src/nameres/tests/diagnostics.rs b/crates/hir_def/src/nameres/tests/diagnostics.rs
index a89061c2e..fefdadb22 100644
--- a/crates/hir_def/src/nameres/tests/diagnostics.rs
+++ b/crates/hir_def/src/nameres/tests/diagnostics.rs
@@ -7,6 +7,11 @@ fn check_diagnostics(ra_fixture: &str) {
7 db.check_diagnostics(); 7 db.check_diagnostics();
8} 8}
9 9
10fn check_no_diagnostics(ra_fixture: &str) {
11 let db: TestDB = TestDB::with_files(ra_fixture);
12 db.check_no_diagnostics();
13}
14
10#[test] 15#[test]
11fn unresolved_import() { 16fn unresolved_import() {
12 check_diagnostics( 17 check_diagnostics(
@@ -202,6 +207,21 @@ fn builtin_macro_fails_expansion() {
202} 207}
203 208
204#[test] 209#[test]
210fn include_macro_should_allow_empty_content() {
211 check_no_diagnostics(
212 r#"
213 //- /lib.rs
214 #[rustc_builtin_macro]
215 macro_rules! include { () => {} }
216
217 include!("bar.rs");
218 //- /bar.rs
219 // empty
220 "#,
221 );
222}
223
224#[test]
205fn good_out_dir_diagnostic() { 225fn good_out_dir_diagnostic() {
206 check_diagnostics( 226 check_diagnostics(
207 r#" 227 r#"
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs
index 8c923bb7b..a3e83e2cf 100644
--- a/crates/hir_def/src/path.rs
+++ b/crates/hir_def/src/path.rs
@@ -7,7 +7,7 @@ use std::{
7 sync::Arc, 7 sync::Arc,
8}; 8};
9 9
10use crate::{body::LowerCtx, type_ref::LifetimeRef}; 10use crate::{body::LowerCtx, intern::Interned, type_ref::LifetimeRef};
11use base_db::CrateId; 11use base_db::CrateId;
12use hir_expand::{ 12use hir_expand::{
13 hygiene::Hygiene, 13 hygiene::Hygiene,
@@ -48,7 +48,7 @@ pub enum ImportAlias {
48 48
49impl ModPath { 49impl ModPath {
50 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { 50 pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> {
51 lower::lower_path(path, hygiene).map(|it| it.mod_path) 51 lower::lower_path(path, hygiene).map(|it| (*it.mod_path).clone())
52 } 52 }
53 53
54 pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath { 54 pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath {
@@ -123,7 +123,7 @@ pub struct Path {
123 /// Type based path like `<T>::foo`. 123 /// Type based path like `<T>::foo`.
124 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. 124 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
125 type_anchor: Option<Box<TypeRef>>, 125 type_anchor: Option<Box<TypeRef>>,
126 mod_path: 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>>>,
129} 129}
@@ -176,7 +176,7 @@ impl Path {
176 path: ModPath, 176 path: ModPath,
177 generic_args: Vec<Option<Arc<GenericArgs>>>, 177 generic_args: Vec<Option<Arc<GenericArgs>>>,
178 ) -> Path { 178 ) -> Path {
179 Path { type_anchor: None, mod_path: path, generic_args } 179 Path { type_anchor: None, mod_path: Interned::new(path), generic_args }
180 } 180 }
181 181
182 pub fn kind(&self) -> &PathKind { 182 pub fn kind(&self) -> &PathKind {
@@ -204,10 +204,10 @@ impl Path {
204 } 204 }
205 let res = Path { 205 let res = Path {
206 type_anchor: self.type_anchor.clone(), 206 type_anchor: self.type_anchor.clone(),
207 mod_path: ModPath::from_segments( 207 mod_path: Interned::new(ModPath::from_segments(
208 self.mod_path.kind.clone(), 208 self.mod_path.kind.clone(),
209 self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(), 209 self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(),
210 ), 210 )),
211 generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), 211 generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(),
212 }; 212 };
213 Some(res) 213 Some(res)
@@ -283,7 +283,7 @@ impl From<Name> for Path {
283 fn from(name: Name) -> Path { 283 fn from(name: Name) -> Path {
284 Path { 284 Path {
285 type_anchor: None, 285 type_anchor: None,
286 mod_path: ModPath::from_segments(PathKind::Plain, iter::once(name)), 286 mod_path: Interned::new(ModPath::from_segments(PathKind::Plain, iter::once(name))),
287 generic_args: vec![None], 287 generic_args: vec![None],
288 } 288 }
289 } 289 }
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs
index 4de951fd3..28f6244da 100644
--- a/crates/hir_def/src/path/lower.rs
+++ b/crates/hir_def/src/path/lower.rs
@@ -2,6 +2,7 @@
2 2
3mod lower_use; 3mod lower_use;
4 4
5use crate::intern::Interned;
5use std::sync::Arc; 6use std::sync::Arc;
6 7
7use either::Either; 8use either::Either;
@@ -74,10 +75,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
74 // <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
75 Some(trait_ref) => { 76 Some(trait_ref) => {
76 let path = Path::from_src(trait_ref.path()?, hygiene)?; 77 let path = Path::from_src(trait_ref.path()?, hygiene)?;
78 let mod_path = (*path.mod_path).clone();
77 let num_segments = path.mod_path.segments.len(); 79 let num_segments = path.mod_path.segments.len();
78 kind = path.mod_path.kind; 80 kind = mod_path.kind;
79 81
80 let mut prefix_segments = path.mod_path.segments; 82 let mut prefix_segments = mod_path.segments;
81 prefix_segments.reverse(); 83 prefix_segments.reverse();
82 segments.extend(prefix_segments); 84 segments.extend(prefix_segments);
83 85
@@ -140,7 +142,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
140 } 142 }
141 } 143 }
142 144
143 let mod_path = ModPath::from_segments(kind, segments); 145 let mod_path = Interned::new(ModPath::from_segments(kind, segments));
144 return Some(Path { type_anchor, mod_path, generic_args }); 146 return Some(Path { type_anchor, mod_path, generic_args });
145 147
146 fn qualifier(path: &ast::Path) -> Option<ast::Path> { 148 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs
index 10977761c..dd36106f8 100644
--- a/crates/hir_def/src/test_db.rs
+++ b/crates/hir_def/src/test_db.rs
@@ -265,4 +265,17 @@ impl TestDB {
265 265
266 assert_eq!(annotations, actual); 266 assert_eq!(annotations, actual);
267 } 267 }
268
269 pub(crate) fn check_no_diagnostics(&self) {
270 let db: &TestDB = self;
271 let annotations = db.extract_annotations();
272 assert!(annotations.is_empty());
273
274 let mut has_diagnostics = false;
275 db.diagnostics(|_| {
276 has_diagnostics = true;
277 });
278
279 assert!(!has_diagnostics);
280 }
268} 281}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 4d52904b9..75ec4196b 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -1,10 +1,10 @@
1//! Builtin macro 1//! Builtin macro
2use crate::{ 2use crate::{
3 db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId, 3 db::AstDatabase, name, quote, AstId, CrateId, EagerMacroId, LazyMacroId, MacroCallId,
4 MacroDefId, MacroDefKind, TextSize, 4 MacroCallLoc, MacroDefId, MacroDefKind, TextSize,
5}; 5};
6 6
7use base_db::{AnchoredPath, FileId}; 7use base_db::{AnchoredPath, Edition, FileId};
8use cfg::CfgExpr; 8use cfg::CfgExpr;
9use either::Either; 9use either::Either;
10use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; 10use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult};
@@ -111,6 +111,8 @@ register_builtin! {
111 (llvm_asm, LlvmAsm) => asm_expand, 111 (llvm_asm, LlvmAsm) => asm_expand,
112 (asm, Asm) => asm_expand, 112 (asm, Asm) => asm_expand,
113 (cfg, Cfg) => cfg_expand, 113 (cfg, Cfg) => cfg_expand,
114 (core_panic, CorePanic) => panic_expand,
115 (std_panic, StdPanic) => panic_expand,
114 116
115 EAGER: 117 EAGER:
116 (compile_error, CompileError) => compile_error_expand, 118 (compile_error, CompileError) => compile_error_expand,
@@ -284,6 +286,25 @@ fn cfg_expand(
284 ExpandResult::ok(expanded) 286 ExpandResult::ok(expanded)
285} 287}
286 288
289fn panic_expand(
290 db: &dyn AstDatabase,
291 id: LazyMacroId,
292 tt: &tt::Subtree,
293) -> ExpandResult<tt::Subtree> {
294 let loc: MacroCallLoc = db.lookup_intern_macro(id);
295 // Expand to a macro call `$crate::panic::panic_{edition}`
296 let krate = tt::Ident { text: "$crate".into(), id: tt::TokenId::unspecified() };
297 let mut call = if db.crate_graph()[loc.krate].edition == Edition::Edition2021 {
298 quote!(#krate::panic::panic_2021!)
299 } else {
300 quote!(#krate::panic::panic_2015!)
301 };
302
303 // Pass the original arguments
304 call.token_trees.push(tt::TokenTree::Subtree(tt.clone()));
305 ExpandResult::ok(call)
306}
307
287fn unquote_str(lit: &tt::Literal) -> Option<String> { 308fn unquote_str(lit: &tt::Literal) -> Option<String> {
288 let lit = ast::make::tokens::literal(&lit.to_string()); 309 let lit = ast::make::tokens::literal(&lit.to_string());
289 let token = ast::String::cast(lit)?; 310 let token = ast::String::cast(lit)?;
@@ -563,7 +584,7 @@ mod tests {
563 }; 584 };
564 585
565 let args = macro_call.token_tree().unwrap(); 586 let args = macro_call.token_tree().unwrap();
566 let parsed_args = mbe::ast_to_token_tree(&args).unwrap().0; 587 let parsed_args = mbe::ast_to_token_tree(&args).0;
567 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));
568 589
569 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_expand/src/name.rs b/crates/hir_expand/src/name.rs
index 203ebbe85..a0f8766b0 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -208,6 +208,8 @@ pub mod known {
208 line, 208 line,
209 module_path, 209 module_path,
210 assert, 210 assert,
211 core_panic,
212 std_panic,
211 stringify, 213 stringify,
212 concat, 214 concat,
213 include, 215 include,
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs
index 08bc5aa49..c82487ef0 100644
--- a/crates/hir_expand/src/quote.rs
+++ b/crates/hir_expand/src/quote.rs
@@ -104,6 +104,7 @@ macro_rules! __quote {
104 ( . ) => {$crate::__quote!(@PUNCT '.')}; 104 ( . ) => {$crate::__quote!(@PUNCT '.')};
105 ( < ) => {$crate::__quote!(@PUNCT '<')}; 105 ( < ) => {$crate::__quote!(@PUNCT '<')};
106 ( > ) => {$crate::__quote!(@PUNCT '>')}; 106 ( > ) => {$crate::__quote!(@PUNCT '>')};
107 ( ! ) => {$crate::__quote!(@PUNCT '!')};
107 108
108 ( $first:tt $($tail:tt)+ ) => { 109 ( $first:tt $($tail:tt)+ ) => {
109 { 110 {
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs
index dc5fc759a..70c56cc45 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -13,11 +13,9 @@ use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase,
16 to_assoc_type_id, to_chalk_trait_id,
17 traits::{InEnvironment, Solution}, 16 traits::{InEnvironment, Solution},
18 utils::generics, 17 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, 18 TyBuilder, TyKind,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 19};
22 20
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 21const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +55,20 @@ fn deref_by_trait(
57 }; 55 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 56 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 57
60 let generic_params = generics(db.upcast(), target.into()); 58 let projection = {
61 if generic_params.len() != 1 { 59 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 60 if b.remaining() != 1 {
63 // namely Deref's Self type 61 // the Target type + Deref trait should only have one generic parameter,
64 return None; 62 // namely Deref's Self type
65 } 63 return None;
64 }
65 b.push(ty.goal.value.clone()).build()
66 };
66 67
67 // FIXME make the Canonical / bound var handling nicer 68 // FIXME make the Canonical / bound var handling nicer
68 69
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 70 // Check that the type implements Deref at all
73 let trait_ref = 71 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 { 72 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 73 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 74 value: InEnvironment {
@@ -84,11 +81,8 @@ fn deref_by_trait(
84 } 81 }
85 82
86 // Now do the assoc type projection 83 // Now do the assoc type projection
87 let projection = AliasEq { 84 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 85 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 86 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 87 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 88 ty.goal.binders.len(&Interner),
@@ -96,9 +90,7 @@ fn deref_by_trait(
96 .intern(&Interner), 90 .intern(&Interner),
97 }; 91 };
98 92
99 let obligation = projection.cast(&Interner); 93 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 94
103 let canonical = Canonical { 95 let canonical = Canonical {
104 value: in_env, 96 value: in_env,
@@ -131,7 +123,7 @@ fn deref_by_trait(
131 // new variables in that case 123 // new variables in that case
132 124
133 for i in 1..vars.0.binders.len(&Interner) { 125 for i in 1..vars.0.binders.len(&Interner) {
134 if vars.0.value[i - 1].interned(&Interner) 126 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 127 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
136 { 128 {
137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 129 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -139,7 +131,12 @@ fn deref_by_trait(
139 } 131 }
140 } 132 }
141 Some(Canonical { 133 Some(Canonical {
142 value: vars.0.value[vars.0.value.len() - 1].clone(), 134 value: vars
135 .0
136 .value
137 .at(&Interner, vars.0.value.len(&Interner) - 1)
138 .assert_ty_ref(&Interner)
139 .clone(),
143 binders: vars.0.binders.clone(), 140 binders: vars.0.binders.clone(),
144 }) 141 })
145 } 142 }
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs
new file mode 100644
index 000000000..4a9a8058f
--- /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(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(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_cast.rs b/crates/hir_ty/src/chalk_cast.rs
index bf884ae15..df6492113 100644
--- a/crates/hir_ty/src/chalk_cast.rs
+++ b/crates/hir_ty/src/chalk_cast.rs
@@ -5,7 +5,7 @@ use chalk_ir::{
5 interner::HasInterner, 5 interner::HasInterner,
6}; 6};
7 7
8use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; 8use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause};
9 9
10macro_rules! has_interner { 10macro_rules! has_interner {
11 ($t:ty) => { 11 ($t:ty) => {
@@ -17,6 +17,8 @@ macro_rules! has_interner {
17 17
18has_interner!(WhereClause); 18has_interner!(WhereClause);
19has_interner!(DomainGoal); 19has_interner!(DomainGoal);
20has_interner!(GenericArg);
21has_interner!(Ty);
20 22
21impl CastTo<WhereClause> for TraitRef { 23impl CastTo<WhereClause> for TraitRef {
22 fn cast_to(self, _interner: &Interner) -> WhereClause { 24 fn cast_to(self, _interner: &Interner) -> WhereClause {
@@ -36,6 +38,12 @@ impl CastTo<DomainGoal> for WhereClause {
36 } 38 }
37} 39}
38 40
41impl CastTo<GenericArg> for Ty {
42 fn cast_to(self, interner: &Interner) -> GenericArg {
43 GenericArg::new(interner, GenericArgData::Ty(self))
44 }
45}
46
39macro_rules! transitive_impl { 47macro_rules! transitive_impl {
40 ($a:ty, $b:ty, $c:ty) => { 48 ($a:ty, $b:ty, $c:ty) => {
41 impl CastTo<$c> for $a { 49 impl CastTo<$c> for $a {
@@ -51,3 +59,15 @@ macro_rules! transitive_impl {
51 59
52transitive_impl!(TraitRef, WhereClause, DomainGoal); 60transitive_impl!(TraitRef, WhereClause, DomainGoal);
53transitive_impl!(AliasEq, WhereClause, DomainGoal); 61transitive_impl!(AliasEq, WhereClause, DomainGoal);
62
63macro_rules! reflexive_impl {
64 ($a:ty) => {
65 impl CastTo<$a> for $a {
66 fn cast_to(self, _interner: &Interner) -> $a {
67 self
68 }
69 }
70 };
71}
72
73reflexive_impl!(GenericArg);
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/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 3909ad354..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::{
@@ -378,7 +378,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
378 _ => return, 378 _ => return,
379 }; 379 };
380 380
381 let (params, required) = match mismatch.expected.interned(&Interner) { 381 let (params, required) = match mismatch.expected.kind(&Interner) {
382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) 382 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters)
383 if *enum_id == core_result_enum => 383 if *enum_id == core_result_enum =>
384 { 384 {
@@ -392,7 +392,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
392 _ => return, 392 _ => return,
393 }; 393 };
394 394
395 if params.len() > 0 && params[0] == mismatch.actual { 395 if params.len(&Interner) > 0
396 && params.at(&Interner, 0).ty(&Interner) == Some(&mismatch.actual)
397 {
396 let (_, source_map) = db.body_with_source_map(self.owner); 398 let (_, source_map) = db.body_with_source_map(self.owner);
397 399
398 if let Ok(source_ptr) = source_map.expr_syntax(id) { 400 if let Ok(source_ptr) = source_map.expr_syntax(id) {
@@ -421,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> {
421 None => return, 423 None => return,
422 }; 424 };
423 425
424 if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { 426 if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty {
425 return; 427 return;
426 } 428 }
427 429
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs
index 9cb472b51..34291578a 100644
--- a/crates/hir_ty/src/diagnostics/match_check.rs
+++ b/crates/hir_ty/src/diagnostics/match_check.rs
@@ -626,7 +626,7 @@ pub(super) fn is_useful(
626 // - enum with no variants 626 // - enum with no variants
627 // - `!` type 627 // - `!` type
628 // In those cases, no match arm is useful. 628 // In those cases, no match arm is useful.
629 match cx.infer[cx.match_expr].strip_references().interned(&Interner) { 629 match cx.infer[cx.match_expr].strip_references().kind(&Interner) {
630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { 630 TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => {
631 if cx.db.enum_data(*enum_id).variants.is_empty() { 631 if cx.db.enum_data(*enum_id).variants.is_empty() {
632 return Ok(Usefulness::NotUseful); 632 return Ok(Usefulness::NotUseful);
@@ -792,7 +792,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Opt
792 Pat::Tuple { .. } => { 792 Pat::Tuple { .. } => {
793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); 793 let pat_id = pat.as_id().expect("we already know this pattern is not a wild");
794 Some(Constructor::Tuple { 794 Some(Constructor::Tuple {
795 arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), 795 arity: cx.infer.type_of_pat[pat_id]
796 .as_tuple()
797 .ok_or(MatchCheckErr::Unknown)?
798 .len(&Interner),
796 }) 799 })
797 } 800 }
798 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { 801 Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] {
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs
index 1f49a4909..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,14 +103,14 @@ 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 });
110 } 110 }
111 } 111 }
112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => { 112 Expr::UnaryOp { expr, op: UnaryOp::Deref } => {
113 if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) { 113 if let TyKind::Raw(..) = &infer[*expr].kind(&Interner) {
114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); 114 unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
115 } 115 }
116 } 116 }
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs
index 51480304b..385bd9405 100644
--- a/crates/hir_ty/src/display.rs
+++ b/crates/hir_ty/src/display.rs
@@ -8,7 +8,7 @@ use hir_def::{
8 find_path, 8 find_path,
9 generics::TypeParamProvenance, 9 generics::TypeParamProvenance,
10 item_scope::ItemInNs, 10 item_scope::ItemInNs,
11 path::{GenericArg, Path, PathKind}, 11 path::{Path, PathKind},
12 type_ref::{TypeBound, TypeRef}, 12 type_ref::{TypeBound, TypeRef},
13 visibility::Visibility, 13 visibility::Visibility,
14 AssocContainerId, Lookup, ModuleId, TraitId, 14 AssocContainerId, Lookup, ModuleId, TraitId,
@@ -18,8 +18,8 @@ use hir_expand::name::Name;
18use crate::{ 18use 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, 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> {
@@ -251,16 +251,16 @@ impl HirDisplay for ProjectionTy {
251 } 251 }
252 252
253 let trait_ = f.db.trait_data(self.trait_(f.db)); 253 let trait_ = f.db.trait_data(self.trait_(f.db));
254 let first_parameter = self.substitution[0].into_displayable( 254 let first_parameter = self.self_type_parameter().into_displayable(
255 f.db, 255 f.db,
256 f.max_size, 256 f.max_size,
257 f.omit_verbose_types, 257 f.omit_verbose_types,
258 f.display_target, 258 f.display_target,
259 ); 259 );
260 write!(f, "<{} as {}", first_parameter, trait_.name)?; 260 write!(f, "<{} as {}", first_parameter, trait_.name)?;
261 if self.substitution.len() > 1 { 261 if self.substitution.len(&Interner) > 1 {
262 write!(f, "<")?; 262 write!(f, "<")?;
263 f.write_joined(&self.substitution[1..], ", ")?; 263 f.write_joined(&self.substitution.interned(&Interner)[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)?;
@@ -274,7 +274,15 @@ impl HirDisplay for OpaqueTy {
274 return write!(f, "{}", TYPE_HINT_TRUNCATION); 274 return write!(f, "{}", TYPE_HINT_TRUNCATION);
275 } 275 }
276 276
277 self.substitution[0].hir_fmt(f) 277 self.substitution.at(&Interner, 0).hir_fmt(f)
278 }
279}
280
281impl HirDisplay for GenericArg {
282 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
283 match self.interned() {
284 crate::GenericArgData::Ty(ty) => ty.hir_fmt(f),
285 }
278 } 286 }
279} 287}
280 288
@@ -284,7 +292,7 @@ impl HirDisplay for Ty {
284 return write!(f, "{}", TYPE_HINT_TRUNCATION); 292 return write!(f, "{}", TYPE_HINT_TRUNCATION);
285 } 293 }
286 294
287 match self.interned(&Interner) { 295 match self.kind(&Interner) {
288 TyKind::Never => write!(f, "!")?, 296 TyKind::Never => write!(f, "!")?,
289 TyKind::Str => write!(f, "str")?, 297 TyKind::Str => write!(f, "str")?,
290 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, 298 TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?,
@@ -306,7 +314,7 @@ impl HirDisplay for Ty {
306 let ty_display = 314 let ty_display =
307 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); 315 t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target);
308 316
309 if matches!(self.interned(&Interner), TyKind::Raw(..)) { 317 if matches!(self.kind(&Interner), TyKind::Raw(..)) {
310 write!( 318 write!(
311 f, 319 f,
312 "*{}", 320 "*{}",
@@ -328,7 +336,7 @@ impl HirDisplay for Ty {
328 336
329 // FIXME: all this just to decide whether to use parentheses... 337 // FIXME: all this just to decide whether to use parentheses...
330 let datas; 338 let datas;
331 let predicates: Vec<_> = match t.interned(&Interner) { 339 let predicates: Vec<_> = match t.kind(&Interner) {
332 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { 340 TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => {
333 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() 341 dyn_ty.bounds.skip_binders().interned().iter().cloned().collect()
334 } 342 }
@@ -373,9 +381,9 @@ impl HirDisplay for Ty {
373 } 381 }
374 } 382 }
375 TyKind::Tuple(_, substs) => { 383 TyKind::Tuple(_, substs) => {
376 if substs.len() == 1 { 384 if substs.len(&Interner) == 1 {
377 write!(f, "(")?; 385 write!(f, "(")?;
378 substs[0].hir_fmt(f)?; 386 substs.at(&Interner, 0).hir_fmt(f)?;
379 write!(f, ",)")?; 387 write!(f, ",)")?;
380 } else { 388 } else {
381 write!(f, "(")?; 389 write!(f, "(")?;
@@ -399,7 +407,7 @@ impl HirDisplay for Ty {
399 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? 407 write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)?
400 } 408 }
401 }; 409 };
402 if parameters.len() > 0 { 410 if parameters.len(&Interner) > 0 {
403 let generics = generics(f.db.upcast(), def.into()); 411 let generics = generics(f.db.upcast(), def.into());
404 let (parent_params, self_param, type_params, _impl_trait_params) = 412 let (parent_params, self_param, type_params, _impl_trait_params) =
405 generics.provenance_split(); 413 generics.provenance_split();
@@ -415,7 +423,7 @@ impl HirDisplay for Ty {
415 f.write_joined(sig.params(), ", ")?; 423 f.write_joined(sig.params(), ", ")?;
416 write!(f, ")")?; 424 write!(f, ")")?;
417 let ret = sig.ret(); 425 let ret = sig.ret();
418 if *ret != Ty::unit() { 426 if !ret.is_unit() {
419 let ret_display = ret.into_displayable( 427 let ret_display = ret.into_displayable(
420 f.db, 428 f.db,
421 f.max_size, 429 f.max_size,
@@ -451,7 +459,7 @@ impl HirDisplay for Ty {
451 } 459 }
452 } 460 }
453 461
454 if parameters.len() > 0 { 462 if parameters.len(&Interner) > 0 {
455 let parameters_to_write = if f.display_target.is_source_code() 463 let parameters_to_write = if f.display_target.is_source_code()
456 || f.omit_verbose_types() 464 || f.omit_verbose_types()
457 { 465 {
@@ -463,9 +471,11 @@ impl HirDisplay for Ty {
463 None => parameters.0.as_ref(), 471 None => parameters.0.as_ref(),
464 Some(default_parameters) => { 472 Some(default_parameters) => {
465 let mut default_from = 0; 473 let mut default_from = 0;
466 for (i, parameter) in parameters.iter().enumerate() { 474 for (i, parameter) in parameters.iter(&Interner).enumerate() {
467 match (parameter.interned(&Interner), default_parameters.get(i)) 475 match (
468 { 476 parameter.assert_ty_ref(&Interner).kind(&Interner),
477 default_parameters.get(i),
478 ) {
469 (&TyKind::Unknown, _) | (_, None) => { 479 (&TyKind::Unknown, _) | (_, None) => {
470 default_from = i + 1; 480 default_from = i + 1;
471 } 481 }
@@ -473,7 +483,8 @@ impl HirDisplay for Ty {
473 let actual_default = default_parameter 483 let actual_default = default_parameter
474 .clone() 484 .clone()
475 .subst(&parameters.prefix(i)); 485 .subst(&parameters.prefix(i));
476 if parameter != &actual_default { 486 if parameter.assert_ty_ref(&Interner) != &actual_default
487 {
477 default_from = i + 1; 488 default_from = i + 1;
478 } 489 }
479 } 490 }
@@ -504,7 +515,7 @@ impl HirDisplay for Ty {
504 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) 515 // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types)
505 if f.display_target.is_test() { 516 if f.display_target.is_test() {
506 write!(f, "{}::{}", trait_.name, type_alias_data.name)?; 517 write!(f, "{}::{}", trait_.name, type_alias_data.name)?;
507 if parameters.len() > 0 { 518 if parameters.len(&Interner) > 0 {
508 write!(f, "<")?; 519 write!(f, "<")?;
509 f.write_joined(&*parameters.0, ", ")?; 520 f.write_joined(&*parameters.0, ", ")?;
510 write!(f, ">")?; 521 write!(f, ">")?;
@@ -537,7 +548,7 @@ impl HirDisplay for Ty {
537 } 548 }
538 ImplTraitId::AsyncBlockTypeImplTrait(..) => { 549 ImplTraitId::AsyncBlockTypeImplTrait(..) => {
539 write!(f, "impl Future<Output = ")?; 550 write!(f, "impl Future<Output = ")?;
540 parameters[0].hir_fmt(f)?; 551 parameters.at(&Interner, 0).hir_fmt(f)?;
541 write!(f, ">")?; 552 write!(f, ">")?;
542 } 553 }
543 } 554 }
@@ -548,7 +559,7 @@ impl HirDisplay for Ty {
548 DisplaySourceCodeError::Closure, 559 DisplaySourceCodeError::Closure,
549 )); 560 ));
550 } 561 }
551 let sig = substs[0].callable_sig(f.db); 562 let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db);
552 if let Some(sig) = sig { 563 if let Some(sig) = sig {
553 if sig.params().is_empty() { 564 if sig.params().is_empty() {
554 write!(f, "||")?; 565 write!(f, "||")?;
@@ -580,7 +591,7 @@ impl HirDisplay for Ty {
580 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? 591 write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))?
581 } 592 }
582 TypeParamProvenance::ArgumentImplTrait => { 593 TypeParamProvenance::ArgumentImplTrait => {
583 let substs = Substitution::type_params_for_generics(f.db, &generics); 594 let substs = generics.type_params_subst(f.db);
584 let bounds = f 595 let bounds = f
585 .db 596 .db
586 .generic_predicates(id.parent) 597 .generic_predicates(id.parent)
@@ -652,7 +663,7 @@ impl HirDisplay for CallableSig {
652 } 663 }
653 write!(f, ")")?; 664 write!(f, ")")?;
654 let ret = self.ret(); 665 let ret = self.ret();
655 if *ret != Ty::unit() { 666 if !ret.is_unit() {
656 let ret_display = 667 let ret_display =
657 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);
658 write!(f, " -> {}", ret_display)?; 669 write!(f, " -> {}", ret_display)?;
@@ -718,7 +729,9 @@ fn write_bounds_like_dyn_trait(
718 write!(f, "{}", f.db.trait_data(trait_).name)?; 729 write!(f, "{}", f.db.trait_data(trait_).name)?;
719 if let [_, params @ ..] = &*trait_ref.substitution.0 { 730 if let [_, params @ ..] = &*trait_ref.substitution.0 {
720 if is_fn_trait { 731 if is_fn_trait {
721 if let Some(args) = params.first().and_then(|it| it.as_tuple()) { 732 if let Some(args) =
733 params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple())
734 {
722 write!(f, "(")?; 735 write!(f, "(")?;
723 f.write_joined(&*args.0, ", ")?; 736 f.write_joined(&*args.0, ", ")?;
724 write!(f, ")")?; 737 write!(f, ")")?;
@@ -767,16 +780,16 @@ impl TraitRef {
767 return write!(f, "{}", TYPE_HINT_TRUNCATION); 780 return write!(f, "{}", TYPE_HINT_TRUNCATION);
768 } 781 }
769 782
770 self.substitution[0].hir_fmt(f)?; 783 self.self_type_parameter().hir_fmt(f)?;
771 if use_as { 784 if use_as {
772 write!(f, " as ")?; 785 write!(f, " as ")?;
773 } else { 786 } else {
774 write!(f, ": ")?; 787 write!(f, ": ")?;
775 } 788 }
776 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; 789 write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?;
777 if self.substitution.len() > 1 { 790 if self.substitution.len(&Interner) > 1 {
778 write!(f, "<")?; 791 write!(f, "<")?;
779 f.write_joined(&self.substitution[1..], ", ")?; 792 f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?;
780 write!(f, ">")?; 793 write!(f, ">")?;
781 } 794 }
782 Ok(()) 795 Ok(())
@@ -1016,11 +1029,11 @@ impl HirDisplay for Path {
1016 } 1029 }
1017} 1030}
1018 1031
1019impl HirDisplay for GenericArg { 1032impl HirDisplay for hir_def::path::GenericArg {
1020 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { 1033 fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> {
1021 match self { 1034 match self {
1022 GenericArg::Type(ty) => ty.hir_fmt(f), 1035 hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f),
1023 GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), 1036 hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name),
1024 } 1037 }
1025 } 1038 }
1026} 1039}
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs
index 497a1beb7..1b1d4458c 100644
--- a/crates/hir_ty/src/infer.rs
+++ b/crates/hir_ty/src/infer.rs
@@ -38,11 +38,11 @@ use syntax::SmolStr;
38 38
39use super::{ 39use super::{
40 traits::{DomainGoal, Guidance, Solution}, 40 traits::{DomainGoal, Guidance, Solution},
41 InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, 41 InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, 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.
@@ -325,7 +325,7 @@ impl<'a> InferenceContext<'a> {
325 325
326 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. 326 /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it.
327 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { 327 fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty {
328 match ty.interned(&Interner) { 328 match ty.kind(&Interner) {
329 TyKind::Unknown => self.table.new_type_var(), 329 TyKind::Unknown => self.table.new_type_var(),
330 _ => ty, 330 _ => ty,
331 } 331 }
@@ -340,6 +340,8 @@ impl<'a> InferenceContext<'a> {
340 // no change 340 // no change
341 return; 341 return;
342 } 342 }
343 let _span = profile::span("resolve_obligations_as_possible");
344
343 self.last_obligations_check = Some(self.table.revision); 345 self.last_obligations_check = Some(self.table.revision);
344 let obligations = mem::replace(&mut self.obligations, Vec::new()); 346 let obligations = mem::replace(&mut self.obligations, Vec::new());
345 for obligation in obligations { 347 for obligation in obligations {
@@ -407,16 +409,14 @@ impl<'a> InferenceContext<'a> {
407 _ => panic!("resolve_associated_type called with non-associated type"), 409 _ => panic!("resolve_associated_type called with non-associated type"),