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.rs122
-rw-r--r--crates/hir/src/semantics.rs6
-rw-r--r--crates/hir/src/source_analyzer.rs30
-rw-r--r--crates/hir_def/Cargo.toml1
-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.rs90
-rw-r--r--crates/hir_def/src/db.rs3
-rw-r--r--crates/hir_def/src/generics.rs62
-rw-r--r--crates/hir_def/src/intern.rs205
-rw-r--r--crates/hir_def/src/item_scope.rs22
-rw-r--r--crates/hir_def/src/item_tree.rs154
-rw-r--r--crates/hir_def/src/item_tree/lower.rs121
-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.rs16
-rw-r--r--crates/hir_def/src/path/lower.rs14
-rw-r--r--crates/hir_def/src/resolver.rs3
-rw-r--r--crates/hir_def/src/test_db.rs13
-rw-r--r--crates/hir_def/src/type_ref.rs17
-rw-r--r--crates/hir_def/src/visibility.rs6
-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.rs11
-rw-r--r--crates/hir_expand/src/quote.rs1
-rw-r--r--crates/hir_ty/src/autoderef.rs49
-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/db.rs2
-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.rs47
-rw-r--r--crates/hir_ty/src/diagnostics/unsafe_check.rs8
-rw-r--r--crates/hir_ty/src/display.rs91
-rw-r--r--crates/hir_ty/src/infer.rs41
-rw-r--r--crates/hir_ty/src/infer/coerce.rs39
-rw-r--r--crates/hir_ty/src/infer/expr.rs138
-rw-r--r--crates/hir_ty/src/infer/pat.rs47
-rw-r--r--crates/hir_ty/src/infer/path.rs33
-rw-r--r--crates/hir_ty/src/infer/unify.rs80
-rw-r--r--crates/hir_ty/src/lib.rs810
-rw-r--r--crates/hir_ty/src/lower.rs151
-rw-r--r--crates/hir_ty/src/method_resolution.rs35
-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/tests/macros.rs26
-rw-r--r--crates/hir_ty/src/tests/traits.rs43
-rw-r--r--crates/hir_ty/src/traits.rs90
-rw-r--r--crates/hir_ty/src/traits/chalk.rs26
-rw-r--r--crates/hir_ty/src/traits/chalk/mapping.rs47
-rw-r--r--crates/hir_ty/src/types.rs416
-rw-r--r--crates/hir_ty/src/utils.rs36
-rw-r--r--crates/hir_ty/src/walk.rs381
-rw-r--r--crates/ide/src/annotations.rs2
-rw-r--r--crates/ide/src/doc_links.rs2
-rw-r--r--crates/ide/src/expand_macro.rs2
-rw-r--r--crates/ide/src/extend_selection.rs2
-rw-r--r--crates/ide/src/file_structure.rs3
-rw-r--r--crates/ide/src/goto_definition.rs2
-rw-r--r--crates/ide/src/goto_implementation.rs2
-rw-r--r--crates/ide/src/goto_type_definition.rs2
-rw-r--r--crates/ide/src/hover.rs113
-rw-r--r--crates/ide/src/inlay_hints.rs4
-rw-r--r--crates/ide/src/join_lines.rs20
-rw-r--r--crates/ide/src/matching_brace.rs2
-rw-r--r--crates/ide/src/move_item.rs2
-rw-r--r--crates/ide/src/parent_module.rs2
-rw-r--r--crates/ide/src/references.rs2
-rw-r--r--crates/ide/src/references/rename.rs4
-rw-r--r--crates/ide/src/runnables.rs3
-rw-r--r--crates/ide/src/status.rs1
-rw-r--r--crates/ide/src/syntax_highlighting.rs3
-rw-r--r--crates/ide/src/syntax_highlighting/highlight.rs35
-rw-r--r--crates/ide/src/syntax_highlighting/tags.rs4
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html8
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_injection.html2
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html6
-rw-r--r--crates/ide/src/syntax_highlighting/test_data/highlighting.html4
-rw-r--r--crates/ide/src/syntax_tree.rs1
-rw-r--r--crates/ide/src/typing.rs3
-rw-r--r--crates/ide/src/typing/on_enter.rs2
-rw-r--r--crates/ide/src/view_hir.rs1
-rw-r--r--crates/ide_assists/src/assist_context.rs5
-rw-r--r--crates/ide_assists/src/handlers/auto_import.rs2
-rw-r--r--crates/ide_assists/src/handlers/convert_into_to_from.rs355
-rw-r--r--crates/ide_assists/src/handlers/extract_type_alias.rs149
-rw-r--r--crates/ide_assists/src/handlers/extract_variable.rs73
-rw-r--r--crates/ide_assists/src/handlers/generate_default_from_new.rs2
-rw-r--r--crates/ide_assists/src/handlers/generate_is_empty_from_len.rs2
-rw-r--r--crates/ide_assists/src/handlers/reorder_fields.rs89
-rw-r--r--crates/ide_assists/src/lib.rs4
-rw-r--r--crates/ide_assists/src/tests/generated.rs51
-rw-r--r--crates/ide_assists/src/utils.rs4
-rw-r--r--crates/ide_completion/src/completions.rs2
-rw-r--r--crates/ide_completion/src/completions/pattern.rs2
-rw-r--r--crates/ide_completion/src/completions/postfix/format_like.rs2
-rw-r--r--crates/ide_completion/src/completions/qualified_path.rs4
-rw-r--r--crates/ide_completion/src/lib.rs2
-rw-r--r--crates/ide_db/src/apply_change.rs1
-rw-r--r--crates/ide_db/src/helpers.rs4
-rw-r--r--crates/ide_db/src/helpers/famous_defs_fixture.rs6
-rw-r--r--crates/ide_db/src/helpers/import_assets.rs2
-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/proc_macro_srv/src/rustc_server.rs19
-rw-r--r--crates/profile/src/google_cpu_profiler.rs19
-rw-r--r--crates/profile/src/lib.rs37
-rw-r--r--crates/rust-analyzer/src/benchmarks.rs2
-rw-r--r--crates/rust-analyzer/src/bin/flags.rs3
-rw-r--r--crates/rust-analyzer/src/bin/main.rs3
-rw-r--r--crates/rust-analyzer/src/cargo_target_spec.rs2
-rw-r--r--crates/rust-analyzer/src/cli/analysis_stats.rs60
-rw-r--r--crates/rust-analyzer/src/diagnostics/test_data/macro_compiler_error.txt138
-rw-r--r--crates/rust-analyzer/src/diagnostics/to_proto.rs101
-rw-r--r--crates/rust-analyzer/src/handlers.rs18
-rw-r--r--crates/rust-analyzer/src/semantic_tokens.rs1
-rw-r--r--crates/rust-analyzer/src/to_proto.rs1
133 files changed, 3655 insertions, 1885 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 4ee08ef21..e41efb385 100644
--- a/crates/hir/src/lib.rs
+++ b/crates/hir/src/lib.rs
@@ -44,6 +44,7 @@ use hir_def::{
44 per_ns::PerNs, 44 per_ns::PerNs,
45 resolver::{HasResolver, Resolver}, 45 resolver::{HasResolver, Resolver},
46 src::HasSource as _, 46 src::HasSource as _,
47 type_ref::TraitRef,
47 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, 48 AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId,
48 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, 49 DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId,
49 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, 50 LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId,
@@ -54,11 +55,11 @@ use hir_ty::{
54 autoderef, could_unify, 55 autoderef, could_unify,
55 method_resolution::{self, TyFingerprint}, 56 method_resolution::{self, TyFingerprint},
56 primitive::UintTy, 57 primitive::UintTy,
57 to_assoc_type_id, 58 traits::FnTrait,
58 traits::{FnTrait, Solution, SolutionVariables},
59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, 59 AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast,
60 DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, 60 DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Solution,
61 Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, 61 SolutionVariables, Substitution, TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind,
62 TyVariableKind, WhereClause,
62}; 63};
63use itertools::Itertools; 64use itertools::Itertools;
64use rustc_hash::FxHashSet; 65use rustc_hash::FxHashSet;
@@ -514,7 +515,7 @@ impl Field {
514 VariantDef::Union(it) => it.id.into(), 515 VariantDef::Union(it) => it.id.into(),
515 VariantDef::Variant(it) => it.parent.id.into(), 516 VariantDef::Variant(it) => it.parent.id.into(),
516 }; 517 };
517 let substs = Substitution::type_params(db, generic_def_id); 518 let substs = TyBuilder::type_params_subst(db, generic_def_id);
518 let ty = db.field_types(var_id)[self.id].clone().subst(&substs); 519 let ty = db.field_types(var_id)[self.id].clone().subst(&substs);
519 Type::new(db, self.parent.module(db).id.krate(), var_id, ty) 520 Type::new(db, self.parent.module(db).id.krate(), var_id, ty)
520 } 521 }
@@ -831,7 +832,7 @@ impl Function {
831 } 832 }
832 833
833 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { 834 pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
834 if !db.function_data(self.id).has_self_param { 835 if !db.function_data(self.id).has_self_param() {
835 return None; 836 return None;
836 } 837 }
837 Some(SelfParam { func: self.id }) 838 Some(SelfParam { func: self.id })
@@ -863,7 +864,7 @@ impl Function {
863 } 864 }
864 865
865 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { 866 pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
866 db.function_data(self.id).qualifier.is_unsafe 867 db.function_data(self.id).is_unsafe()
867 } 868 }
868 869
869 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { 870 pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
@@ -877,7 +878,7 @@ impl Function {
877 /// 878 ///
878 /// This is false in the case of required (not provided) trait methods. 879 /// This is false in the case of required (not provided) trait methods.
879 pub fn has_body(self, db: &dyn HirDatabase) -> bool { 880 pub fn has_body(self, db: &dyn HirDatabase) -> bool {
880 db.function_data(self.id).has_body 881 db.function_data(self.id).has_body()
881 } 882 }
882 883
883 /// A textual representation of the HIR of this function for debugging purposes. 884 /// A textual representation of the HIR of this function for debugging purposes.
@@ -956,7 +957,7 @@ impl SelfParam {
956 func_data 957 func_data
957 .params 958 .params
958 .first() 959 .first()
959 .map(|param| match *param { 960 .map(|param| match &**param {
960 TypeRef::Reference(.., mutability) => match mutability { 961 TypeRef::Reference(.., mutability) => match mutability {
961 hir_def::type_ref::Mutability::Shared => Access::Shared, 962 hir_def::type_ref::Mutability::Shared => Access::Shared,
962 hir_def::type_ref::Mutability::Mut => Access::Exclusive, 963 hir_def::type_ref::Mutability::Mut => Access::Exclusive,
@@ -1010,7 +1011,7 @@ impl Const {
1010 } 1011 }
1011 1012
1012 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { 1013 pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef {
1013 db.const_data(self.id).type_ref.clone() 1014 db.const_data(self.id).type_ref.as_ref().clone()
1014 } 1015 }
1015} 1016}
1016 1017
@@ -1100,7 +1101,7 @@ impl TypeAlias {
1100 } 1101 }
1101 1102
1102 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1103 pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> {
1103 db.type_alias_data(self.id).type_ref.clone() 1104 db.type_alias_data(self.id).type_ref.as_deref().cloned()
1104 } 1105 }
1105 1106
1106 pub fn ty(self, db: &dyn HirDatabase) -> Type { 1107 pub fn ty(self, db: &dyn HirDatabase) -> Type {
@@ -1128,7 +1129,7 @@ pub struct BuiltinType {
1128impl BuiltinType { 1129impl BuiltinType {
1129 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { 1130 pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type {
1130 let resolver = module.id.resolver(db.upcast()); 1131 let resolver = module.id.resolver(db.upcast());
1131 Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) 1132 Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner))
1132 .expect("crate not present in resolver") 1133 .expect("crate not present in resolver")
1133 } 1134 }
1134 1135
@@ -1501,7 +1502,7 @@ impl TypeParam {
1501 let resolver = self.id.parent.resolver(db.upcast()); 1502 let resolver = self.id.parent.resolver(db.upcast());
1502 let krate = self.id.parent.module(db.upcast()).krate(); 1503 let krate = self.id.parent.module(db.upcast()).krate();
1503 let ty = params.get(local_idx)?.clone(); 1504 let ty = params.get(local_idx)?.clone();
1504 let subst = Substitution::type_params(db, self.id.parent); 1505 let subst = TyBuilder::type_params_subst(db, self.id.parent);
1505 let ty = ty.subst(&subst.prefix(local_idx)); 1506 let ty = ty.subst(&subst.prefix(local_idx));
1506 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) 1507 Some(Type::new_with_resolver_inner(db, krate, &resolver, ty))
1507 } 1508 }
@@ -1573,9 +1574,9 @@ impl Impl {
1573 }; 1574 };
1574 1575
1575 let filter = |impl_def: &Impl| { 1576 let filter = |impl_def: &Impl| {
1576 let target_ty = impl_def.target_ty(db); 1577 let self_ty = impl_def.self_ty(db);
1577 let rref = target_ty.remove_ref(); 1578 let rref = self_ty.remove_ref();
1578 ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) 1579 ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty))
1579 }; 1580 };
1580 1581
1581 let mut all = Vec::new(); 1582 let mut all = Vec::new();
@@ -1613,16 +1614,16 @@ impl Impl {
1613 1614
1614 // FIXME: the return type is wrong. This should be a hir version of 1615 // FIXME: the return type is wrong. This should be a hir version of
1615 // `TraitRef` (ie, resolved `TypeRef`). 1616 // `TraitRef` (ie, resolved `TypeRef`).
1616 pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { 1617 pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> {
1617 db.impl_data(self.id).target_trait.clone() 1618 db.impl_data(self.id).target_trait.as_deref().cloned()
1618 } 1619 }
1619 1620
1620 pub fn target_ty(self, db: &dyn HirDatabase) -> Type { 1621 pub fn self_ty(self, db: &dyn HirDatabase) -> Type {
1621 let impl_data = db.impl_data(self.id); 1622 let impl_data = db.impl_data(self.id);
1622 let resolver = self.id.resolver(db.upcast()); 1623 let resolver = self.id.resolver(db.upcast());
1623 let krate = self.id.lookup(db.upcast()).container.krate(); 1624 let krate = self.id.lookup(db.upcast()).container.krate();
1624 let ctx = hir_ty::TyLoweringContext::new(db, &resolver); 1625 let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1625 let ty = ctx.lower_ty(&impl_data.target_type); 1626 let ty = ctx.lower_ty(&impl_data.self_ty);
1626 Type::new_with_resolver_inner(db, krate, &resolver, ty) 1627 Type::new_with_resolver_inner(db, krate, &resolver, ty)
1627 } 1628 }
1628 1629
@@ -1702,30 +1703,29 @@ impl Type {
1702 fn from_def( 1703 fn from_def(
1703 db: &dyn HirDatabase, 1704 db: &dyn HirDatabase,
1704 krate: CrateId, 1705 krate: CrateId,
1705 def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, 1706 def: impl HasResolver + Into<TyDefId>,
1706 ) -> Type { 1707 ) -> Type {
1707 let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); 1708 let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build();
1708 let ty = db.ty(def.into()).subst(&substs);
1709 Type::new(db, krate, def, ty) 1709 Type::new(db, krate, def, ty)
1710 } 1710 }
1711 1711
1712 pub fn is_unit(&self) -> bool { 1712 pub fn is_unit(&self) -> bool {
1713 matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) 1713 matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..))
1714 } 1714 }
1715 pub fn is_bool(&self) -> bool { 1715 pub fn is_bool(&self) -> bool {
1716 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) 1716 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool))
1717 } 1717 }
1718 1718
1719 pub fn is_mutable_reference(&self) -> bool { 1719 pub fn is_mutable_reference(&self) -> bool {
1720 matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) 1720 matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..))
1721 } 1721 }
1722 1722
1723 pub fn is_usize(&self) -> bool { 1723 pub fn is_usize(&self) -> bool {
1724 matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) 1724 matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize)))
1725 } 1725 }
1726 1726
1727 pub fn remove_ref(&self) -> Option<Type> { 1727 pub fn remove_ref(&self) -> Option<Type> {
1728 match &self.ty.interned(&Interner) { 1728 match &self.ty.kind(&Interner) {
1729 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), 1729 TyKind::Ref(.., ty) => Some(self.derived(ty.clone())),
1730 _ => None, 1730 _ => None,
1731 } 1731 }
@@ -1784,13 +1784,10 @@ impl Type {
1784 } 1784 }
1785 1785
1786 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { 1786 pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool {
1787 let trait_ref = hir_ty::TraitRef { 1787 let trait_ref = TyBuilder::trait_ref(db, trait_.id)
1788 trait_id: hir_ty::to_chalk_trait_id(trait_.id), 1788 .push(self.ty.clone())
1789 substitution: Substitution::build_for_def(db, trait_.id) 1789 .fill(args.iter().map(|t| t.ty.clone()))
1790 .push(self.ty.clone()) 1790 .build();
1791 .fill(args.iter().map(|t| t.ty.clone()))
1792 .build(),
1793 };
1794 1791
1795 let goal = Canonical { 1792 let goal = Canonical {
1796 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), 1793 value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)),
@@ -1803,11 +1800,10 @@ impl Type {
1803 pub fn normalize_trait_assoc_type( 1800 pub fn normalize_trait_assoc_type(
1804 &self, 1801 &self,
1805 db: &dyn HirDatabase, 1802 db: &dyn HirDatabase,
1806 trait_: Trait,
1807 args: &[Type], 1803 args: &[Type],
1808 alias: TypeAlias, 1804 alias: TypeAlias,
1809 ) -> Option<Type> { 1805 ) -> Option<Type> {
1810 let subst = Substitution::build_for_def(db, trait_.id) 1806 let projection = TyBuilder::assoc_type_projection(db, alias.id)
1811 .push(self.ty.clone()) 1807 .push(self.ty.clone())
1812 .fill(args.iter().map(|t| t.ty.clone())) 1808 .fill(args.iter().map(|t| t.ty.clone()))
1813 .build(); 1809 .build();
@@ -1815,10 +1811,7 @@ impl Type {
1815 InEnvironment::new( 1811 InEnvironment::new(
1816 self.env.env.clone(), 1812 self.env.env.clone(),
1817 AliasEq { 1813 AliasEq {
1818 alias: AliasTy::Projection(ProjectionTy { 1814 alias: AliasTy::Projection(projection),
1819 associated_ty_id: to_assoc_type_id(alias.id),
1820 substitution: subst,
1821 }),
1822 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) 1815 ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0))
1823 .intern(&Interner), 1816 .intern(&Interner),
1824 } 1817 }
@@ -1828,9 +1821,11 @@ impl Type {
1828 ); 1821 );
1829 1822
1830 match db.trait_solve(self.krate, goal)? { 1823 match db.trait_solve(self.krate, goal)? {
1831 Solution::Unique(SolutionVariables(subst)) => { 1824 Solution::Unique(SolutionVariables(subst)) => subst
1832 subst.value.first().map(|ty| self.derived(ty.clone())) 1825 .value
1833 } 1826 .interned()
1827 .first()
1828 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())),
1834 Solution::Ambig(_) => None, 1829 Solution::Ambig(_) => None,
1835 } 1830 }
1836 } 1831 }
@@ -1852,15 +1847,15 @@ impl Type {
1852 } 1847 }
1853 1848
1854 pub fn is_closure(&self) -> bool { 1849 pub fn is_closure(&self) -> bool {
1855 matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) 1850 matches!(&self.ty.kind(&Interner), TyKind::Closure { .. })
1856 } 1851 }
1857 1852
1858 pub fn is_fn(&self) -> bool { 1853 pub fn is_fn(&self) -> bool {
1859 matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) 1854 matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. })
1860 } 1855 }
1861 1856
1862 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { 1857 pub fn is_packed(&self, db: &dyn HirDatabase) -> bool {
1863 let adt_id = match self.ty.interned(&Interner) { 1858 let adt_id = match self.ty.kind(&Interner) {
1864 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, 1859 &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id,
1865 _ => return false, 1860 _ => return false,
1866 }; 1861 };
@@ -1873,14 +1868,14 @@ impl Type {
1873 } 1868 }
1874 1869
1875 pub fn is_raw_ptr(&self) -> bool { 1870 pub fn is_raw_ptr(&self) -> bool {
1876 matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) 1871 matches!(&self.ty.kind(&Interner), TyKind::Raw(..))
1877 } 1872 }
1878 1873
1879 pub fn contains_unknown(&self) -> bool { 1874 pub fn contains_unknown(&self) -> bool {
1880 return go(&self.ty); 1875 return go(&self.ty);
1881 1876
1882 fn go(ty: &Ty) -> bool { 1877 fn go(ty: &Ty) -> bool {
1883 match ty.interned(&Interner) { 1878 match ty.kind(&Interner) {
1884 TyKind::Unknown => true, 1879 TyKind::Unknown => true,
1885 1880
1886 TyKind::Adt(_, substs) 1881 TyKind::Adt(_, substs)
@@ -1888,7 +1883,9 @@ impl Type {
1888 | TyKind::Tuple(_, substs) 1883 | TyKind::Tuple(_, substs)
1889 | TyKind::OpaqueType(_, substs) 1884 | TyKind::OpaqueType(_, substs)
1890 | TyKind::FnDef(_, substs) 1885 | TyKind::FnDef(_, substs)
1891 | TyKind::Closure(_, substs) => substs.iter().any(go), 1886 | TyKind::Closure(_, substs) => {
1887 substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go)
1888 }
1892 1889
1893 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { 1890 TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => {
1894 go(ty) 1891 go(ty)
@@ -1909,7 +1906,7 @@ impl Type {
1909 } 1906 }
1910 1907
1911 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { 1908 pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> {
1912 let (variant_id, substs) = match self.ty.interned(&Interner) { 1909 let (variant_id, substs) = match self.ty.kind(&Interner) {
1913 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), 1910 &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs),
1914 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), 1911 &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs),
1915 _ => return Vec::new(), 1912 _ => return Vec::new(),
@@ -1926,8 +1923,11 @@ impl Type {
1926 } 1923 }
1927 1924
1928 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { 1925 pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> {
1929 if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { 1926 if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) {
1930 substs.iter().map(|ty| self.derived(ty.clone())).collect() 1927 substs
1928 .iter(&Interner)
1929 .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone()))
1930 .collect()
1931 } else { 1931 } else {
1932 Vec::new() 1932 Vec::new()
1933 } 1933 }
@@ -1972,8 +1972,9 @@ impl Type {
1972 .strip_references() 1972 .strip_references()
1973 .substs() 1973 .substs()
1974 .into_iter() 1974 .into_iter()
1975 .flat_map(|substs| substs.iter()) 1975 .flat_map(|substs| substs.iter(&Interner))
1976 .map(move |ty| self.derived(ty.clone())) 1976 .filter_map(|arg| arg.ty(&Interner).cloned())
1977 .map(move |ty| self.derived(ty))
1977 } 1978 }
1978 1979
1979 pub fn iterate_method_candidates<T>( 1980 pub fn iterate_method_candidates<T>(
@@ -2079,7 +2080,7 @@ impl Type {
2079 substs: &Substitution, 2080 substs: &Substitution,
2080 cb: &mut impl FnMut(Type), 2081 cb: &mut impl FnMut(Type),
2081 ) { 2082 ) {
2082 for ty in substs.iter() { 2083 for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) {
2083 walk_type(db, &type_.derived(ty.clone()), cb); 2084 walk_type(db, &type_.derived(ty.clone()), cb);
2084 } 2085 }
2085 } 2086 }
@@ -2095,7 +2096,12 @@ impl Type {
2095 WhereClause::Implemented(trait_ref) => { 2096 WhereClause::Implemented(trait_ref) => {
2096 cb(type_.clone()); 2097 cb(type_.clone());
2097 // skip the self type. it's likely the type we just got the bounds from 2098 // skip the self type. it's likely the type we just got the bounds from
2098 for ty in trait_ref.substitution.iter().skip(1) { 2099 for ty in trait_ref
2100 .substitution
2101 .iter(&Interner)
2102 .skip(1)
2103 .filter_map(|a| a.ty(&Interner))
2104 {
2099 walk_type(db, &type_.derived(ty.clone()), cb); 2105 walk_type(db, &type_.derived(ty.clone()), cb);
2100 } 2106 }
2101 } 2107 }
@@ -2106,7 +2112,7 @@ impl Type {
2106 2112
2107 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { 2113 fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) {
2108 let ty = type_.ty.strip_references(); 2114 let ty = type_.ty.strip_references();
2109 match ty.interned(&Interner) { 2115 match ty.kind(&Interner) {
2110 TyKind::Adt(..) => { 2116 TyKind::Adt(..) => {
2111 cb(type_.derived(ty.clone())); 2117 cb(type_.derived(ty.clone()));
2112 } 2118 }
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs
index d3caeef4e..3bf722d2a 100644
--- a/crates/hir/src/semantics.rs
+++ b/crates/hir/src/semantics.rs
@@ -76,9 +76,11 @@ impl PathResolution {
76 pub fn assoc_type_shorthand_candidates<R>( 76 pub fn assoc_type_shorthand_candidates<R>(
77 &self, 77 &self,
78 db: &dyn HirDatabase, 78 db: &dyn HirDatabase,
79 mut cb: impl FnMut(TypeAlias) -> Option<R>, 79 mut cb: impl FnMut(&Name, TypeAlias) -> Option<R>,
80 ) -> Option<R> { 80 ) -> Option<R> {
81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |_, _, id| cb(id.into())) 81 associated_type_shorthand_candidates(db, self.in_type_ns()?, |name, _, id| {
82 cb(name, id.into())
83 })
82 } 84 }
83} 85}
84 86
diff --git a/crates/hir/src/source_analyzer.rs b/crates/hir/src/source_analyzer.rs
index 37d162b32..8e9ea0a03 100644
--- a/crates/hir/src/source_analyzer.rs
+++ b/crates/hir/src/source_analyzer.rs
@@ -20,7 +20,7 @@ use hir_def::{
20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile}; 20use hir_expand::{hygiene::Hygiene, name::AsName, HirFileId, InFile};
21use hir_ty::{ 21use hir_ty::{
22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields}, 22 diagnostics::{record_literal_missing_fields, record_pattern_missing_fields},
23 InferenceResult, Substitution, 23 InferenceResult, Substitution, TyLoweringContext,
24}; 24};
25use syntax::{ 25use syntax::{
26 ast::{self, AstNode}, 26 ast::{self, AstNode},
@@ -466,7 +466,21 @@ fn resolve_hir_path_(
466 prefer_value_ns: bool, 466 prefer_value_ns: bool,
467) -> Option<PathResolution> { 467) -> Option<PathResolution> {
468 let types = || { 468 let types = || {
469 resolver.resolve_path_in_type_ns_fully(db.upcast(), path.mod_path()).map(|ty| match ty { 469 let (ty, unresolved) = match path.type_anchor() {
470 Some(type_ref) => {
471 let (_, res) = TyLoweringContext::new(db, resolver).lower_ty_ext(type_ref);
472 res.map(|ty_ns| (ty_ns, path.segments().first()))
473 }
474 None => {
475 let (ty, remaining) =
476 resolver.resolve_path_in_type_ns(db.upcast(), path.mod_path())?;
477 match remaining {
478 Some(remaining) if remaining > 1 => None,
479 _ => Some((ty, path.segments().get(1))),
480 }
481 }
482 }?;
483 let res = match ty {
470 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()), 484 TypeNs::SelfType(it) => PathResolution::SelfType(it.into()),
471 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }), 485 TypeNs::GenericParam(id) => PathResolution::TypeParam(TypeParam { id }),
472 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => { 486 TypeNs::AdtSelfType(it) | TypeNs::AdtId(it) => {
@@ -476,7 +490,17 @@ fn resolve_hir_path_(
476 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()), 490 TypeNs::TypeAliasId(it) => PathResolution::Def(TypeAlias::from(it).into()),
477 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()), 491 TypeNs::BuiltinType(it) => PathResolution::Def(BuiltinType::from(it).into()),
478 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()), 492 TypeNs::TraitId(it) => PathResolution::Def(Trait::from(it).into()),
479 }) 493 };
494 match unresolved {
495 Some(unresolved) => res
496 .assoc_type_shorthand_candidates(db, |name, alias| {
497 (name == unresolved.name).then(|| alias)
498 })
499 .map(TypeAlias::from)
500 .map(Into::into)
501 .map(PathResolution::Def),
502 None => Some(res),
503 }
480 }; 504 };
481 505
482 let body_owner = resolver.body_owner(); 506 let body_owner = resolver.body_owner();
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml
index 475d337f3..43324d8d9 100644
--- a/crates/hir_def/Cargo.toml
+++ b/crates/hir_def/Cargo.toml
@@ -11,6 +11,7 @@ doctest = false
11 11
12[dependencies] 12[dependencies]
13cov-mark = { version = "1.1", features = ["thread-local"] } 13cov-mark = { version = "1.1", features = ["thread-local"] }
14dashmap = { version = "4.0.2", features = ["raw-api"] }
14log = "0.4.8" 15log = "0.4.8"
15once_cell = "1.3.1" 16once_cell = "1.3.1"
16rustc-hash = "1.1.0" 17rustc-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 74bb6de35..ab77d924a 100644
--- a/crates/hir_def/src/attr.rs
+++ b/crates/hir_def/src/attr.rs
@@ -22,6 +22,7 @@ use tt::Subtree;
22 22
23use crate::{ 23use crate::{
24 db::DefDatabase, 24 db::DefDatabase,
25 intern::Interned,
25 item_tree::{ItemTreeId, ItemTreeNode}, 26 item_tree::{ItemTreeId, ItemTreeNode},
26 nameres::ModuleSource, 27 nameres::ModuleSource,
27 path::{ModPath, PathKind}, 28 path::{ModPath, PathKind},
@@ -102,7 +103,7 @@ impl RawAttrs {
102 Either::Right(comment) => comment.doc_comment().map(|doc| Attr { 103 Either::Right(comment) => comment.doc_comment().map(|doc| Attr {
103 index: i as u32, 104 index: i as u32,
104 input: Some(AttrInput::Literal(SmolStr::new(doc))), 105 input: Some(AttrInput::Literal(SmolStr::new(doc))),
105 path: ModPath::from(hir_expand::name!(doc)), 106 path: Interned::new(ModPath::from(hir_expand::name!(doc))),
106 }), 107 }),
107 }) 108 })
108 .collect::<Arc<_>>(); 109 .collect::<Arc<_>>();
@@ -601,7 +602,7 @@ impl DocsRangeMap {
601#[derive(Debug, Clone, PartialEq, Eq)] 602#[derive(Debug, Clone, PartialEq, Eq)]
602pub struct Attr { 603pub struct Attr {
603 index: u32, 604 index: u32,
604 pub(crate) path: ModPath, 605 pub(crate) path: Interned<ModPath>,
605 pub(crate) input: Option<AttrInput>, 606 pub(crate) input: Option<AttrInput>,
606} 607}
607 608
@@ -615,7 +616,7 @@ pub enum AttrInput {
615 616
616impl Attr { 617impl Attr {
617 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { 618 fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> {
618 let path = ModPath::from_src(ast.path()?, hygiene)?; 619 let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?);
619 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { 620 let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() {
620 let value = match lit.kind() { 621 let value = match lit.kind() {
621 ast::LiteralKind::String(string) => string.value()?.into(), 622 ast::LiteralKind::String(string) => string.value()?.into(),
@@ -623,7 +624,7 @@ impl Attr {
623 }; 624 };
624 Some(AttrInput::Literal(value)) 625 Some(AttrInput::Literal(value))
625 } else if let Some(tt) = ast.token_tree() { 626 } else if let Some(tt) = ast.token_tree() {
626 Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) 627 Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0))
627 } else { 628 } else {
628 None 629 None
629 }; 630 };
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 0be868ba2..135a6698e 100644
--- a/crates/hir_def/src/data.rs
+++ b/crates/hir_def/src/data.rs
@@ -9,8 +9,9 @@ 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 type_ref::{TypeBound, TypeRef}, 13 item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param},
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,
16 Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, 17 Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc,
@@ -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.bits |= 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.bits & FnFlags::HAS_BODY != 0
75 }
76
77 /// True if the first param is `self`. This is relevant to decide whether this
78 /// can be called as a method.
79 pub fn has_self_param(&self) -> bool {
80 self.flags.bits & FnFlags::HAS_SELF_PARAM != 0
81 }
82
83 pub fn is_default(&self) -> bool {
84 self.flags.bits & FnFlags::IS_DEFAULT != 0
85 }
86
87 pub fn is_const(&self) -> bool {
88 self.flags.bits & FnFlags::IS_CONST != 0
89 }
90
91 pub fn is_async(&self) -> bool {
92 self.flags.bits & FnFlags::IS_ASYNC != 0
93 }
94
95 pub fn is_unsafe(&self) -> bool {
96 self.flags.bits & FnFlags::IS_UNSAFE != 0
97 }
98
99 pub fn is_in_extern_block(&self) -> bool {
100 self.flags.bits & FnFlags::IS_IN_EXTERN_BLOCK != 0
101 }
102
103 pub fn is_varargs(&self) -> bool {
104 self.flags.bits & FnFlags::IS_VARARGS != 0
105 }
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<TypeRef>, 191 pub target_trait: Option<Interned<TraitRef>>,
160 pub target_type: 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 target_type = item_tree[impl_def.target_type].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);
@@ -187,7 +219,7 @@ impl ImplData {
187 ); 219 );
188 let items = items.into_iter().map(|(_, item)| item).collect(); 220 let items = items.into_iter().map(|(_, item)| item).collect();
189 221
190 Arc::new(ImplData { target_trait, target_type, items, is_negative }) 222 Arc::new(ImplData { target_trait, self_ty, items, is_negative })
191 } 223 }
192} 224}
193 225
@@ -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/db.rs b/crates/hir_def/src/db.rs
index 068b2ee38..9b7a213a1 100644
--- a/crates/hir_def/src/db.rs
+++ b/crates/hir_def/src/db.rs
@@ -13,6 +13,7 @@ use crate::{
13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData}, 13 data::{ConstData, FunctionData, ImplData, StaticData, TraitData, TypeAliasData},
14 generics::GenericParams, 14 generics::GenericParams,
15 import_map::ImportMap, 15 import_map::ImportMap,
16 intern::Interned,
16 item_tree::ItemTree, 17 item_tree::ItemTree,
17 lang_item::{LangItemTarget, LangItems}, 18 lang_item::{LangItemTarget, LangItems},
18 nameres::DefMap, 19 nameres::DefMap,
@@ -113,7 +114,7 @@ pub trait DefDatabase: InternDatabase + AstDatabase + Upcast<dyn AstDatabase> {
113 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>; 114 fn expr_scopes(&self, def: DefWithBodyId) -> Arc<ExprScopes>;
114 115
115 #[salsa::invoke(GenericParams::generic_params_query)] 116 #[salsa::invoke(GenericParams::generic_params_query)]
116 fn generic_params(&self, def: GenericDefId) -> Arc<GenericParams>; 117 fn generic_params(&self, def: GenericDefId) -> Interned<GenericParams>;
117 118
118 #[salsa::invoke(Attrs::variants_attrs_query)] 119 #[salsa::invoke(Attrs::variants_attrs_query)]
119 fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>; 120 fn variants_attrs(&self, def: EnumId) -> Arc<ArenaMap<LocalEnumVariantId, Attrs>>;
diff --git a/crates/hir_def/src/generics.rs b/crates/hir_def/src/generics.rs
index 7c6cbff11..de5acced8 100644
--- a/crates/hir_def/src/generics.rs
+++ b/crates/hir_def/src/generics.rs
@@ -2,7 +2,6 @@
2//! structs, impls, traits, etc. This module provides a common HIR for these 2//! structs, impls, traits, etc. This module provides a common HIR for these
3//! generic parameters. See also the `Generics` type and the `generics_of` query 3//! generic parameters. See also the `Generics` type and the `generics_of` query
4//! in rustc. 4//! in rustc.
5use std::sync::Arc;
6 5
7use base_db::FileId; 6use base_db::FileId;
8use either::Either; 7use either::Either;
@@ -18,6 +17,7 @@ use crate::{
18 child_by_source::ChildBySource, 17 child_by_source::ChildBySource,
19 db::DefDatabase, 18 db::DefDatabase,
20 dyn_map::DynMap, 19 dyn_map::DynMap,
20 intern::Interned,
21 keys, 21 keys,
22 src::{HasChildSource, HasSource}, 22 src::{HasChildSource, HasSource},
23 type_ref::{LifetimeRef, TypeBound, TypeRef}, 23 type_ref::{LifetimeRef, TypeBound, TypeRef},
@@ -26,27 +26,27 @@ use crate::{
26}; 26};
27 27
28/// Data about a generic type parameter (to a function, struct, impl, ...). 28/// Data about a generic type parameter (to a function, struct, impl, ...).
29#[derive(Clone, PartialEq, Eq, Debug)] 29#[derive(Clone, PartialEq, Eq, Debug, Hash)]
30pub struct TypeParamData { 30pub struct TypeParamData {
31 pub name: Option<Name>, 31 pub name: Option<Name>,
32 pub default: Option<TypeRef>, 32 pub default: Option<Interned<TypeRef>>,
33 pub provenance: TypeParamProvenance, 33 pub provenance: TypeParamProvenance,
34} 34}
35 35
36/// Data about a generic lifetime parameter (to a function, struct, impl, ...). 36/// Data about a generic lifetime parameter (to a function, struct, impl, ...).
37#[derive(Clone, PartialEq, Eq, Debug)] 37#[derive(Clone, PartialEq, Eq, Debug, Hash)]
38pub struct LifetimeParamData { 38pub struct LifetimeParamData {
39 pub name: Name, 39 pub name: Name,
40} 40}
41 41
42/// Data about a generic const parameter (to a function, struct, impl, ...). 42/// Data about a generic const parameter (to a function, struct, impl, ...).
43#[derive(Clone, PartialEq, Eq, Debug)] 43#[derive(Clone, PartialEq, Eq, Debug, Hash)]
44pub struct ConstParamData { 44pub struct ConstParamData {
45 pub name: Name, 45 pub name: Name,
46 pub ty: TypeRef, 46 pub ty: Interned<TypeRef>,
47} 47}
48 48
49#[derive(Copy, Clone, PartialEq, Eq, Debug)] 49#[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
50pub enum TypeParamProvenance { 50pub enum TypeParamProvenance {
51 TypeParamList, 51 TypeParamList,
52 TraitSelf, 52 TraitSelf,
@@ -54,7 +54,7 @@ pub enum TypeParamProvenance {
54} 54}
55 55
56/// Data about the generic parameters of a function, struct, impl, etc. 56/// Data about the generic parameters of a function, struct, impl, etc.
57#[derive(Clone, PartialEq, Eq, Debug, Default)] 57#[derive(Clone, PartialEq, Eq, Debug, Default, Hash)]
58pub struct GenericParams { 58pub struct GenericParams {
59 pub types: Arena<TypeParamData>, 59 pub types: Arena<TypeParamData>,
60 pub lifetimes: Arena<LifetimeParamData>, 60 pub lifetimes: Arena<LifetimeParamData>,
@@ -66,16 +66,16 @@ pub struct GenericParams {
66/// where clauses like `where T: Foo + Bar` are turned into multiple of these. 66/// where clauses like `where T: Foo + Bar` are turned into multiple of these.
67/// It might still result in multiple actual predicates though, because of 67/// It might still result in multiple actual predicates though, because of
68/// associated type bindings like `Iterator<Item = u32>`. 68/// associated type bindings like `Iterator<Item = u32>`.
69#[derive(Clone, PartialEq, Eq, Debug)] 69#[derive(Clone, PartialEq, Eq, Debug, Hash)]
70pub enum WherePredicate { 70pub enum WherePredicate {
71 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound }, 71 TypeBound { target: WherePredicateTypeTarget, bound: TypeBound },
72 Lifetime { target: LifetimeRef, bound: LifetimeRef }, 72 Lifetime { target: LifetimeRef, bound: LifetimeRef },
73 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound }, 73 ForLifetime { lifetimes: Box<[Name]>, target: WherePredicateTypeTarget, bound: TypeBound },
74} 74}
75 75
76#[derive(Clone, PartialEq, Eq, Debug)] 76#[derive(Clone, PartialEq, Eq, Debug, Hash)]
77pub enum WherePredicateTypeTarget { 77pub enum WherePredicateTypeTarget {
78 TypeRef(TypeRef), 78 TypeRef(Interned<TypeRef>),
79 /// For desugared where predicates that can directly refer to a type param. 79 /// For desugared where predicates that can directly refer to a type param.
80 TypeParam(LocalTypeParamId), 80 TypeParam(LocalTypeParamId),
81} 81}
@@ -91,7 +91,7 @@ impl GenericParams {
91 pub(crate) fn generic_params_query( 91 pub(crate) fn generic_params_query(
92 db: &dyn DefDatabase, 92 db: &dyn DefDatabase,
93 def: GenericDefId, 93 def: GenericDefId,
94 ) -> Arc<GenericParams> { 94 ) -> Interned<GenericParams> {
95 let _p = profile::span("generic_params_query"); 95 let _p = profile::span("generic_params_query");
96 96
97 let generics = match def { 97 let generics = match def {
@@ -99,47 +99,49 @@ impl GenericParams {
99 let id = id.lookup(db).id; 99 let id = id.lookup(db).id;
100 let tree = id.item_tree(db); 100 let tree = id.item_tree(db);
101 let item = &tree[id.value]; 101 let item = &tree[id.value];
102 tree[item.generic_params].clone() 102 item.generic_params.clone()
103 } 103 }
104 GenericDefId::AdtId(AdtId::StructId(id)) => { 104 GenericDefId::AdtId(AdtId::StructId(id)) => {
105 let id = id.lookup(db).id; 105 let id = id.lookup(db).id;
106 let tree = id.item_tree(db); 106 let tree = id.item_tree(db);
107 let item = &tree[id.value]; 107 let item = &tree[id.value];
108 tree[item.generic_params].clone() 108 item.generic_params.clone()
109 } 109 }
110 GenericDefId::AdtId(AdtId::EnumId(id)) => { 110 GenericDefId::AdtId(AdtId::EnumId(id)) => {
111 let id = id.lookup(db).id; 111 let id = id.lookup(db).id;
112 let tree = id.item_tree(db); 112 let tree = id.item_tree(db);
113 let item = &tree[id.value]; 113 let item = &tree[id.value];
114 tree[item.generic_params].clone() 114 item.generic_params.clone()
115 } 115 }
116 GenericDefId::AdtId(AdtId::UnionId(id)) => { 116 GenericDefId::AdtId(AdtId::UnionId(id)) => {
117 let id = id.lookup(db).id; 117 let id = id.lookup(db).id;
118 let tree = id.item_tree(db); 118 let tree = id.item_tree(db);
119 let item = &tree[id.value]; 119 let item = &tree[id.value];
120 tree[item.generic_params].clone() 120 item.generic_params.clone()
121 } 121 }
122 GenericDefId::TraitId(id) => { 122 GenericDefId::TraitId(id) => {
123 let id = id.lookup(db).id; 123 let id = id.lookup(db).id;
124 let tree = id.item_tree(db); 124 let tree = id.item_tree(db);
125 let item = &tree[id.value]; 125 let item = &tree[id.value];
126 tree[item.generic_params].clone() 126 item.generic_params.clone()
127 } 127 }
128 GenericDefId::TypeAliasId(id) => { 128 GenericDefId::TypeAliasId(id) => {
129 let id = id.lookup(db).id; 129 let id = id.lookup(db).id;
130 let tree = id.item_tree(db); 130 let tree = id.item_tree(db);
131 let item = &tree[id.value]; 131 let item = &tree[id.value];
132 tree[item.generic_params].clone() 132 item.generic_params.clone()
133 } 133 }
134 GenericDefId::ImplId(id) => { 134 GenericDefId::ImplId(id) => {
135 let id = id.lookup(db).id; 135 let id = id.lookup(db).id;
136 let tree = id.item_tree(db); 136 let tree = id.item_tree(db);
137 let item = &tree[id.value]; 137 let item = &tree[id.value];
138 tree[item.generic_params].clone() 138 item.generic_params.clone()
139 }
140 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => {
141 Interned::new(GenericParams::default())
139 } 142 }
140 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => GenericParams::default(),
141 }; 143 };
142 Arc::new(generics) 144 generics
143 } 145 }
144 146
145 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) { 147 fn new(db: &dyn DefDatabase, def: GenericDefId) -> (GenericParams, InFile<SourceMap>) {
@@ -217,6 +219,7 @@ impl GenericParams {
217 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(), 219 GenericDefId::EnumVariantId(_) | GenericDefId::ConstId(_) => FileId(!0).into(),
218 }; 220 };
219 221
222 generics.shrink_to_fit();
220 (generics, InFile::new(file_id, sm)) 223 (generics, InFile::new(file_id, sm))
221 } 224 }
222 225
@@ -256,7 +259,8 @@ impl GenericParams {
256 for type_param in params.type_params() { 259 for type_param in params.type_params() {
257 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name()); 260 let name = type_param.name().map_or_else(Name::missing, |it| it.as_name());
258 // FIXME: Use `Path::from_src` 261 // FIXME: Use `Path::from_src`
259 let default = type_param.default_type().map(|it| TypeRef::from_ast(lower_ctx, it)); 262 let default =
263 type_param.default_type().map(|it| Interned::new(TypeRef::from_ast(lower_ctx, it)));
260 let param = TypeParamData { 264 let param = TypeParamData {
261 name: Some(name.clone()), 265 name: Some(name.clone()),
262 default, 266 default,
@@ -280,7 +284,7 @@ impl GenericParams {
280 for const_param in params.const_params() { 284 for const_param in params.const_params() {
281 let name = const_param.name().map_or_else(Name::missing, |it| it.as_name()); 285 let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
282 let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it)); 286 let ty = const_param.ty().map_or(TypeRef::Error, |it| TypeRef::from_ast(lower_ctx, it));
283 let param = ConstParamData { name, ty }; 287 let param = ConstParamData { name, ty: Interned::new(ty) };
284 let param_id = self.consts.alloc(param); 288 let param_id = self.consts.alloc(param);
285 sm.const_params.insert(param_id, const_param.clone()); 289 sm.const_params.insert(param_id, const_param.clone());
286 } 290 }
@@ -334,11 +338,11 @@ impl GenericParams {
334 (Either::Left(type_ref), bound) => match hrtb_lifetimes { 338 (Either::Left(type_ref), bound) => match hrtb_lifetimes {
335 Some(hrtb_lifetimes) => WherePredicate::ForLifetime { 339 Some(hrtb_lifetimes) => WherePredicate::ForLifetime {
336 lifetimes: hrtb_lifetimes.clone(), 340 lifetimes: hrtb_lifetimes.clone(),
337 target: WherePredicateTypeTarget::TypeRef(type_ref), 341 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
338 bound, 342 bound,
339 }, 343 },
340 None => WherePredicate::TypeBound { 344 None => WherePredicate::TypeBound {
341 target: WherePredicateTypeTarget::TypeRef(type_ref), 345 target: WherePredicateTypeTarget::TypeRef(Interned::new(type_ref)),
342 bound, 346 bound,
343 }, 347 },
344 }, 348 },
@@ -369,6 +373,14 @@ impl GenericParams {
369 }); 373 });
370 } 374 }
371 375
376 pub(crate) fn shrink_to_fit(&mut self) {
377 let Self { consts, lifetimes, types, where_predicates } = self;
378 consts.shrink_to_fit();
379 lifetimes.shrink_to_fit();
380 types.shrink_to_fit();
381 where_predicates.shrink_to_fit();
382 }
383
372 pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> { 384 pub fn find_type_by_name(&self, name: &Name) -> Option<LocalTypeParamId> {
373 self.types 385 self.types
374 .iter() 386 .iter()
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs
new file mode 100644
index 000000000..2467e9299
--- /dev/null
+++ b/crates/hir_def/src/intern.rs
@@ -0,0 +1,205 @@
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
17use crate::generics::GenericParams;
18
19type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>;
20type Guard<T> =
21 RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>;
22
23#[derive(Hash)]
24pub struct Interned<T: Internable + ?Sized> {
25 arc: Arc<T>,
26}
27
28impl<T: Internable> Interned<T> {
29 pub fn new(obj: T) -> Self {
30 match Interned::lookup(&obj) {
31 Ok(this) => this,
32 Err(shard) => {
33 let arc = Arc::new(obj);
34 Self::alloc(arc, shard)
35 }
36 }
37 }
38}
39
40impl<T: Internable + ?Sized> Interned<T> {
41 fn lookup(obj: &T) -> Result<Self, Guard<T>> {
42 let storage = T::storage().get();
43 let shard_idx = storage.determine_map(obj);
44 let shard = &storage.shards()[shard_idx];
45 let shard = shard.write();
46
47 // Atomically,
48 // - check if `obj` is already in the map
49 // - if so, clone its `Arc` and return it
50 // - if not, box it up, insert it, and return a clone
51 // This needs to be atomic (locking the shard) to avoid races with other thread, which could
52 // insert the same object between us looking it up and inserting it.
53
54 // FIXME: avoid double lookup/hashing by using raw entry API (once stable, or when
55 // hashbrown can be plugged into dashmap)
56 match shard.get_key_value(obj) {
57 Some((arc, _)) => Ok(Self { arc: arc.clone() }),
58 None => Err(shard),
59 }
60 }
61
62 fn alloc(arc: Arc<T>, mut shard: Guard<T>) -> Self {
63 let arc2 = arc.clone();
64
65 shard.insert(arc2, SharedValue::new(()));
66
67 Self { arc }
68 }
69}
70
71impl Interned<str> {
72 pub fn new_str(s: &str) -> Self {
73 match Interned::lookup(s) {
74 Ok(this) => this,
75 Err(shard) => {
76 let arc = Arc::<str>::from(s);
77 Self::alloc(arc, shard)
78 }
79 }
80 }
81}
82
83impl<T: Internable + ?Sized> Drop for Interned<T> {
84 #[inline]
85 fn drop(&mut self) {
86 // When the last `Ref` is dropped, remove the object from the global map.
87 if Arc::strong_count(&self.arc) == 2 {
88 // Only `self` and the global map point to the object.
89
90 self.drop_slow();
91 }
92 }
93}
94
95impl<T: Internable + ?Sized> Interned<T> {
96 #[cold]
97 fn drop_slow(&mut self) {
98 let storage = T::storage().get();
99 let shard_idx = storage.determine_map(&self.arc);
100 let shard = &storage.shards()[shard_idx];
101 let mut shard = shard.write();
102
103 // FIXME: avoid double lookup
104 let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely");
105
106 if Arc::strong_count(arc) != 2 {
107 // Another thread has interned another copy
108 return;
109 }
110
111 shard.remove(&self.arc);
112
113 // Shrink the backing storage if the shard is less than 50% occupied.
114 if shard.len() * 2 < shard.capacity() {
115 shard.shrink_to_fit();
116 }
117 }
118}
119
120/// Compares interned `Ref`s using pointer equality.
121impl<T: Internable> PartialEq for Interned<T> {
122 // NOTE: No `?Sized` because `ptr_eq` doesn't work right with trait objects.
123
124 #[inline]
125 fn eq(&self, other: &Self) -> bool {
126 Arc::ptr_eq(&self.arc, &other.arc)
127 }
128}
129
130impl<T: Internable> Eq for Interned<T> {}
131
132impl PartialEq for Interned<str> {
133 fn eq(&self, other: &Self) -> bool {
134 Arc::ptr_eq(&self.arc, &other.arc)
135 }
136}
137
138impl Eq for Interned<str> {}
139
140impl<T: Internable + ?Sized> AsRef<T> for Interned<T> {
141 #[inline]
142 fn as_ref(&self) -> &T {
143 &self.arc
144 }
145}
146
147impl<T: Internable + ?Sized> Deref for Interned<T> {
148 type Target = T;
149
150 #[inline]
151 fn deref(&self) -> &Self::Target {
152 &self.arc
153 }
154}
155
156impl<T: Internable + ?Sized> Clone for Interned<T> {
157 fn clone(&self) -> Self {
158 Self { arc: self.arc.clone() }
159 }
160}
161
162impl<T: Debug + Internable + ?Sized> Debug for Interned<T> {
163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
164 (*self.arc).fmt(f)
165 }
166}
167
168pub struct InternStorage<T: ?Sized> {
169 map: OnceCell<InternMap<T>>,
170}
171
172impl<T: ?Sized> InternStorage<T> {
173 pub const fn new() -> Self {
174 Self { map: OnceCell::new() }
175 }
176}
177
178impl<T: Internable + ?Sized> InternStorage<T> {
179 fn get(&self) -> &InternMap<T> {
180 self.map.get_or_init(DashMap::default)
181 }
182}
183
184pub trait Internable: Hash + Eq + 'static {
185 fn storage() -> &'static InternStorage<Self>;
186}
187
188macro_rules! impl_internable {
189 ( $($t:path),+ $(,)? ) => { $(
190 impl Internable for $t {
191 fn storage() -> &'static InternStorage<Self> {
192 static STORAGE: InternStorage<$t> = InternStorage::new();
193 &STORAGE
194 }
195 }
196 )+ };
197}
198
199impl_internable!(
200 crate::type_ref::TypeRef,
201 crate::type_ref::TraitRef,
202 crate::path::ModPath,
203 GenericParams,
204 str
205);
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs
index f3ebe7c72..a8ee5eeac 100644
--- a/crates/hir_def/src/item_scope.rs
+++ b/crates/hir_def/src/item_scope.rs
@@ -285,6 +285,28 @@ impl ItemScope {
285 buf.push('\n'); 285 buf.push('\n');
286 } 286 }
287 } 287 }
288
289 pub(crate) fn shrink_to_fit(&mut self) {
290 // Exhaustive match to require handling new fields.
291 let Self {
292 types,
293 values,
294 macros,
295 unresolved,
296 defs,
297 impls,
298 unnamed_trait_imports,
299 legacy_macros,
300 } = self;
301 types.shrink_to_fit();
302 values.shrink_to_fit();
303 macros.shrink_to_fit();
304 unresolved.shrink_to_fit();
305 defs.shrink_to_fit();
306 impls.shrink_to_fit();
307 unnamed_trait_imports.shrink_to_fit();
308 legacy_macros.shrink_to_fit();
309 }
288} 310}
289 311
290impl PerNs { 312impl PerNs {
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index ca0048b16..240662486 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -24,14 +24,15 @@ 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, TypeBound, TypeRef}, 35 type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
35 visibility::RawVisibility, 36 visibility::RawVisibility,
36}; 37};
37 38
@@ -57,13 +58,6 @@ impl fmt::Debug for RawVisibilityId {
57 } 58 }
58} 59}
59 60
60#[derive(Debug, Copy, Clone, Eq, PartialEq)]
61pub struct GenericParamsId(u32);
62
63impl GenericParamsId {
64 pub const EMPTY: Self = GenericParamsId(u32::max_value());
65}
66
67/// The item tree of a source file. 61/// The item tree of a source file.
68#[derive(Debug, Default, Eq, PartialEq)] 62#[derive(Debug, Default, Eq, PartialEq)]
69pub struct ItemTree { 63pub struct ItemTree {
@@ -145,8 +139,6 @@ impl ItemTree {
145 macro_rules, 139 macro_rules,
146 macro_defs, 140 macro_defs,
147 vis, 141 vis,
148 generics,
149 type_refs,
150 inner_items, 142 inner_items,
151 } = &mut **data; 143 } = &mut **data;
152 144
@@ -170,9 +162,6 @@ impl ItemTree {
170 macro_defs.shrink_to_fit(); 162 macro_defs.shrink_to_fit();
171 163
172 vis.arena.shrink_to_fit(); 164 vis.arena.shrink_to_fit();
173 generics.arena.shrink_to_fit();
174 type_refs.arena.shrink_to_fit();
175 type_refs.map.shrink_to_fit();
176 165
177 inner_items.shrink_to_fit(); 166 inner_items.shrink_to_fit();
178 } 167 }
@@ -244,58 +233,6 @@ static VIS_PRIV: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKi
244static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate)); 233static VIS_PUB_CRATE: RawVisibility = RawVisibility::Module(ModPath::from_kind(PathKind::Crate));
245 234
246#[derive(Default, Debug, Eq, PartialEq)] 235#[derive(Default, Debug, Eq, PartialEq)]
247struct GenericParamsStorage {
248 arena: Arena<GenericParams>,
249}
250
251impl GenericParamsStorage {
252 fn alloc(&mut self, params: GenericParams) -> GenericParamsId {
253 if params.types.is_empty()
254 && params.lifetimes.is_empty()
255 && params.consts.is_empty()
256 && params.where_predicates.is_empty()
257 {
258 return GenericParamsId::EMPTY;
259 }
260
261 GenericParamsId(self.arena.alloc(params).into_raw().into())
262 }
263}
264
265static EMPTY_GENERICS: GenericParams = GenericParams {
266 types: Arena::new(),
267 lifetimes: Arena::new(),
268 consts: Arena::new(),
269 where_predicates: Vec::new(),
270};
271
272/// `TypeRef` interner.
273#[derive(Default, Debug, Eq, PartialEq)]
274struct TypeRefStorage {
275 arena: Arena<Arc<TypeRef>>,
276 map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>,
277}
278
279impl TypeRefStorage {
280 // Note: We lie about the `Idx<TypeRef>` to hide the interner details.
281
282 fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> {
283 if let Some(id) = self.map.get(&ty) {
284 return Idx::from_raw(id.into_raw());
285 }
286
287 let ty = Arc::new(ty);
288 let idx = self.arena.alloc(ty.clone());
289 self.map.insert(ty, idx);
290 Idx::from_raw(idx.into_raw())
291 }
292
293 fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef {
294 &self.arena[Idx::from_raw(id.into_raw())]
295 }
296}
297
298#[derive(Default, Debug, Eq, PartialEq)]
299struct ItemTreeData { 236struct ItemTreeData {
300 imports: Arena<Import>, 237 imports: Arena<Import>,
301 extern_crates: Arena<ExternCrate>, 238 extern_crates: Arena<ExternCrate>,
@@ -317,8 +254,6 @@ struct ItemTreeData {
317 macro_defs: Arena<MacroDef>, 254 macro_defs: Arena<MacroDef>,
318 255
319 vis: ItemVisibilities, 256 vis: ItemVisibilities,
320 generics: GenericParamsStorage,
321 type_refs: TypeRefStorage,
322 257
323 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, 258 inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>,
324} 259}
@@ -537,25 +472,6 @@ impl Index<RawVisibilityId> for ItemTree {
537 } 472 }
538} 473}
539 474
540impl Index<GenericParamsId> for ItemTree {
541 type Output = GenericParams;
542
543 fn index(&self, index: GenericParamsId) -> &Self::Output {
544 match index {
545 GenericParamsId::EMPTY => &EMPTY_GENERICS,
546 _ => &self.data().generics.arena[Idx::from_raw(index.0.into())],
547 }
548 }
549}
550
551impl Index<Idx<TypeRef>> for ItemTree {
552 type Output = TypeRef;
553
554 fn index(&self, id: Idx<TypeRef>) -> &Self::Output {
555 self.data().type_refs.lookup(id)
556 }
557}
558
559impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { 475impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
560 type Output = N; 476 type Output = N;
561 fn index(&self, id: FileItemTreeId<N>) -> &N { 477 fn index(&self, id: FileItemTreeId<N>) -> &N {
@@ -566,7 +482,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree {
566/// A desugared `use` import. 482/// A desugared `use` import.
567#[derive(Debug, Clone, Eq, PartialEq)] 483#[derive(Debug, Clone, Eq, PartialEq)]
568pub struct Import { 484pub struct Import {
569 pub path: ModPath, 485 pub path: Interned<ModPath>,
570 pub alias: Option<ImportAlias>, 486 pub alias: Option<ImportAlias>,
571 pub visibility: RawVisibilityId, 487 pub visibility: RawVisibilityId,
572 pub is_glob: bool, 488 pub is_glob: bool,
@@ -592,38 +508,42 @@ pub struct ExternCrate {
592pub struct Function { 508pub struct Function {
593 pub name: Name, 509 pub name: Name,
594 pub visibility: RawVisibilityId, 510 pub visibility: RawVisibilityId,
595 pub generic_params: GenericParamsId, 511 pub generic_params: Interned<GenericParams>,
596 pub has_self_param: bool, 512 pub abi: Option<Interned<str>>,
597 pub has_body: bool,
598 pub qualifier: FunctionQualifier,
599 /// Whether the function is located in an `extern` block (*not* whether it is an
600 /// `extern "abi" fn`).
601 pub is_in_extern_block: bool,
602 pub params: IdRange<Param>, 513 pub params: IdRange<Param>,
603 pub ret_type: Idx<TypeRef>, 514 pub ret_type: Interned<TypeRef>,
604 pub ast_id: FileAstId<ast::Fn>, 515 pub ast_id: FileAstId<ast::Fn>,
516 pub(crate) flags: FnFlags,
605} 517}
606 518
607#[derive(Debug, Clone, Eq, PartialEq)] 519#[derive(Debug, Clone, Eq, PartialEq)]
608pub enum Param { 520pub enum Param {
609 Normal(Idx<TypeRef>), 521 Normal(Interned<TypeRef>),
610 Varargs, 522 Varargs,
611} 523}
612 524
613#[derive(Debug, Clone, PartialEq, Eq)] 525#[derive(Debug, Clone, Copy, Eq, PartialEq, Default)]
614pub struct FunctionQualifier { 526pub(crate) struct FnFlags {
615 pub is_default: bool, 527 pub(crate) bits: u8,
616 pub is_const: bool, 528}
617 pub is_async: bool, 529impl FnFlags {
618 pub is_unsafe: bool, 530 pub(crate) const HAS_SELF_PARAM: u8 = 1 << 0;
619 pub abi: Option<SmolStr>, 531 pub(crate) const HAS_BODY: u8 = 1 << 1;
532 pub(crate) const IS_DEFAULT: u8 = 1 << 2;
533 pub(crate) const IS_CONST: u8 = 1 << 3;
534 pub(crate) const IS_ASYNC: u8 = 1 << 4;
535 pub(crate) const IS_UNSAFE: u8 = 1 << 5;
536 /// Whether the function is located in an `extern` block (*not* whether it is an
537 /// `extern "abi" fn`).
538 pub(crate) const IS_IN_EXTERN_BLOCK: u8 = 1 << 6;
539 pub(crate) const IS_VARARGS: u8 = 1 << 7;
620} 540}
621 541
622#[derive(Debug, Clone, Eq, PartialEq)] 542#[derive(Debug, Clone, Eq, PartialEq)]
623pub struct Struct { 543pub struct Struct {
624 pub name: Name, 544 pub name: Name,
625 pub visibility: RawVisibilityId, 545 pub visibility: RawVisibilityId,
626 pub generic_params: GenericParamsId, 546 pub generic_params: Interned<GenericParams>,
627 pub fields: Fields, 547 pub fields: Fields,
628 pub ast_id: FileAstId<ast::Struct>, 548 pub ast_id: FileAstId<ast::Struct>,
629 pub kind: StructDefKind, 549 pub kind: StructDefKind,
@@ -643,7 +563,7 @@ pub enum StructDefKind {
643pub struct Union { 563pub struct Union {
644 pub name: Name, 564 pub name: Name,
645 pub visibility: RawVisibilityId, 565 pub visibility: RawVisibilityId,
646 pub generic_params: GenericParamsId, 566 pub generic_params: Interned<GenericParams>,
647 pub fields: Fields, 567 pub fields: Fields,
648 pub ast_id: FileAstId<ast::Union>, 568 pub ast_id: FileAstId<ast::Union>,
649} 569}
@@ -652,7 +572,7 @@ pub struct Union {
652pub struct Enum { 572pub struct Enum {
653 pub name: Name, 573 pub name: Name,
654 pub visibility: RawVisibilityId, 574 pub visibility: RawVisibilityId,
655 pub generic_params: GenericParamsId, 575 pub generic_params: Interned<GenericParams>,
656 pub variants: IdRange<Variant>, 576 pub variants: IdRange<Variant>,
657 pub ast_id: FileAstId<ast::Enum>, 577 pub ast_id: FileAstId<ast::Enum>,
658} 578}
@@ -662,7 +582,7 @@ pub struct Const {
662 /// const _: () = (); 582 /// const _: () = ();
663 pub name: Option<Name>, 583 pub name: Option<Name>,
664 pub visibility: RawVisibilityId, 584 pub visibility: RawVisibilityId,
665 pub type_ref: Idx<TypeRef>, 585 pub type_ref: Interned<TypeRef>,
666 pub ast_id: FileAstId<ast::Const>, 586 pub ast_id: FileAstId<ast::Const>,
667} 587}
668 588
@@ -673,7 +593,7 @@ pub struct Static {
673 pub mutable: bool, 593 pub mutable: bool,
674 /// Whether the static is in an `extern` block. 594 /// Whether the static is in an `extern` block.
675 pub is_extern: bool, 595 pub is_extern: bool,
676 pub type_ref: Idx<TypeRef>, 596 pub type_ref: Interned<TypeRef>,
677 pub ast_id: FileAstId<ast::Static>, 597 pub ast_id: FileAstId<ast::Static>,
678} 598}
679 599
@@ -681,7 +601,7 @@ pub struct Static {
681pub struct Trait { 601pub struct Trait {
682 pub name: Name, 602 pub name: Name,
683 pub visibility: RawVisibilityId, 603 pub visibility: RawVisibilityId,
684 pub generic_params: GenericParamsId, 604 pub generic_params: Interned<GenericParams>,
685 pub is_auto: bool, 605 pub is_auto: bool,
686 pub is_unsafe: bool, 606 pub is_unsafe: bool,
687 pub bounds: Box<[TypeBound]>, 607 pub bounds: Box<[TypeBound]>,
@@ -691,9 +611,9 @@ pub struct Trait {
691 611
692#[derive(Debug, Clone, Eq, PartialEq)] 612#[derive(Debug, Clone, Eq, PartialEq)]
693pub struct Impl { 613pub struct Impl {
694 pub generic_params: GenericParamsId, 614 pub generic_params: Interned<GenericParams>,
695 pub target_trait: Option<Idx<TypeRef>>, 615 pub target_trait: Option<Interned<TraitRef>>,
696 pub target_type: Idx<TypeRef>, 616 pub self_ty: Interned<TypeRef>,
697 pub is_negative: bool, 617 pub is_negative: bool,
698 pub items: Box<[AssocItem]>, 618 pub items: Box<[AssocItem]>,
699 pub ast_id: FileAstId<ast::Impl>, 619 pub ast_id: FileAstId<ast::Impl>,
@@ -705,8 +625,8 @@ pub struct TypeAlias {
705 pub visibility: RawVisibilityId, 625 pub visibility: RawVisibilityId,
706 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. 626 /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`.
707 pub bounds: Box<[TypeBound]>, 627 pub bounds: Box<[TypeBound]>,
708 pub generic_params: GenericParamsId, 628 pub generic_params: Interned<GenericParams>,
709 pub type_ref: Option<Idx<TypeRef>>, 629 pub type_ref: Option<Interned<TypeRef>>,
710 pub is_extern: bool, 630 pub is_extern: bool,
711 pub ast_id: FileAstId<ast::TypeAlias>, 631 pub ast_id: FileAstId<ast::TypeAlias>,
712} 632}
@@ -731,7 +651,7 @@ pub enum ModKind {
731#[derive(Debug, Clone, Eq, PartialEq)] 651#[derive(Debug, Clone, Eq, PartialEq)]
732pub struct MacroCall { 652pub struct MacroCall {
733 /// Path to the called macro. 653 /// Path to the called macro.
734 pub path: ModPath, 654 pub path: Interned<ModPath>,
735 pub ast_id: FileAstId<ast::MacroCall>, 655 pub ast_id: FileAstId<ast::MacroCall>,
736} 656}
737 657
@@ -896,6 +816,6 @@ pub enum Fields {
896#[derive(Debug, Clone, PartialEq, Eq)] 816#[derive(Debug, Clone, PartialEq, Eq)]
897pub struct Field { 817pub struct Field {
898 pub name: Name, 818 pub name: Name,
899 pub type_ref: Idx<TypeRef>, 819 pub type_ref: Interned<TypeRef>,
900 pub visibility: RawVisibilityId, 820 pub visibility: RawVisibilityId,
901} 821}
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 3f558edd8..c5629af24 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -11,7 +11,7 @@ use syntax::{
11 11
12use crate::{ 12use crate::{
13 generics::{GenericParams, TypeParamData, TypeParamProvenance}, 13 generics::{GenericParams, TypeParamData, TypeParamProvenance},
14 type_ref::LifetimeRef, 14 type_ref::{LifetimeRef, TraitRef},
15}; 15};
16 16
17use super::*; 17use super::*;
@@ -174,6 +174,12 @@ impl Ctx {
174 let forced_vis = self.forced_visibility.take(); 174 let forced_vis = self.forced_visibility.take();
175 175
176 let mut block_stack = Vec::new(); 176 let mut block_stack = Vec::new();
177
178 // if container itself is block, add it to the stack
179 if let Some(block) = ast::BlockExpr::cast(container.clone()) {
180 block_stack.push(self.source_ast_id_map.ast_id(&block));
181 }
182
177 for event in container.preorder().skip(1) { 183 for event in container.preorder().skip(1) {
178 match event { 184 match event {
179 WalkEvent::Enter(node) => { 185 WalkEvent::Enter(node) => {
@@ -356,7 +362,7 @@ impl Ctx {
356 } 362 }
357 } 363 }
358 }; 364 };
359 let ty = self.data().type_refs.intern(self_type); 365 let ty = Interned::new(self_type);
360 let idx = self.data().params.alloc(Param::Normal(ty)); 366 let idx = self.data().params.alloc(Param::Normal(ty));
361 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); 367 self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene));
362 has_self_param = true; 368 has_self_param = true;
@@ -366,7 +372,7 @@ impl Ctx {
366 Some(_) => self.data().params.alloc(Param::Varargs), 372 Some(_) => self.data().params.alloc(Param::Varargs),
367 None => { 373 None => {
368 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());
369 let ty = self.data().type_refs.intern(type_ref); 375 let ty = Interned::new(type_ref);
370 self.data().params.alloc(Param::Normal(ty)) 376 self.data().params.alloc(Param::Normal(ty))
371 } 377 }
372 }; 378 };
@@ -389,41 +395,51 @@ impl Ctx {
389 ret_type 395 ret_type
390 }; 396 };
391 397
392 let ret_type = self.data().type_refs.intern(ret_type); 398 let abi = func.abi().map(|abi| {
393 399 // FIXME: Abi::abi() -> Option<SyntaxToken>?
394 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 });
395 411
396 let ast_id = self.source_ast_id_map.ast_id(func); 412 let ast_id = self.source_ast_id_map.ast_id(func);
397 let qualifier = FunctionQualifier { 413
398 is_default: func.default_token().is_some(), 414 let mut flags = FnFlags::default();
399 is_const: func.const_token().is_some(), 415 if func.body().is_some() {
400 is_async: func.async_token().is_some(), 416 flags.bits |= FnFlags::HAS_BODY;
401 is_unsafe: func.unsafe_token().is_some(), 417 }
402 abi: func.abi().map(|abi| { 418 if has_self_param {
403 // FIXME: Abi::abi() -> Option<SyntaxToken>? 419 flags.bits |= FnFlags::HAS_SELF_PARAM;
404 match abi.syntax().last_token() { 420 }
405 Some(tok) if tok.kind() == SyntaxKind::STRING => { 421 if func.default_token().is_some() {
406 // FIXME: Better way to unescape? 422 flags.bits |= FnFlags::IS_DEFAULT;
407 tok.text().trim_matches('"').into() 423 }
408 } 424 if func.const_token().is_some() {
409 _ => { 425 flags.bits |= FnFlags::IS_CONST;
410 // `extern` default to be `extern "C"`. 426 }
411 "C".into() 427 if func.async_token().is_some() {
412 } 428 flags.bits |= FnFlags::IS_ASYNC;
413 } 429 }
414 }), 430 if func.unsafe_token().is_some() {
415 }; 431 flags.bits |= FnFlags::IS_UNSAFE;
432 }
433
416 let mut res = Function { 434 let mut res = Function {
417 name, 435 name,
418 visibility, 436 visibility,
419 generic_params: GenericParamsId::EMPTY, 437 generic_params: Interned::new(GenericParams::default()),
420 has_self_param, 438 abi,
421 has_body,
422 qualifier,
423 is_in_extern_block: false,
424 params, 439 params,
425 ret_type, 440 ret_type: Interned::new(ret_type),
426 ast_id, 441 ast_id,
442 flags,
427 }; 443 };
428 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); 444 res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func);
429 445
@@ -536,8 +552,11 @@ impl Ctx {
536 fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { 552 fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> {
537 let generic_params = 553 let generic_params =
538 self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); 554 self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def);
539 let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr)); 555 // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl
540 let target_type = self.lower_type_ref(&impl_def.self_ty()?); 556 // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only
557 // equals itself.
558 let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr));
559 let self_ty = self.lower_type_ref(&impl_def.self_ty()?);
541 let is_negative = impl_def.excl_token().is_some(); 560 let is_negative = impl_def.excl_token().is_some();
542 561
543 // We cannot use `assoc_items()` here as that does not include macro calls. 562 // We cannot use `assoc_items()` here as that does not include macro calls.
@@ -554,7 +573,7 @@ impl Ctx {
554 }) 573 })
555 .collect(); 574 .collect();
556 let ast_id = self.source_ast_id_map.ast_id(impl_def); 575 let ast_id = self.source_ast_id_map.ast_id(impl_def);
557 let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }; 576 let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id };
558 Some(id(self.data().impls.alloc(res))) 577 Some(id(self.data().impls.alloc(res)))
559 } 578 }
560 579
@@ -570,7 +589,7 @@ impl Ctx {
570 &self.hygiene, 589 &self.hygiene,
571 |path, _use_tree, is_glob, alias| { 590 |path, _use_tree, is_glob, alias| {
572 imports.push(id(tree.imports.alloc(Import { 591 imports.push(id(tree.imports.alloc(Import {
573 path, 592 path: Interned::new(path),
574 alias, 593 alias,
575 visibility, 594 visibility,
576 is_glob, 595 is_glob,
@@ -599,7 +618,7 @@ impl Ctx {
599 } 618 }
600 619
601 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>> {
602 let path = ModPath::from_src(m.path()?, &self.hygiene)?; 621 let path = Interned::new(ModPath::from_src(m.path()?, &self.hygiene)?);
603 let ast_id = self.source_ast_id_map.ast_id(m); 622 let ast_id = self.source_ast_id_map.ast_id(m);
604 let res = MacroCall { path, ast_id }; 623 let res = MacroCall { path, ast_id };
605 Some(id(self.data().macro_calls.alloc(res))) 624 Some(id(self.data().macro_calls.alloc(res)))
@@ -633,8 +652,10 @@ impl Ctx {
633 ast::ExternItem::Fn(ast) => { 652 ast::ExternItem::Fn(ast) => {
634 let func_id = self.lower_function(&ast)?; 653 let func_id = self.lower_function(&ast)?;
635 let func = &mut self.data().functions[func_id.index]; 654 let func = &mut self.data().functions[func_id.index];
636 func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); 655 if is_intrinsic_fn_unsafe(&func.name) {
637 func.is_in_extern_block = true; 656 func.flags.bits |= FnFlags::IS_UNSAFE;
657 }
658 func.flags.bits |= FnFlags::IS_IN_EXTERN_BLOCK;
638 func_id.into() 659 func_id.into()
639 } 660 }
640 ast::ExternItem::Static(ast) => { 661 ast::ExternItem::Static(ast) => {
@@ -661,7 +682,7 @@ impl Ctx {
661 &mut self, 682 &mut self,
662 owner: GenericsOwner<'_>, 683 owner: GenericsOwner<'_>,
663 node: &impl ast::GenericParamsOwner, 684 node: &impl ast::GenericParamsOwner,
664 ) -> GenericParamsId { 685 ) -> Interned<GenericParams> {
665 // Generics are part of item headers and may contain inner items we need to collect. 686 // Generics are part of item headers and may contain inner items we need to collect.
666 if let Some(params) = node.generic_param_list() { 687 if let Some(params) = node.generic_param_list() {
667 self.collect_inner_items(params.syntax()); 688 self.collect_inner_items(params.syntax());
@@ -677,7 +698,7 @@ impl Ctx {
677 &mut self, 698 &mut self,
678 owner: GenericsOwner<'_>, 699 owner: GenericsOwner<'_>,
679 node: &impl ast::GenericParamsOwner, 700 node: &impl ast::GenericParamsOwner,
680 ) -> GenericParamsId { 701 ) -> Interned<GenericParams> {
681 let mut sm = &mut Default::default(); 702 let mut sm = &mut Default::default();
682 let mut generics = GenericParams::default(); 703 let mut generics = GenericParams::default();
683 match owner { 704 match owner {
@@ -685,8 +706,7 @@ impl Ctx {
685 generics.fill(&self.body_ctx, sm, node); 706 generics.fill(&self.body_ctx, sm, node);
686 // lower `impl Trait` in arguments 707 // lower `impl Trait` in arguments
687 for id in func.params.clone() { 708 for id in func.params.clone() {
688 if let Param::Normal(ty) = self.data().params[id] { 709 if let Param::Normal(ty) = &self.data().params[id] {
689 let ty = self.data().type_refs.lookup(ty);
690 generics.fill_implicit_impl_trait_args(ty); 710 generics.fill_implicit_impl_trait_args(ty);
691 } 711 }
692 } 712 }
@@ -719,7 +739,8 @@ impl Ctx {
719 } 739 }
720 } 740 }
721 741
722 self.data().generics.alloc(generics) 742 generics.shrink_to_fit();
743 Interned::new(generics)
723 } 744 }
724 745
725 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> { 746 fn lower_type_bounds(&mut self, node: &impl ast::TypeBoundsOwner) -> Vec<TypeBound> {
@@ -740,14 +761,20 @@ impl Ctx {
740 self.data().vis.alloc(vis) 761 self.data().vis.alloc(vis)
741 } 762 }
742 763
743 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { 764 fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Interned<TraitRef>> {
765 let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?;
766 Some(Interned::new(trait_ref))
767 }
768
769 fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Interned<TypeRef> {
744 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); 770 let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone());
745 self.data().type_refs.intern(tyref) 771 Interned::new(tyref)
746 } 772 }
747 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { 773
774 fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Interned<TypeRef> {
748 match type_ref.map(|ty| self.lower_type_ref(&ty)) { 775 match type_ref.map(|ty| self.lower_type_ref(&ty)) {
749 Some(it) => it, 776 Some(it) => it,
750 None => self.data().type_refs.intern(TypeRef::Error), 777 None => Interned::new(TypeRef::Error),
751 } 778 }
752 } 779 }
753 780
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index c9e07de86..be9a5e1a0 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -27,6 +27,7 @@ pub mod dyn_map;
27pub mod keys; 27pub mod keys;
28 28
29pub mod item_tree; 29pub mod item_tree;
30pub mod intern;
30 31
31pub mod adt; 32pub mod adt;
32pub mod data; 33pub mod data;
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..f9c8328f0 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 {
@@ -122,8 +122,8 @@ impl ModPath {
122pub struct Path { 122pub struct Path {
123 /// Type based path like `<T>::foo`. 123 /// Type based path like `<T>::foo`.
124 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. 124 /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`.
125 type_anchor: Option<Box<TypeRef>>, 125 type_anchor: Option<Interned<TypeRef>>,
126 mod_path: 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 505493a74..7b29d9d4f 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;
@@ -68,15 +69,17 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
68 match trait_ref { 69 match trait_ref {
69 // <T>::foo 70 // <T>::foo
70 None => { 71 None => {
71 type_anchor = Some(Box::new(self_type)); 72 type_anchor = Some(Interned::new(self_type));
72 kind = PathKind::Plain; 73 kind = PathKind::Plain;
73 } 74 }
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)?;
77 kind = path.mod_path.kind; 78 let mod_path = (*path.mod_path).clone();
79 let num_segments = path.mod_path.segments.len();
80 kind = mod_path.kind;
78 81
79 let mut prefix_segments = path.mod_path.segments; 82 let mut prefix_segments = mod_path.segments;
80 prefix_segments.reverse(); 83 prefix_segments.reverse();
81 segments.extend(prefix_segments); 84 segments.extend(prefix_segments);
82 85
@@ -85,7 +88,8 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
85 generic_args.extend(prefix_args); 88 generic_args.extend(prefix_args);
86 89
87 // Insert the type reference (T in the above example) as Self parameter for the trait 90 // Insert the type reference (T in the above example) as Self parameter for the trait
88 let last_segment = generic_args.last_mut()?; 91 let last_segment =
92 generic_args.iter_mut().rev().nth(num_segments.saturating_sub(1))?;
89 if last_segment.is_none() { 93 if last_segment.is_none() {
90 *last_segment = Some(Arc::new(GenericArgs::empty())); 94 *last_segment = Some(Arc::new(GenericArgs::empty()));
91 }; 95 };
@@ -138,7 +142,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path>
138 } 142 }
139 } 143 }
140 144
141 let mod_path = ModPath::from_segments(kind, segments); 145 let mod_path = Interned::new(ModPath::from_segments(kind, segments));
142 return Some(Path { type_anchor, mod_path, generic_args }); 146 return Some(Path { type_anchor, mod_path, generic_args });
143 147
144 fn qualifier(path: &ast::Path) -> Option<ast::Path> { 148 fn qualifier(path: &ast::Path) -> Option<ast::Path> {
diff --git a/crates/hir_def/src/resolver.rs b/crates/hir_def/src/resolver.rs
index a73585ee7..0391cc49b 100644
--- a/crates/hir_def/src/resolver.rs
+++ b/crates/hir_def/src/resolver.rs
@@ -14,6 +14,7 @@ use crate::{
14 db::DefDatabase, 14 db::DefDatabase,
15 expr::{ExprId, LabelId, PatId}, 15 expr::{ExprId, LabelId, PatId},
16 generics::GenericParams, 16 generics::GenericParams,
17 intern::Interned,
17 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE}, 18 item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
18 nameres::DefMap, 19 nameres::DefMap,
19 path::{ModPath, PathKind}, 20 path::{ModPath, PathKind},
@@ -50,7 +51,7 @@ enum Scope {
50 /// All the items and imported names of a module 51 /// All the items and imported names of a module
51 ModuleScope(ModuleItemMap), 52 ModuleScope(ModuleItemMap),
52 /// Brings the generic parameters of an item into scope 53 /// Brings the generic parameters of an item into scope
53 GenericParams { def: GenericDefId, params: Arc<GenericParams> }, 54 GenericParams { def: GenericDefId, params: Interned<GenericParams> },
54 /// Brings `Self` in `impl` block into scope 55 /// Brings `Self` in `impl` block into scope
55 ImplDefScope(ImplId), 56 ImplDefScope(ImplId),
56 /// Brings `Self` in enum, struct and union definitions into scope 57 /// Brings `Self` in enum, struct and union definitions into scope
diff --git a/crates/hir_def/src/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_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs
index 049b2e462..4c24aae94 100644
--- a/crates/hir_def/src/type_ref.rs
+++ b/crates/hir_def/src/type_ref.rs
@@ -51,6 +51,23 @@ impl Rawness {
51 } 51 }
52} 52}
53 53
54#[derive(Clone, PartialEq, Eq, Hash, Debug)]
55pub struct TraitRef {
56 pub path: Path,
57}
58
59impl TraitRef {
60 /// Converts an `ast::PathType` to a `hir::TraitRef`.
61 pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Option<Self> {
62 // FIXME: Use `Path::from_src`
63 match node {
64 ast::Type::PathType(path) => {
65 path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path })
66 }
67 _ => None,
68 }
69 }
70}
54/// Compare ty::Ty 71/// Compare ty::Ty
55#[derive(Clone, PartialEq, Eq, Hash, Debug)] 72#[derive(Clone, PartialEq, Eq, Hash, Debug)]
56pub enum TypeRef { 73pub enum TypeRef {
diff --git a/crates/hir_def/src/visibility.rs b/crates/hir_def/src/visibility.rs
index 7d00a37c4..9908cd926 100644
--- a/crates/hir_def/src/visibility.rs
+++ b/crates/hir_def/src/visibility.rs
@@ -11,7 +11,7 @@ use crate::{
11 nameres::DefMap, 11 nameres::DefMap,
12 path::{ModPath, PathKind}, 12 path::{ModPath, PathKind},
13 resolver::HasResolver, 13 resolver::HasResolver,
14 FunctionId, HasModule, LocalFieldId, ModuleDefId, ModuleId, VariantId, 14 FunctionId, HasModule, LocalFieldId, ModuleId, VariantId,
15}; 15};
16 16
17/// Visibility of an item, not yet resolved. 17/// Visibility of an item, not yet resolved.
@@ -25,7 +25,7 @@ pub enum RawVisibility {
25} 25}
26 26
27impl RawVisibility { 27impl RawVisibility {
28 pub(crate) const fn private() -> RawVisibility { 28 pub(crate) fn private() -> RawVisibility {
29 RawVisibility::Module(ModPath::from_kind(PathKind::Super(0))) 29 RawVisibility::Module(ModPath::from_kind(PathKind::Super(0)))
30 } 30 }
31 31
@@ -217,6 +217,6 @@ pub(crate) fn field_visibilities_query(
217 217
218/// Resolve visibility of a function. 218/// Resolve visibility of a function.
219pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility { 219pub(crate) fn function_visibility_query(db: &dyn DefDatabase, def: FunctionId) -> Visibility {
220 let resolver = ModuleDefId::from(def).module(db).unwrap().resolver(db); 220 let resolver = def.resolver(db);
221 db.function_data(def).visibility.resolve(db, &resolver) 221 db.function_data(def).visibility.resolve(db, &resolver)
222} 222}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 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 cd691b1d2..a0f8766b0 100644
--- a/crates/hir_expand/src/name.rs
+++ b/crates/hir_expand/src/name.rs
@@ -55,6 +55,15 @@ impl Name {
55 } 55 }
56 } 56 }
57 57
58 /// A fake name for things missing in the source code.
59 ///
60 /// For example, `impl Foo for {}` should be treated as a trait impl for a
61 /// type with a missing name. Similarly, `struct S { : u32 }` should have a
62 /// single field with a missing name.
63 ///
64 /// Ideally, we want a `gensym` semantics for missing names -- each missing
65 /// name is equal only to itself. It's not clear how to implement this in
66 /// salsa though, so we punt on that bit for a moment.
58 pub fn missing() -> Name { 67 pub fn missing() -> Name {
59 Name::new_text("[missing name]".into()) 68 Name::new_text("[missing name]".into())
60 } 69 }
@@ -199,6 +208,8 @@ pub mod known {
199 line, 208 line,
200 module_path, 209 module_path,
201 assert, 210 assert,
211 core_panic,
212 std_panic,
202 stringify, 213 stringify,
203 concat, 214 concat,
204 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..7ca4af80e 100644
--- a/crates/hir_ty/src/autoderef.rs
+++ b/crates/hir_ty/src/autoderef.rs
@@ -12,12 +12,8 @@ use hir_expand::name::name;
12use log::{info, warn}; 12use log::{info, warn};
13 13
14use crate::{ 14use crate::{
15 db::HirDatabase, 15 db::HirDatabase, AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex,
16 to_assoc_type_id, to_chalk_trait_id, 16 InEnvironment, Interner, Solution, Ty, TyBuilder, TyKind,
17 traits::{InEnvironment, Solution},
18 utils::generics,
19 AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner,
20 ProjectionTy, Substitution, TraitRef, Ty, TyKind,
21}; 17};
22 18
23const AUTODEREF_RECURSION_LIMIT: usize = 10; 19const AUTODEREF_RECURSION_LIMIT: usize = 10;
@@ -57,21 +53,20 @@ fn deref_by_trait(
57 }; 53 };
58 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; 54 let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?;
59 55
60 let generic_params = generics(db.upcast(), target.into()); 56 let projection = {
61 if generic_params.len() != 1 { 57 let b = TyBuilder::assoc_type_projection(db, target);
62 // the Target type + Deref trait should only have one generic parameter, 58 if b.remaining() != 1 {
63 // namely Deref's Self type 59 // the Target type + Deref trait should only have one generic parameter,
64 return None; 60 // namely Deref's Self type
65 } 61 return None;
62 }
63 b.push(ty.goal.value.clone()).build()
64 };
66 65
67 // FIXME make the Canonical / bound var handling nicer 66 // FIXME make the Canonical / bound var handling nicer
68 67
69 let parameters =
70 Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build();
71
72 // Check that the type implements Deref at all 68 // Check that the type implements Deref at all
73 let trait_ref = 69 let trait_ref = projection.trait_ref(db);
74 TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() };
75 let implements_goal = Canonical { 70 let implements_goal = Canonical {
76 binders: ty.goal.binders.clone(), 71 binders: ty.goal.binders.clone(),
77 value: InEnvironment { 72 value: InEnvironment {
@@ -84,11 +79,8 @@ fn deref_by_trait(
84 } 79 }
85 80
86 // Now do the assoc type projection 81 // Now do the assoc type projection
87 let projection = AliasEq { 82 let alias_eq = AliasEq {
88 alias: AliasTy::Projection(ProjectionTy { 83 alias: AliasTy::Projection(projection),
89 associated_ty_id: to_assoc_type_id(target),
90 substitution: parameters,
91 }),
92 ty: TyKind::BoundVar(BoundVar::new( 84 ty: TyKind::BoundVar(BoundVar::new(
93 DebruijnIndex::INNERMOST, 85 DebruijnIndex::INNERMOST,
94 ty.goal.binders.len(&Interner), 86 ty.goal.binders.len(&Interner),
@@ -96,9 +88,7 @@ fn deref_by_trait(
96 .intern(&Interner), 88 .intern(&Interner),
97 }; 89 };
98 90
99 let obligation = projection.cast(&Interner); 91 let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment };
100
101 let in_env = InEnvironment { goal: obligation, environment: ty.environment };
102 92
103 let canonical = Canonical { 93 let canonical = Canonical {
104 value: in_env, 94 value: in_env,
@@ -131,7 +121,7 @@ fn deref_by_trait(
131 // new variables in that case 121 // new variables in that case
132 122
133 for i in 1..vars.0.binders.len(&Interner) { 123 for i in 1..vars.0.binders.len(&Interner) {
134 if vars.0.value[i - 1].interned(&Interner) 124 if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner)
135 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) 125 != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1))
136 { 126 {
137 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); 127 warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution);
@@ -139,7 +129,12 @@ fn deref_by_trait(
139 } 129 }
140 } 130 }
141 Some(Canonical { 131 Some(Canonical {
142 value: vars.0.value[vars.0.value.len() - 1].clone(), 132 value: vars
133 .0
134 .value
135 .at(&a