diff options
Diffstat (limited to 'crates')
64 files changed, 1499 insertions, 908 deletions
diff --git a/crates/cfg/src/tests.rs b/crates/cfg/src/tests.rs index bd0f9ec48..d8736c893 100644 --- a/crates/cfg/src/tests.rs +++ b/crates/cfg/src/tests.rs | |||
@@ -8,7 +8,7 @@ fn assert_parse_result(input: &str, expected: CfgExpr) { | |||
8 | let (tt, _) = { | 8 | let (tt, _) = { |
9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 9 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 10 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
11 | ast_to_token_tree(&tt).unwrap() | 11 | ast_to_token_tree(&tt) |
12 | }; | 12 | }; |
13 | let cfg = CfgExpr::parse(&tt); | 13 | let cfg = CfgExpr::parse(&tt); |
14 | assert_eq!(cfg, expected); | 14 | assert_eq!(cfg, expected); |
@@ -18,7 +18,7 @@ fn check_dnf(input: &str, expect: Expect) { | |||
18 | let (tt, _) = { | 18 | let (tt, _) = { |
19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 19 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 20 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
21 | ast_to_token_tree(&tt).unwrap() | 21 | ast_to_token_tree(&tt) |
22 | }; | 22 | }; |
23 | let cfg = CfgExpr::parse(&tt); | 23 | let cfg = CfgExpr::parse(&tt); |
24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); | 24 | let actual = format!("#![cfg({})]", DnfExpr::new(cfg)); |
@@ -29,7 +29,7 @@ fn check_why_inactive(input: &str, opts: &CfgOptions, expect: Expect) { | |||
29 | let (tt, _) = { | 29 | let (tt, _) = { |
30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 30 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 31 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
32 | ast_to_token_tree(&tt).unwrap() | 32 | ast_to_token_tree(&tt) |
33 | }; | 33 | }; |
34 | let cfg = CfgExpr::parse(&tt); | 34 | let cfg = CfgExpr::parse(&tt); |
35 | let dnf = DnfExpr::new(cfg); | 35 | let dnf = DnfExpr::new(cfg); |
@@ -42,7 +42,7 @@ fn check_enable_hints(input: &str, opts: &CfgOptions, expected_hints: &[&str]) { | |||
42 | let (tt, _) = { | 42 | let (tt, _) = { |
43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); | 43 | let source_file = ast::SourceFile::parse(input).ok().unwrap(); |
44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); | 44 | let tt = source_file.syntax().descendants().find_map(ast::TokenTree::cast).unwrap(); |
45 | ast_to_token_tree(&tt).unwrap() | 45 | ast_to_token_tree(&tt) |
46 | }; | 46 | }; |
47 | let cfg = CfgExpr::parse(&tt); | 47 | let cfg = CfgExpr::parse(&tt); |
48 | let dnf = DnfExpr::new(cfg); | 48 | let dnf = DnfExpr::new(cfg); |
diff --git a/crates/hir/src/db.rs b/crates/hir/src/db.rs index 1902a8d16..df5758342 100644 --- a/crates/hir/src/db.rs +++ b/crates/hir/src/db.rs | |||
@@ -1,14 +1,6 @@ | |||
1 | //! FIXME: write short doc here | 1 | //! FIXME: write short doc here |
2 | 2 | ||
3 | pub use hir_def::db::{ | 3 | pub use hir_def::db::*; |
4 | AttrsQuery, BlockDefMapQuery, BodyQuery, BodyWithSourceMapQuery, ConstDataQuery, | ||
5 | CrateDefMapQueryQuery, CrateLangItemsQuery, DefDatabase, DefDatabaseStorage, EnumDataQuery, | ||
6 | ExprScopesQuery, FileItemTreeQuery, FunctionDataQuery, GenericParamsQuery, ImplDataQuery, | ||
7 | ImportMapQuery, InternConstQuery, InternDatabase, InternDatabaseStorage, InternEnumQuery, | ||
8 | InternFunctionQuery, InternImplQuery, InternStaticQuery, InternStructQuery, InternTraitQuery, | ||
9 | InternTypeAliasQuery, InternUnionQuery, LangItemQuery, StaticDataQuery, StructDataQuery, | ||
10 | TraitDataQuery, TypeAliasDataQuery, UnionDataQuery, | ||
11 | }; | ||
12 | pub use hir_expand::db::{ | 4 | pub use hir_expand::db::{ |
13 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, | 5 | AstDatabase, AstDatabaseStorage, AstIdMapQuery, HygieneFrameQuery, InternEagerExpansionQuery, |
14 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, | 6 | InternMacroQuery, MacroArgTextQuery, MacroDefQuery, MacroExpandQuery, ParseMacroExpansionQuery, |
diff --git a/crates/hir/src/display.rs b/crates/hir/src/display.rs index 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 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, | 15 | Adt, Const, ConstParam, Enum, Field, Function, GenericParam, HasVisibility, LifetimeParam, |
16 | Module, Static, Struct, Substitution, Trait, Type, TypeAlias, TypeParam, Union, Variant, | 16 | Module, Static, Struct, Trait, TyBuilder, Type, TypeAlias, TypeParam, Union, Variant, |
17 | }; | 17 | }; |
18 | 18 | ||
19 | impl HirDisplay for Function { | 19 | impl HirDisplay for Function { |
20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 20 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
21 | let data = f.db.function_data(self.id); | 21 | let data = f.db.function_data(self.id); |
22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; | 22 | write_visibility(self.module(f.db).id, self.visibility(f.db), f)?; |
23 | let qual = &data.qualifier; | 23 | if data.is_default() { |
24 | if qual.is_default { | ||
25 | write!(f, "default ")?; | 24 | write!(f, "default ")?; |
26 | } | 25 | } |
27 | if qual.is_const { | 26 | if data.is_const() { |
28 | write!(f, "const ")?; | 27 | write!(f, "const ")?; |
29 | } | 28 | } |
30 | if qual.is_async { | 29 | if data.is_async() { |
31 | write!(f, "async ")?; | 30 | write!(f, "async ")?; |
32 | } | 31 | } |
33 | if qual.is_unsafe { | 32 | if data.is_unsafe() { |
34 | write!(f, "unsafe ")?; | 33 | write!(f, "unsafe ")?; |
35 | } | 34 | } |
36 | if let Some(abi) = &qual.abi { | 35 | if let Some(abi) = &data.abi { |
37 | // FIXME: String escape? | 36 | // FIXME: String escape? |
38 | write!(f, "extern \"{}\" ", abi)?; | 37 | write!(f, "extern \"{}\" ", &**abi)?; |
39 | } | 38 | } |
40 | write!(f, "fn {}", data.name)?; | 39 | write!(f, "fn {}", data.name)?; |
41 | 40 | ||
@@ -68,7 +67,7 @@ impl HirDisplay for Function { | |||
68 | write!(f, ", ")?; | 67 | write!(f, ", ")?; |
69 | } else { | 68 | } else { |
70 | first = false; | 69 | first = false; |
71 | if data.has_self_param { | 70 | if data.has_self_param() { |
72 | write_self_param(type_ref, f)?; | 71 | write_self_param(type_ref, f)?; |
73 | continue; | 72 | continue; |
74 | } | 73 | } |
@@ -88,10 +87,10 @@ impl HirDisplay for Function { | |||
88 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. | 87 | // `FunctionData::ret_type` will be `::core::future::Future<Output = ...>` for async fns. |
89 | // Use ugly pattern match to strip the Future trait. | 88 | // Use ugly pattern match to strip the Future trait. |
90 | // Better way? | 89 | // Better way? |
91 | let ret_type = if !qual.is_async { | 90 | let ret_type = if !data.is_async() { |
92 | &data.ret_type | 91 | &data.ret_type |
93 | } else { | 92 | } else { |
94 | match &data.ret_type { | 93 | match &*data.ret_type { |
95 | TypeRef::ImplTrait(bounds) => match &bounds[0] { | 94 | TypeRef::ImplTrait(bounds) => match &bounds[0] { |
96 | TypeBound::Path(path) => { | 95 | TypeBound::Path(path) => { |
97 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings | 96 | path.segments().iter().last().unwrap().args_and_bindings.unwrap().bindings |
@@ -235,7 +234,7 @@ impl HirDisplay for TypeParam { | |||
235 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 234 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
236 | write!(f, "{}", self.name(f.db))?; | 235 | write!(f, "{}", self.name(f.db))?; |
237 | let bounds = f.db.generic_predicates_for_param(self.id); | 236 | let bounds = f.db.generic_predicates_for_param(self.id); |
238 | let substs = Substitution::type_params(f.db, self.id.parent); | 237 | let substs = TyBuilder::type_params_subst(f.db, self.id.parent); |
239 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); | 238 | let predicates = bounds.iter().cloned().map(|b| b.subst(&substs)).collect::<Vec<_>>(); |
240 | if !(predicates.is_empty() || f.omit_verbose_types()) { | 239 | if !(predicates.is_empty() || f.omit_verbose_types()) { |
241 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; | 240 | write_bounds_like_dyn_trait_with_prefix(":", &predicates, f)?; |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 97f162315..19901ed33 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -55,11 +55,10 @@ use hir_ty::{ | |||
55 | autoderef, could_unify, | 55 | autoderef, could_unify, |
56 | method_resolution::{self, TyFingerprint}, | 56 | method_resolution::{self, TyFingerprint}, |
57 | primitive::UintTy, | 57 | primitive::UintTy, |
58 | to_assoc_type_id, | ||
59 | traits::{FnTrait, Solution, SolutionVariables}, | 58 | traits::{FnTrait, Solution, SolutionVariables}, |
60 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, | 59 | AliasEq, AliasTy, BoundVar, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, |
61 | DebruijnIndex, InEnvironment, Interner, ProjectionTy, QuantifiedWhereClause, Scalar, | 60 | DebruijnIndex, InEnvironment, Interner, QuantifiedWhereClause, Scalar, Substitution, |
62 | Substitution, TraitEnvironment, Ty, TyDefId, TyKind, TyVariableKind, WhereClause, | 61 | TraitEnvironment, Ty, TyBuilder, TyDefId, TyKind, TyVariableKind, WhereClause, |
63 | }; | 62 | }; |
64 | use itertools::Itertools; | 63 | use itertools::Itertools; |
65 | use rustc_hash::FxHashSet; | 64 | use rustc_hash::FxHashSet; |
@@ -515,7 +514,7 @@ impl Field { | |||
515 | VariantDef::Union(it) => it.id.into(), | 514 | VariantDef::Union(it) => it.id.into(), |
516 | VariantDef::Variant(it) => it.parent.id.into(), | 515 | VariantDef::Variant(it) => it.parent.id.into(), |
517 | }; | 516 | }; |
518 | let substs = Substitution::type_params(db, generic_def_id); | 517 | let substs = TyBuilder::type_params_subst(db, generic_def_id); |
519 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); | 518 | let ty = db.field_types(var_id)[self.id].clone().subst(&substs); |
520 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) | 519 | Type::new(db, self.parent.module(db).id.krate(), var_id, ty) |
521 | } | 520 | } |
@@ -832,7 +831,7 @@ impl Function { | |||
832 | } | 831 | } |
833 | 832 | ||
834 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { | 833 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { |
835 | if !db.function_data(self.id).has_self_param { | 834 | if !db.function_data(self.id).has_self_param() { |
836 | return None; | 835 | return None; |
837 | } | 836 | } |
838 | Some(SelfParam { func: self.id }) | 837 | Some(SelfParam { func: self.id }) |
@@ -864,7 +863,7 @@ impl Function { | |||
864 | } | 863 | } |
865 | 864 | ||
866 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { | 865 | pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { |
867 | db.function_data(self.id).qualifier.is_unsafe | 866 | db.function_data(self.id).is_unsafe() |
868 | } | 867 | } |
869 | 868 | ||
870 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { | 869 | pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { |
@@ -878,7 +877,7 @@ impl Function { | |||
878 | /// | 877 | /// |
879 | /// This is false in the case of required (not provided) trait methods. | 878 | /// This is false in the case of required (not provided) trait methods. |
880 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { | 879 | pub fn has_body(self, db: &dyn HirDatabase) -> bool { |
881 | db.function_data(self.id).has_body | 880 | db.function_data(self.id).has_body() |
882 | } | 881 | } |
883 | 882 | ||
884 | /// A textual representation of the HIR of this function for debugging purposes. | 883 | /// A textual representation of the HIR of this function for debugging purposes. |
@@ -957,7 +956,7 @@ impl SelfParam { | |||
957 | func_data | 956 | func_data |
958 | .params | 957 | .params |
959 | .first() | 958 | .first() |
960 | .map(|param| match *param { | 959 | .map(|param| match &**param { |
961 | TypeRef::Reference(.., mutability) => match mutability { | 960 | TypeRef::Reference(.., mutability) => match mutability { |
962 | hir_def::type_ref::Mutability::Shared => Access::Shared, | 961 | hir_def::type_ref::Mutability::Shared => Access::Shared, |
963 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, | 962 | hir_def::type_ref::Mutability::Mut => Access::Exclusive, |
@@ -1011,7 +1010,7 @@ impl Const { | |||
1011 | } | 1010 | } |
1012 | 1011 | ||
1013 | pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { | 1012 | pub fn type_ref(self, db: &dyn HirDatabase) -> TypeRef { |
1014 | db.const_data(self.id).type_ref.clone() | 1013 | db.const_data(self.id).type_ref.as_ref().clone() |
1015 | } | 1014 | } |
1016 | } | 1015 | } |
1017 | 1016 | ||
@@ -1101,7 +1100,7 @@ impl TypeAlias { | |||
1101 | } | 1100 | } |
1102 | 1101 | ||
1103 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1102 | pub fn type_ref(self, db: &dyn HirDatabase) -> Option<TypeRef> { |
1104 | db.type_alias_data(self.id).type_ref.clone() | 1103 | db.type_alias_data(self.id).type_ref.as_deref().cloned() |
1105 | } | 1104 | } |
1106 | 1105 | ||
1107 | pub fn ty(self, db: &dyn HirDatabase) -> Type { | 1106 | pub fn ty(self, db: &dyn HirDatabase) -> Type { |
@@ -1129,7 +1128,7 @@ pub struct BuiltinType { | |||
1129 | impl BuiltinType { | 1128 | impl BuiltinType { |
1130 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { | 1129 | pub fn ty(self, db: &dyn HirDatabase, module: Module) -> Type { |
1131 | let resolver = module.id.resolver(db.upcast()); | 1130 | let resolver = module.id.resolver(db.upcast()); |
1132 | Type::new_with_resolver(db, &resolver, Ty::builtin(self.inner)) | 1131 | Type::new_with_resolver(db, &resolver, TyBuilder::builtin(self.inner)) |
1133 | .expect("crate not present in resolver") | 1132 | .expect("crate not present in resolver") |
1134 | } | 1133 | } |
1135 | 1134 | ||
@@ -1502,7 +1501,7 @@ impl TypeParam { | |||
1502 | let resolver = self.id.parent.resolver(db.upcast()); | 1501 | let resolver = self.id.parent.resolver(db.upcast()); |
1503 | let krate = self.id.parent.module(db.upcast()).krate(); | 1502 | let krate = self.id.parent.module(db.upcast()).krate(); |
1504 | let ty = params.get(local_idx)?.clone(); | 1503 | let ty = params.get(local_idx)?.clone(); |
1505 | let subst = Substitution::type_params(db, self.id.parent); | 1504 | let subst = TyBuilder::type_params_subst(db, self.id.parent); |
1506 | let ty = ty.subst(&subst.prefix(local_idx)); | 1505 | let ty = ty.subst(&subst.prefix(local_idx)); |
1507 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) | 1506 | Some(Type::new_with_resolver_inner(db, krate, &resolver, ty)) |
1508 | } | 1507 | } |
@@ -1615,7 +1614,7 @@ impl Impl { | |||
1615 | // FIXME: the return type is wrong. This should be a hir version of | 1614 | // FIXME: the return type is wrong. This should be a hir version of |
1616 | // `TraitRef` (ie, resolved `TypeRef`). | 1615 | // `TraitRef` (ie, resolved `TypeRef`). |
1617 | pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> { | 1616 | pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> { |
1618 | db.impl_data(self.id).target_trait.clone() | 1617 | db.impl_data(self.id).target_trait.as_deref().cloned() |
1619 | } | 1618 | } |
1620 | 1619 | ||
1621 | pub fn self_ty(self, db: &dyn HirDatabase) -> Type { | 1620 | pub fn self_ty(self, db: &dyn HirDatabase) -> Type { |
@@ -1703,30 +1702,29 @@ impl Type { | |||
1703 | fn from_def( | 1702 | fn from_def( |
1704 | db: &dyn HirDatabase, | 1703 | db: &dyn HirDatabase, |
1705 | krate: CrateId, | 1704 | krate: CrateId, |
1706 | def: impl HasResolver + Into<TyDefId> + Into<GenericDefId>, | 1705 | def: impl HasResolver + Into<TyDefId>, |
1707 | ) -> Type { | 1706 | ) -> Type { |
1708 | let substs = Substitution::build_for_def(db, def).fill_with_unknown().build(); | 1707 | let ty = TyBuilder::def_ty(db, def.into()).fill_with_unknown().build(); |
1709 | let ty = db.ty(def.into()).subst(&substs); | ||
1710 | Type::new(db, krate, def, ty) | 1708 | Type::new(db, krate, def, ty) |
1711 | } | 1709 | } |
1712 | 1710 | ||
1713 | pub fn is_unit(&self) -> bool { | 1711 | pub fn is_unit(&self) -> bool { |
1714 | matches!(self.ty.interned(&Interner), TyKind::Tuple(0, ..)) | 1712 | matches!(self.ty.kind(&Interner), TyKind::Tuple(0, ..)) |
1715 | } | 1713 | } |
1716 | pub fn is_bool(&self) -> bool { | 1714 | pub fn is_bool(&self) -> bool { |
1717 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Bool)) | 1715 | matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Bool)) |
1718 | } | 1716 | } |
1719 | 1717 | ||
1720 | pub fn is_mutable_reference(&self) -> bool { | 1718 | pub fn is_mutable_reference(&self) -> bool { |
1721 | matches!(self.ty.interned(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) | 1719 | matches!(self.ty.kind(&Interner), TyKind::Ref(hir_ty::Mutability::Mut, ..)) |
1722 | } | 1720 | } |
1723 | 1721 | ||
1724 | pub fn is_usize(&self) -> bool { | 1722 | pub fn is_usize(&self) -> bool { |
1725 | matches!(self.ty.interned(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) | 1723 | matches!(self.ty.kind(&Interner), TyKind::Scalar(Scalar::Uint(UintTy::Usize))) |
1726 | } | 1724 | } |
1727 | 1725 | ||
1728 | pub fn remove_ref(&self) -> Option<Type> { | 1726 | pub fn remove_ref(&self) -> Option<Type> { |
1729 | match &self.ty.interned(&Interner) { | 1727 | match &self.ty.kind(&Interner) { |
1730 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), | 1728 | TyKind::Ref(.., ty) => Some(self.derived(ty.clone())), |
1731 | _ => None, | 1729 | _ => None, |
1732 | } | 1730 | } |
@@ -1785,13 +1783,10 @@ impl Type { | |||
1785 | } | 1783 | } |
1786 | 1784 | ||
1787 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { | 1785 | pub fn impls_trait(&self, db: &dyn HirDatabase, trait_: Trait, args: &[Type]) -> bool { |
1788 | let trait_ref = hir_ty::TraitRef { | 1786 | let trait_ref = TyBuilder::trait_ref(db, trait_.id) |
1789 | trait_id: hir_ty::to_chalk_trait_id(trait_.id), | 1787 | .push(self.ty.clone()) |
1790 | substitution: Substitution::build_for_def(db, trait_.id) | 1788 | .fill(args.iter().map(|t| t.ty.clone())) |
1791 | .push(self.ty.clone()) | 1789 | .build(); |
1792 | .fill(args.iter().map(|t| t.ty.clone())) | ||
1793 | .build(), | ||
1794 | }; | ||
1795 | 1790 | ||
1796 | let goal = Canonical { | 1791 | let goal = Canonical { |
1797 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), | 1792 | value: hir_ty::InEnvironment::new(self.env.env.clone(), trait_ref.cast(&Interner)), |
@@ -1804,11 +1799,10 @@ impl Type { | |||
1804 | pub fn normalize_trait_assoc_type( | 1799 | pub fn normalize_trait_assoc_type( |
1805 | &self, | 1800 | &self, |
1806 | db: &dyn HirDatabase, | 1801 | db: &dyn HirDatabase, |
1807 | trait_: Trait, | ||
1808 | args: &[Type], | 1802 | args: &[Type], |
1809 | alias: TypeAlias, | 1803 | alias: TypeAlias, |
1810 | ) -> Option<Type> { | 1804 | ) -> Option<Type> { |
1811 | let subst = Substitution::build_for_def(db, trait_.id) | 1805 | let projection = TyBuilder::assoc_type_projection(db, alias.id) |
1812 | .push(self.ty.clone()) | 1806 | .push(self.ty.clone()) |
1813 | .fill(args.iter().map(|t| t.ty.clone())) | 1807 | .fill(args.iter().map(|t| t.ty.clone())) |
1814 | .build(); | 1808 | .build(); |
@@ -1816,10 +1810,7 @@ impl Type { | |||
1816 | InEnvironment::new( | 1810 | InEnvironment::new( |
1817 | self.env.env.clone(), | 1811 | self.env.env.clone(), |
1818 | AliasEq { | 1812 | AliasEq { |
1819 | alias: AliasTy::Projection(ProjectionTy { | 1813 | alias: AliasTy::Projection(projection), |
1820 | associated_ty_id: to_assoc_type_id(alias.id), | ||
1821 | substitution: subst, | ||
1822 | }), | ||
1823 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) | 1814 | ty: TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, 0)) |
1824 | .intern(&Interner), | 1815 | .intern(&Interner), |
1825 | } | 1816 | } |
@@ -1829,9 +1820,11 @@ impl Type { | |||
1829 | ); | 1820 | ); |
1830 | 1821 | ||
1831 | match db.trait_solve(self.krate, goal)? { | 1822 | match db.trait_solve(self.krate, goal)? { |
1832 | Solution::Unique(SolutionVariables(subst)) => { | 1823 | Solution::Unique(SolutionVariables(subst)) => subst |
1833 | subst.value.first().map(|ty| self.derived(ty.clone())) | 1824 | .value |
1834 | } | 1825 | .interned(&Interner) |
1826 | .first() | ||
1827 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())), | ||
1835 | Solution::Ambig(_) => None, | 1828 | Solution::Ambig(_) => None, |
1836 | } | 1829 | } |
1837 | } | 1830 | } |
@@ -1853,15 +1846,15 @@ impl Type { | |||
1853 | } | 1846 | } |
1854 | 1847 | ||
1855 | pub fn is_closure(&self) -> bool { | 1848 | pub fn is_closure(&self) -> bool { |
1856 | matches!(&self.ty.interned(&Interner), TyKind::Closure { .. }) | 1849 | matches!(&self.ty.kind(&Interner), TyKind::Closure { .. }) |
1857 | } | 1850 | } |
1858 | 1851 | ||
1859 | pub fn is_fn(&self) -> bool { | 1852 | pub fn is_fn(&self) -> bool { |
1860 | matches!(&self.ty.interned(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) | 1853 | matches!(&self.ty.kind(&Interner), TyKind::FnDef(..) | TyKind::Function { .. }) |
1861 | } | 1854 | } |
1862 | 1855 | ||
1863 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { | 1856 | pub fn is_packed(&self, db: &dyn HirDatabase) -> bool { |
1864 | let adt_id = match self.ty.interned(&Interner) { | 1857 | let adt_id = match self.ty.kind(&Interner) { |
1865 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, | 1858 | &TyKind::Adt(hir_ty::AdtId(adt_id), ..) => adt_id, |
1866 | _ => return false, | 1859 | _ => return false, |
1867 | }; | 1860 | }; |
@@ -1874,14 +1867,14 @@ impl Type { | |||
1874 | } | 1867 | } |
1875 | 1868 | ||
1876 | pub fn is_raw_ptr(&self) -> bool { | 1869 | pub fn is_raw_ptr(&self) -> bool { |
1877 | matches!(&self.ty.interned(&Interner), TyKind::Raw(..)) | 1870 | matches!(&self.ty.kind(&Interner), TyKind::Raw(..)) |
1878 | } | 1871 | } |
1879 | 1872 | ||
1880 | pub fn contains_unknown(&self) -> bool { | 1873 | pub fn contains_unknown(&self) -> bool { |
1881 | return go(&self.ty); | 1874 | return go(&self.ty); |
1882 | 1875 | ||
1883 | fn go(ty: &Ty) -> bool { | 1876 | fn go(ty: &Ty) -> bool { |
1884 | match ty.interned(&Interner) { | 1877 | match ty.kind(&Interner) { |
1885 | TyKind::Unknown => true, | 1878 | TyKind::Unknown => true, |
1886 | 1879 | ||
1887 | TyKind::Adt(_, substs) | 1880 | TyKind::Adt(_, substs) |
@@ -1889,7 +1882,9 @@ impl Type { | |||
1889 | | TyKind::Tuple(_, substs) | 1882 | | TyKind::Tuple(_, substs) |
1890 | | TyKind::OpaqueType(_, substs) | 1883 | | TyKind::OpaqueType(_, substs) |
1891 | | TyKind::FnDef(_, substs) | 1884 | | TyKind::FnDef(_, substs) |
1892 | | TyKind::Closure(_, substs) => substs.iter().any(go), | 1885 | | TyKind::Closure(_, substs) => { |
1886 | substs.iter(&Interner).filter_map(|a| a.ty(&Interner)).any(go) | ||
1887 | } | ||
1893 | 1888 | ||
1894 | TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { | 1889 | TyKind::Array(ty) | TyKind::Slice(ty) | TyKind::Raw(_, ty) | TyKind::Ref(_, ty) => { |
1895 | go(ty) | 1890 | go(ty) |
@@ -1910,7 +1905,7 @@ impl Type { | |||
1910 | } | 1905 | } |
1911 | 1906 | ||
1912 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { | 1907 | pub fn fields(&self, db: &dyn HirDatabase) -> Vec<(Field, Type)> { |
1913 | let (variant_id, substs) = match self.ty.interned(&Interner) { | 1908 | let (variant_id, substs) = match self.ty.kind(&Interner) { |
1914 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), | 1909 | &TyKind::Adt(hir_ty::AdtId(AdtId::StructId(s)), ref substs) => (s.into(), substs), |
1915 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), | 1910 | &TyKind::Adt(hir_ty::AdtId(AdtId::UnionId(u)), ref substs) => (u.into(), substs), |
1916 | _ => return Vec::new(), | 1911 | _ => return Vec::new(), |
@@ -1927,8 +1922,11 @@ impl Type { | |||
1927 | } | 1922 | } |
1928 | 1923 | ||
1929 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { | 1924 | pub fn tuple_fields(&self, _db: &dyn HirDatabase) -> Vec<Type> { |
1930 | if let TyKind::Tuple(_, substs) = &self.ty.interned(&Interner) { | 1925 | if let TyKind::Tuple(_, substs) = &self.ty.kind(&Interner) { |
1931 | substs.iter().map(|ty| self.derived(ty.clone())).collect() | 1926 | substs |
1927 | .iter(&Interner) | ||
1928 | .map(|ty| self.derived(ty.assert_ty_ref(&Interner).clone())) | ||
1929 | .collect() | ||
1932 | } else { | 1930 | } else { |
1933 | Vec::new() | 1931 | Vec::new() |
1934 | } | 1932 | } |
@@ -1973,8 +1971,9 @@ impl Type { | |||
1973 | .strip_references() | 1971 | .strip_references() |
1974 | .substs() | 1972 | .substs() |
1975 | .into_iter() | 1973 | .into_iter() |
1976 | .flat_map(|substs| substs.iter()) | 1974 | .flat_map(|substs| substs.iter(&Interner)) |
1977 | .map(move |ty| self.derived(ty.clone())) | 1975 | .filter_map(|arg| arg.ty(&Interner).cloned()) |
1976 | .map(move |ty| self.derived(ty)) | ||
1978 | } | 1977 | } |
1979 | 1978 | ||
1980 | pub fn iterate_method_candidates<T>( | 1979 | pub fn iterate_method_candidates<T>( |
@@ -2080,7 +2079,7 @@ impl Type { | |||
2080 | substs: &Substitution, | 2079 | substs: &Substitution, |
2081 | cb: &mut impl FnMut(Type), | 2080 | cb: &mut impl FnMut(Type), |
2082 | ) { | 2081 | ) { |
2083 | for ty in substs.iter() { | 2082 | for ty in substs.iter(&Interner).filter_map(|a| a.ty(&Interner)) { |
2084 | walk_type(db, &type_.derived(ty.clone()), cb); | 2083 | walk_type(db, &type_.derived(ty.clone()), cb); |
2085 | } | 2084 | } |
2086 | } | 2085 | } |
@@ -2096,7 +2095,12 @@ impl Type { | |||
2096 | WhereClause::Implemented(trait_ref) => { | 2095 | WhereClause::Implemented(trait_ref) => { |
2097 | cb(type_.clone()); | 2096 | cb(type_.clone()); |
2098 | // skip the self type. it's likely the type we just got the bounds from | 2097 | // skip the self type. it's likely the type we just got the bounds from |
2099 | for ty in trait_ref.substitution.iter().skip(1) { | 2098 | for ty in trait_ref |
2099 | .substitution | ||
2100 | .iter(&Interner) | ||
2101 | .skip(1) | ||
2102 | .filter_map(|a| a.ty(&Interner)) | ||
2103 | { | ||
2100 | walk_type(db, &type_.derived(ty.clone()), cb); | 2104 | walk_type(db, &type_.derived(ty.clone()), cb); |
2101 | } | 2105 | } |
2102 | } | 2106 | } |
@@ -2107,7 +2111,7 @@ impl Type { | |||
2107 | 2111 | ||
2108 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { | 2112 | fn walk_type(db: &dyn HirDatabase, type_: &Type, cb: &mut impl FnMut(Type)) { |
2109 | let ty = type_.ty.strip_references(); | 2113 | let ty = type_.ty.strip_references(); |
2110 | match ty.interned(&Interner) { | 2114 | match ty.kind(&Interner) { |
2111 | TyKind::Adt(..) => { | 2115 | TyKind::Adt(..) => { |
2112 | cb(type_.derived(ty.clone())); | 2116 | cb(type_.derived(ty.clone())); |
2113 | } | 2117 | } |
diff --git a/crates/hir_def/Cargo.toml b/crates/hir_def/Cargo.toml index 475d337f3..60adb655c 100644 --- a/crates/hir_def/Cargo.toml +++ b/crates/hir_def/Cargo.toml | |||
@@ -10,7 +10,9 @@ edition = "2018" | |||
10 | doctest = false | 10 | doctest = false |
11 | 11 | ||
12 | [dependencies] | 12 | [dependencies] |
13 | bitflags = "1.2.1" | ||
13 | cov-mark = { version = "1.1", features = ["thread-local"] } | 14 | cov-mark = { version = "1.1", features = ["thread-local"] } |
15 | dashmap = { version = "4.0.2", features = ["raw-api"] } | ||
14 | log = "0.4.8" | 16 | log = "0.4.8" |
15 | once_cell = "1.3.1" | 17 | once_cell = "1.3.1" |
16 | rustc-hash = "1.1.0" | 18 | rustc-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}; | |||
15 | use crate::{ | 15 | use 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)] |
59 | pub struct FieldData { | 60 | pub struct FieldData { |
60 | pub name: Name, | 61 | pub name: Name, |
61 | pub type_ref: TypeRef, | 62 | pub type_ref: Interned<TypeRef>, |
62 | pub visibility: RawVisibility, | 63 | pub visibility: RawVisibility, |
63 | } | 64 | } |
64 | 65 | ||
@@ -292,7 +293,7 @@ fn lower_struct( | |||
292 | || Either::Left(fd.clone()), | 293 | || Either::Left(fd.clone()), |
293 | || FieldData { | 294 | || FieldData { |
294 | name: Name::new_tuple_field(i), | 295 | name: Name::new_tuple_field(i), |
295 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), | 296 | type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), |
296 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 297 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
297 | }, | 298 | }, |
298 | ); | 299 | ); |
@@ -309,7 +310,7 @@ fn lower_struct( | |||
309 | || Either::Right(fd.clone()), | 310 | || Either::Right(fd.clone()), |
310 | || FieldData { | 311 | || FieldData { |
311 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), | 312 | name: fd.name().map(|n| n.as_name()).unwrap_or_else(Name::missing), |
312 | type_ref: TypeRef::from_ast_opt(&ctx, fd.ty()), | 313 | type_ref: Interned::new(TypeRef::from_ast_opt(&ctx, fd.ty())), |
313 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), | 314 | visibility: RawVisibility::from_ast(db, ast.with_value(fd.visibility())), |
314 | }, | 315 | }, |
315 | ); | 316 | ); |
@@ -358,7 +359,7 @@ fn lower_field( | |||
358 | ) -> FieldData { | 359 | ) -> FieldData { |
359 | FieldData { | 360 | FieldData { |
360 | name: field.name.clone(), | 361 | name: field.name.clone(), |
361 | type_ref: item_tree[field.type_ref].clone(), | 362 | type_ref: field.type_ref.clone(), |
362 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), | 363 | visibility: item_tree[override_visibility.unwrap_or(field.visibility)].clone(), |
363 | } | 364 | } |
364 | } | 365 | } |
diff --git a/crates/hir_def/src/attr.rs b/crates/hir_def/src/attr.rs index 52a2bce9b..442c5fb5b 100644 --- a/crates/hir_def/src/attr.rs +++ b/crates/hir_def/src/attr.rs | |||
@@ -18,6 +18,7 @@ use tt::Subtree; | |||
18 | 18 | ||
19 | use crate::{ | 19 | use crate::{ |
20 | db::DefDatabase, | 20 | db::DefDatabase, |
21 | intern::Interned, | ||
21 | item_tree::{ItemTreeId, ItemTreeNode}, | 22 | item_tree::{ItemTreeId, ItemTreeNode}, |
22 | nameres::ModuleSource, | 23 | nameres::ModuleSource, |
23 | path::{ModPath, PathKind}, | 24 | path::{ModPath, PathKind}, |
@@ -98,7 +99,7 @@ impl RawAttrs { | |||
98 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { | 99 | Either::Right(comment) => comment.doc_comment().map(|doc| Attr { |
99 | index: i as u32, | 100 | index: i as u32, |
100 | input: Some(AttrInput::Literal(SmolStr::new(doc))), | 101 | input: Some(AttrInput::Literal(SmolStr::new(doc))), |
101 | path: ModPath::from(hir_expand::name!(doc)), | 102 | path: Interned::new(ModPath::from(hir_expand::name!(doc))), |
102 | }), | 103 | }), |
103 | }) | 104 | }) |
104 | .collect::<Arc<_>>(); | 105 | .collect::<Arc<_>>(); |
@@ -510,7 +511,7 @@ impl AttrSourceMap { | |||
510 | #[derive(Debug, Clone, PartialEq, Eq)] | 511 | #[derive(Debug, Clone, PartialEq, Eq)] |
511 | pub struct Attr { | 512 | pub struct Attr { |
512 | index: u32, | 513 | index: u32, |
513 | pub(crate) path: ModPath, | 514 | pub(crate) path: Interned<ModPath>, |
514 | pub(crate) input: Option<AttrInput>, | 515 | pub(crate) input: Option<AttrInput>, |
515 | } | 516 | } |
516 | 517 | ||
@@ -524,7 +525,7 @@ pub enum AttrInput { | |||
524 | 525 | ||
525 | impl Attr { | 526 | impl Attr { |
526 | fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { | 527 | fn from_src(ast: ast::Attr, hygiene: &Hygiene, index: u32) -> Option<Attr> { |
527 | let path = ModPath::from_src(ast.path()?, hygiene)?; | 528 | let path = Interned::new(ModPath::from_src(ast.path()?, hygiene)?); |
528 | let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { | 529 | let input = if let Some(ast::Expr::Literal(lit)) = ast.expr() { |
529 | let value = match lit.kind() { | 530 | let value = match lit.kind() { |
530 | ast::LiteralKind::String(string) => string.value()?.into(), | 531 | ast::LiteralKind::String(string) => string.value()?.into(), |
@@ -532,7 +533,7 @@ impl Attr { | |||
532 | }; | 533 | }; |
533 | Some(AttrInput::Literal(value)) | 534 | Some(AttrInput::Literal(value)) |
534 | } else if let Some(tt) = ast.token_tree() { | 535 | } else if let Some(tt) = ast.token_tree() { |
535 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt)?.0)) | 536 | Some(AttrInput::TokenTree(ast_to_token_tree(&tt).0)) |
536 | } else { | 537 | } else { |
537 | None | 538 | None |
538 | }; | 539 | }; |
diff --git a/crates/hir_def/src/body.rs b/crates/hir_def/src/body.rs index 1080d9c2c..96b959967 100644 --- a/crates/hir_def/src/body.rs +++ b/crates/hir_def/src/body.rs | |||
@@ -226,7 +226,7 @@ pub struct Body { | |||
226 | /// The `ExprId` of the actual body expression. | 226 | /// The `ExprId` of the actual body expression. |
227 | pub body_expr: ExprId, | 227 | pub body_expr: ExprId, |
228 | /// Block expressions in this body that may contain inner items. | 228 | /// Block expressions in this body that may contain inner items. |
229 | pub block_scopes: Vec<BlockId>, | 229 | block_scopes: Vec<BlockId>, |
230 | _c: Count<Self>, | 230 | _c: Count<Self>, |
231 | } | 231 | } |
232 | 232 | ||
@@ -302,7 +302,8 @@ impl Body { | |||
302 | } | 302 | } |
303 | }; | 303 | }; |
304 | let expander = Expander::new(db, file_id, module); | 304 | let expander = Expander::new(db, file_id, module); |
305 | let (body, source_map) = Body::new(db, expander, params, body); | 305 | let (mut body, source_map) = Body::new(db, expander, params, body); |
306 | body.shrink_to_fit(); | ||
306 | (Arc::new(body), Arc::new(source_map)) | 307 | (Arc::new(body), Arc::new(source_map)) |
307 | } | 308 | } |
308 | 309 | ||
@@ -310,6 +311,16 @@ impl Body { | |||
310 | db.body_with_source_map(def).0 | 311 | db.body_with_source_map(def).0 |
311 | } | 312 | } |
312 | 313 | ||
314 | /// Returns an iterator over all block expressions in this body that define inner items. | ||
315 | pub fn blocks<'a>( | ||
316 | &'a self, | ||
317 | db: &'a dyn DefDatabase, | ||
318 | ) -> impl Iterator<Item = (BlockId, Arc<DefMap>)> + '_ { | ||
319 | self.block_scopes | ||
320 | .iter() | ||
321 | .map(move |block| (*block, db.block_def_map(*block).expect("block ID without DefMap"))) | ||
322 | } | ||
323 | |||
313 | fn new( | 324 | fn new( |
314 | db: &dyn DefDatabase, | 325 | db: &dyn DefDatabase, |
315 | expander: Expander, | 326 | expander: Expander, |
@@ -318,6 +329,15 @@ impl Body { | |||
318 | ) -> (Body, BodySourceMap) { | 329 | ) -> (Body, BodySourceMap) { |
319 | lower::lower(db, expander, params, body) | 330 | lower::lower(db, expander, params, body) |
320 | } | 331 | } |
332 | |||
333 | fn shrink_to_fit(&mut self) { | ||
334 | let Self { _c: _, body_expr: _, block_scopes, exprs, labels, params, pats } = self; | ||
335 | block_scopes.shrink_to_fit(); | ||
336 | exprs.shrink_to_fit(); | ||
337 | labels.shrink_to_fit(); | ||
338 | params.shrink_to_fit(); | ||
339 | pats.shrink_to_fit(); | ||
340 | } | ||
321 | } | 341 | } |
322 | 342 | ||
323 | impl Index<ExprId> for Body { | 343 | impl Index<ExprId> for Body { |
diff --git a/crates/hir_def/src/body/lower.rs b/crates/hir_def/src/body/lower.rs index 229e81dd4..63e89a1f4 100644 --- a/crates/hir_def/src/body/lower.rs +++ b/crates/hir_def/src/body/lower.rs | |||
@@ -673,12 +673,14 @@ impl ExprCollector<'_> { | |||
673 | let block_loc = | 673 | let block_loc = |
674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; | 674 | BlockLoc { ast_id, module: self.expander.def_map.module_id(self.expander.module) }; |
675 | let block_id = self.db.intern_block(block_loc); | 675 | let block_id = self.db.intern_block(block_loc); |
676 | self.body.block_scopes.push(block_id); | ||
677 | 676 | ||
678 | let opt_def_map = self.db.block_def_map(block_id); | 677 | let (module, def_map) = match self.db.block_def_map(block_id) { |
679 | let has_def_map = opt_def_map.is_some(); | 678 | Some(def_map) => { |
680 | let def_map = opt_def_map.unwrap_or_else(|| self.expander.def_map.clone()); | 679 | self.body.block_scopes.push(block_id); |
681 | let module = if has_def_map { def_map.root() } else { self.expander.module }; | 680 | (def_map.root(), def_map) |
681 | } | ||
682 | None => (self.expander.module, self.expander.def_map.clone()), | ||
683 | }; | ||
682 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); | 684 | let prev_def_map = mem::replace(&mut self.expander.def_map, def_map); |
683 | let prev_local_module = mem::replace(&mut self.expander.module, module); | 685 | let prev_local_module = mem::replace(&mut self.expander.module, module); |
684 | let prev_statements = std::mem::take(&mut self.statements_in_scope); | 686 | let prev_statements = std::mem::take(&mut self.statements_in_scope); |
diff --git a/crates/hir_def/src/child_by_source.rs b/crates/hir_def/src/child_by_source.rs index 2a331dcaf..f40a7f80d 100644 --- a/crates/hir_def/src/child_by_source.rs +++ b/crates/hir_def/src/child_by_source.rs | |||
@@ -160,7 +160,7 @@ impl ChildBySource for EnumId { | |||
160 | impl ChildBySource for DefWithBodyId { | 160 | impl ChildBySource for DefWithBodyId { |
161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { | 161 | fn child_by_source_to(&self, db: &dyn DefDatabase, res: &mut DynMap) { |
162 | let body = db.body(*self); | 162 | let body = db.body(*self); |
163 | for def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | 163 | for (_, def_map) in body.blocks(db) { |
164 | // All block expressions are merged into the same map, because they logically all add | 164 | // All block expressions are merged into the same map, because they logically all add |
165 | // inner items to the containing `DefWithBodyId`. | 165 | // inner items to the containing `DefWithBodyId`. |
166 | def_map[def_map.root()].scope.child_by_source_to(db, res); | 166 | def_map[def_map.root()].scope.child_by_source_to(db, res); |
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 214bcc648..b409fb45c 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -9,7 +9,8 @@ use crate::{ | |||
9 | attr::Attrs, | 9 | attr::Attrs, |
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 12 | intern::Interned, |
13 | item_tree::{AssocItem, FnFlags, ItemTreeId, ModItem, Param}, | ||
13 | type_ref::{TraitRef, TypeBound, TypeRef}, | 14 | type_ref::{TraitRef, TypeBound, TypeRef}, |
14 | visibility::RawVisibility, | 15 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 16 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
@@ -19,17 +20,12 @@ use crate::{ | |||
19 | #[derive(Debug, Clone, PartialEq, Eq)] | 20 | #[derive(Debug, Clone, PartialEq, Eq)] |
20 | pub struct FunctionData { | 21 | pub 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 | ||
35 | impl FunctionData { | 31 | impl FunctionData { |
@@ -52,31 +48,67 @@ impl FunctionData { | |||
52 | .next_back() | 48 | .next_back() |
53 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); | 49 | .map_or(false, |param| matches!(item_tree[param], Param::Varargs)); |
54 | 50 | ||
51 | let mut flags = func.flags; | ||
52 | if is_varargs { | ||
53 | flags |= FnFlags::IS_VARARGS; | ||
54 | } | ||
55 | |||
55 | Arc::new(FunctionData { | 56 | Arc::new(FunctionData { |
56 | name: func.name.clone(), | 57 | name: func.name.clone(), |
57 | params: enabled_params | 58 | params: enabled_params |
58 | .clone() | 59 | .clone() |
59 | .filter_map(|id| match &item_tree[id] { | 60 | .filter_map(|id| match &item_tree[id] { |
60 | Param::Normal(ty) => Some(item_tree[*ty].clone()), | 61 | Param::Normal(ty) => Some(ty.clone()), |
61 | Param::Varargs => None, | 62 | Param::Varargs => None, |
62 | }) | 63 | }) |
63 | .collect(), | 64 | .collect(), |
64 | ret_type: item_tree[func.ret_type].clone(), | 65 | ret_type: func.ret_type.clone(), |
65 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), | 66 | attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), |
66 | has_self_param: func.has_self_param, | ||
67 | has_body: func.has_body, | ||
68 | qualifier: func.qualifier.clone(), | ||
69 | is_in_extern_block: func.is_in_extern_block, | ||
70 | is_varargs, | ||
71 | visibility: item_tree[func.visibility].clone(), | 67 | visibility: item_tree[func.visibility].clone(), |
68 | abi: func.abi.clone(), | ||
69 | flags, | ||
72 | }) | 70 | }) |
73 | } | 71 | } |
72 | |||
73 | pub fn has_body(&self) -> bool { | ||
74 | self.flags.contains(FnFlags::HAS_BODY) | ||
75 | } | ||
76 | |||
77 | /// True if the first param is `self`. This is relevant to decide whether this | ||
78 | /// can be called as a method. | ||
79 | pub fn has_self_param(&self) -> bool { | ||
80 | self.flags.contains(FnFlags::HAS_SELF_PARAM) | ||
81 | } | ||
82 | |||
83 | pub fn is_default(&self) -> bool { | ||
84 | self.flags.contains(FnFlags::IS_DEFAULT) | ||
85 | } | ||
86 | |||
87 | pub fn is_const(&self) -> bool { | ||
88 | self.flags.contains(FnFlags::IS_CONST) | ||
89 | } | ||
90 | |||
91 | pub fn is_async(&self) -> bool { | ||
92 | self.flags.contains(FnFlags::IS_ASYNC) | ||
93 | } | ||
94 | |||
95 | pub fn is_unsafe(&self) -> bool { | ||
96 | self.flags.contains(FnFlags::IS_UNSAFE) | ||
97 | } | ||
98 | |||
99 | pub fn is_in_extern_block(&self) -> bool { | ||
100 | self.flags.contains(FnFlags::IS_IN_EXTERN_BLOCK) | ||
101 | } | ||
102 | |||
103 | pub fn is_varargs(&self) -> bool { | ||
104 | self.flags.contains(FnFlags::IS_VARARGS) | ||
105 | } | ||
74 | } | 106 | } |
75 | 107 | ||
76 | #[derive(Debug, Clone, PartialEq, Eq)] | 108 | #[derive(Debug, Clone, PartialEq, Eq)] |
77 | pub struct TypeAliasData { | 109 | pub 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)] |
158 | pub struct ImplData { | 190 | pub struct ImplData { |
159 | pub target_trait: Option<TraitRef>, | 191 | pub target_trait: Option<Interned<TraitRef>>, |
160 | pub self_ty: TypeRef, | 192 | pub self_ty: Interned<TypeRef>, |
161 | pub items: Vec<AssocItemId>, | 193 | pub items: Vec<AssocItemId>, |
162 | pub is_negative: bool, | 194 | pub is_negative: bool, |
163 | } | 195 | } |
@@ -169,8 +201,8 @@ impl ImplData { | |||
169 | 201 | ||
170 | let item_tree = impl_loc.id.item_tree(db); | 202 | let item_tree = impl_loc.id.item_tree(db); |
171 | let impl_def = &item_tree[impl_loc.id.value]; | 203 | let impl_def = &item_tree[impl_loc.id.value]; |
172 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); | 204 | let target_trait = impl_def.target_trait.clone(); |
173 | let self_ty = item_tree[impl_def.self_ty].clone(); | 205 | let self_ty = impl_def.self_ty.clone(); |
174 | let is_negative = impl_def.is_negative; | 206 | let is_negative = impl_def.is_negative; |
175 | let module_id = impl_loc.container; | 207 | let module_id = impl_loc.container; |
176 | let container = AssocContainerId::ImplId(id); | 208 | let container = AssocContainerId::ImplId(id); |
@@ -195,7 +227,7 @@ impl ImplData { | |||
195 | pub struct ConstData { | 227 | pub 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)] |
217 | pub struct StaticData { | 249 | pub struct StaticData { |
218 | pub name: Option<Name>, | 250 | pub name: Option<Name>, |
219 | pub type_ref: TypeRef, | 251 | pub type_ref: Interned<TypeRef>, |
220 | pub visibility: RawVisibility, | 252 | pub visibility: RawVisibility, |
221 | pub mutable: bool, | 253 | pub mutable: bool, |
222 | pub is_extern: bool, | 254 | pub is_extern: bool, |
@@ -230,7 +262,7 @@ impl StaticData { | |||
230 | 262 | ||
231 | Arc::new(StaticData { | 263 | Arc::new(StaticData { |
232 | name: Some(statik.name.clone()), | 264 | name: Some(statik.name.clone()), |
233 | type_ref: item_tree[statik.type_ref].clone(), | 265 | type_ref: statik.type_ref.clone(), |
234 | visibility: item_tree[statik.visibility].clone(), | 266 | visibility: item_tree[statik.visibility].clone(), |
235 | mutable: statik.mutable, | 267 | mutable: statik.mutable, |
236 | is_extern: statik.is_extern, | 268 | is_extern: statik.is_extern, |
diff --git a/crates/hir_def/src/intern.rs b/crates/hir_def/src/intern.rs new file mode 100644 index 000000000..d163f633f --- /dev/null +++ b/crates/hir_def/src/intern.rs | |||
@@ -0,0 +1,197 @@ | |||
1 | //! Global `Arc`-based object interning infrastructure. | ||
2 | //! | ||
3 | //! Eventually this should probably be replaced with salsa-based interning. | ||
4 | |||
5 | use std::{ | ||
6 | collections::HashMap, | ||
7 | fmt::{self, Debug}, | ||
8 | hash::{BuildHasherDefault, Hash}, | ||
9 | ops::Deref, | ||
10 | sync::Arc, | ||
11 | }; | ||
12 | |||
13 | use dashmap::{lock::RwLockWriteGuard, DashMap, SharedValue}; | ||
14 | use once_cell::sync::OnceCell; | ||
15 | use rustc_hash::FxHasher; | ||
16 | |||
17 | type InternMap<T> = DashMap<Arc<T>, (), BuildHasherDefault<FxHasher>>; | ||
18 | type Guard<T> = | ||
19 | RwLockWriteGuard<'static, HashMap<Arc<T>, SharedValue<()>, BuildHasherDefault<FxHasher>>>; | ||
20 | |||
21 | #[derive(Hash)] | ||
22 | pub struct Interned<T: Internable + ?Sized> { | ||
23 | arc: Arc<T>, | ||
24 | } | ||
25 | |||
26 | impl<T: Internable> Interned<T> { | ||
27 | pub fn new(obj: T) -> Self { | ||
28 | match Interned::lookup(&obj) { | ||
29 | Ok(this) => this, | ||
30 | Err(shard) => { | ||
31 | let arc = Arc::new(obj); | ||
32 | Self::alloc(arc, shard) | ||
33 | } | ||
34 | } | ||
35 | } | ||
36 | } | ||
37 | |||
38 | impl<T: Internable + ?Sized> Interned<T> { | ||
39 | fn lookup(obj: &T) -> Result<Self, Guard<T>> { | ||
40 | let storage = T::storage().get(); | ||
41 | let shard_idx = storage.determine_map(obj); | ||
42 | let shard = &storage.shards()[shard_idx]; | ||
43 | let shard = shard.write(); | ||
44 | |||
45 | // Atomically, | ||
46 | // - check if `obj` is already in the map | ||
47 | // - if so, clone its `Arc` and return it | ||
48 | // - if not, box it up, insert it, and return a clone | ||
49 | // This needs to be atomic (locking the shard) to avoid races with other thread, which could | ||
50 | // insert the same object between us looking it up and inserting it. | ||
51 | |||
52 | // FIXME: avoid double lookup/hashing by using raw entry API (once stable, or when | ||
53 | // hashbrown can be plugged into dashmap) | ||
54 | match shard.get_key_value(obj) { | ||
55 | Some((arc, _)) => Ok(Self { arc: arc.clone() }), | ||
56 | None => Err(shard), | ||
57 | } | ||
58 | } | ||
59 | |||
60 | fn alloc(arc: Arc<T>, mut shard: Guard<T>) -> Self { | ||
61 | let arc2 = arc.clone(); | ||
62 | |||
63 | shard.insert(arc2, SharedValue::new(())); | ||
64 | |||
65 | Self { arc } | ||
66 | } | ||
67 | } | ||
68 | |||
69 | impl Interned<str> { | ||
70 | pub fn new_str(s: &str) -> Self { | ||
71 | match Interned::lookup(s) { | ||
72 | Ok(this) => this, | ||
73 | Err(shard) => { | ||
74 | let arc = Arc::<str>::from(s); | ||
75 | Self::alloc(arc, shard) | ||
76 | } | ||
77 | } | ||
78 | } | ||
79 | } | ||
80 | |||
81 | impl<T: Internable + ?Sized> Drop for Interned<T> { | ||
82 | #[inline] | ||
83 | fn drop(&mut self) { | ||
84 | // When the last `Ref` is dropped, remove the object from the global map. | ||
85 | if Arc::strong_count(&self.arc) == 2 { | ||
86 | // Only `self` and the global map point to the object. | ||
87 | |||
88 | self.drop_slow(); | ||
89 | } | ||
90 | } | ||
91 | } | ||
92 | |||
93 | impl<T: Internable + ?Sized> Interned<T> { | ||
94 | #[cold] | ||
95 | fn drop_slow(&mut self) { | ||
96 | let storage = T::storage().get(); | ||
97 | let shard_idx = storage.determine_map(&self.arc); | ||
98 | let shard = &storage.shards()[shard_idx]; | ||
99 | let mut shard = shard.write(); | ||
100 | |||
101 | // FIXME: avoid double lookup | ||
102 | let (arc, _) = shard.get_key_value(&self.arc).expect("interned value removed prematurely"); | ||
103 | |||
104 | if Arc::strong_count(arc) != 2 { | ||
105 | // Another thread has interned another copy | ||
106 | return; | ||
107 | } | ||
108 | |||
109 | shard.remove(&self.arc); | ||
110 | |||
111 | // Shrink the backing storage if the shard is less than 50% occupied. | ||
112 | if shard.len() * 2 < shard.capacity() { | ||
113 | shard.shrink_to_fit(); | ||
114 | } | ||
115 | } | ||
116 | } | ||
117 | |||
118 | /// Compares interned `Ref`s using pointer equality. | ||
119 | impl<T: Internable> PartialEq for Interned<T> { | ||
120 | // NOTE: No `?Sized` because `ptr_eq` doesn't work right with trait objects. | ||
121 | |||
122 | #[inline] | ||
123 | fn eq(&self, other: &Self) -> bool { | ||
124 | Arc::ptr_eq(&self.arc, &other.arc) | ||
125 | } | ||
126 | } | ||
127 | |||
128 | impl<T: Internable> Eq for Interned<T> {} | ||
129 | |||
130 | impl PartialEq for Interned<str> { | ||
131 | fn eq(&self, other: &Self) -> bool { | ||
132 | Arc::ptr_eq(&self.arc, &other.arc) | ||
133 | } | ||
134 | } | ||
135 | |||
136 | impl Eq for Interned<str> {} | ||
137 | |||
138 | impl<T: Internable + ?Sized> AsRef<T> for Interned<T> { | ||
139 | #[inline] | ||
140 | fn as_ref(&self) -> &T { | ||
141 | &self.arc | ||
142 | } | ||
143 | } | ||
144 | |||
145 | impl<T: Internable + ?Sized> Deref for Interned<T> { | ||
146 | type Target = T; | ||
147 | |||
148 | #[inline] | ||
149 | fn deref(&self) -> &Self::Target { | ||
150 | &self.arc | ||
151 | } | ||
152 | } | ||
153 | |||
154 | impl<T: Internable + ?Sized> Clone for Interned<T> { | ||
155 | fn clone(&self) -> Self { | ||
156 | Self { arc: self.arc.clone() } | ||
157 | } | ||
158 | } | ||
159 | |||
160 | impl<T: Debug + Internable + ?Sized> Debug for Interned<T> { | ||
161 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { | ||
162 | (*self.arc).fmt(f) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | pub struct InternStorage<T: ?Sized> { | ||
167 | map: OnceCell<InternMap<T>>, | ||
168 | } | ||
169 | |||
170 | impl<T: ?Sized> InternStorage<T> { | ||
171 | pub const fn new() -> Self { | ||
172 | Self { map: OnceCell::new() } | ||
173 | } | ||
174 | } | ||
175 | |||
176 | impl<T: Internable + ?Sized> InternStorage<T> { | ||
177 | fn get(&self) -> &InternMap<T> { | ||
178 | self.map.get_or_init(DashMap::default) | ||
179 | } | ||
180 | } | ||
181 | |||
182 | pub trait Internable: Hash + Eq + 'static { | ||
183 | fn storage() -> &'static InternStorage<Self>; | ||
184 | } | ||
185 | |||
186 | macro_rules! impl_internable { | ||
187 | ( $($t:path),+ $(,)? ) => { $( | ||
188 | impl Internable for $t { | ||
189 | fn storage() -> &'static InternStorage<Self> { | ||
190 | static STORAGE: InternStorage<$t> = InternStorage::new(); | ||
191 | &STORAGE | ||
192 | } | ||
193 | } | ||
194 | )+ }; | ||
195 | } | ||
196 | |||
197 | impl_internable!(crate::type_ref::TypeRef, crate::type_ref::TraitRef, crate::path::ModPath, str); | ||
diff --git a/crates/hir_def/src/item_scope.rs b/crates/hir_def/src/item_scope.rs index f3ebe7c72..a8ee5eeac 100644 --- a/crates/hir_def/src/item_scope.rs +++ b/crates/hir_def/src/item_scope.rs | |||
@@ -285,6 +285,28 @@ impl ItemScope { | |||
285 | buf.push('\n'); | 285 | buf.push('\n'); |
286 | } | 286 | } |
287 | } | 287 | } |
288 | |||
289 | pub(crate) fn shrink_to_fit(&mut self) { | ||
290 | // Exhaustive match to require handling new fields. | ||
291 | let Self { | ||
292 | types, | ||
293 | values, | ||
294 | macros, | ||
295 | unresolved, | ||
296 | defs, | ||
297 | impls, | ||
298 | unnamed_trait_imports, | ||
299 | legacy_macros, | ||
300 | } = self; | ||
301 | types.shrink_to_fit(); | ||
302 | values.shrink_to_fit(); | ||
303 | macros.shrink_to_fit(); | ||
304 | unresolved.shrink_to_fit(); | ||
305 | defs.shrink_to_fit(); | ||
306 | impls.shrink_to_fit(); | ||
307 | unnamed_trait_imports.shrink_to_fit(); | ||
308 | legacy_macros.shrink_to_fit(); | ||
309 | } | ||
288 | } | 310 | } |
289 | 311 | ||
290 | impl PerNs { | 312 | impl PerNs { |
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 5449bbf5d..c6d700977 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -24,12 +24,13 @@ use la_arena::{Arena, Idx, RawIdx}; | |||
24 | use profile::Count; | 24 | use profile::Count; |
25 | use rustc_hash::FxHashMap; | 25 | use rustc_hash::FxHashMap; |
26 | use smallvec::SmallVec; | 26 | use smallvec::SmallVec; |
27 | use syntax::{ast, match_ast, SmolStr, SyntaxKind}; | 27 | use syntax::{ast, match_ast, SyntaxKind}; |
28 | 28 | ||
29 | use crate::{ | 29 | use crate::{ |
30 | attr::{Attrs, RawAttrs}, | 30 | attr::{Attrs, RawAttrs}, |
31 | db::DefDatabase, | 31 | db::DefDatabase, |
32 | generics::GenericParams, | 32 | generics::GenericParams, |
33 | intern::Interned, | ||
33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, | 34 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, |
34 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, | 35 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, |
35 | visibility::RawVisibility, | 36 | visibility::RawVisibility, |
@@ -146,8 +147,6 @@ impl ItemTree { | |||
146 | macro_defs, | 147 | macro_defs, |
147 | vis, | 148 | vis, |
148 | generics, | 149 | generics, |
149 | type_refs, | ||
150 | trait_refs, | ||
151 | inner_items, | 150 | inner_items, |
152 | } = &mut **data; | 151 | } = &mut **data; |
153 | 152 | ||
@@ -172,9 +171,6 @@ impl ItemTree { | |||
172 | 171 | ||
173 | vis.arena.shrink_to_fit(); | 172 | vis.arena.shrink_to_fit(); |
174 | generics.arena.shrink_to_fit(); | 173 | generics.arena.shrink_to_fit(); |
175 | type_refs.arena.shrink_to_fit(); | ||
176 | type_refs.map.shrink_to_fit(); | ||
177 | trait_refs.map.shrink_to_fit(); | ||
178 | 174 | ||
179 | inner_items.shrink_to_fit(); | 175 | inner_items.shrink_to_fit(); |
180 | } | 176 | } |
@@ -271,58 +267,6 @@ static EMPTY_GENERICS: GenericParams = GenericParams { | |||
271 | where_predicates: Vec::new(), | 267 | where_predicates: Vec::new(), |
272 | }; | 268 | }; |
273 | 269 | ||
274 | /// `TypeRef` interner. | ||
275 | #[derive(Default, Debug, Eq, PartialEq)] | ||
276 | struct TypeRefStorage { | ||
277 | arena: Arena<Arc<TypeRef>>, | ||
278 | map: FxHashMap<Arc<TypeRef>, Idx<Arc<TypeRef>>>, | ||
279 | } | ||
280 | |||
281 | impl TypeRefStorage { | ||
282 | // Note: We lie about the `Idx<TypeRef>` to hide the interner details. | ||
283 | |||
284 | fn intern(&mut self, ty: TypeRef) -> Idx<TypeRef> { | ||
285 | if let Some(id) = self.map.get(&ty) { | ||
286 | return Idx::from_raw(id.into_raw()); | ||
287 | } | ||
288 | |||
289 | let ty = Arc::new(ty); | ||
290 | let idx = self.arena.alloc(ty.clone()); | ||
291 | self.map.insert(ty, idx); | ||
292 | Idx::from_raw(idx.into_raw()) | ||
293 | } | ||
294 | |||
295 | fn lookup(&self, id: Idx<TypeRef>) -> &TypeRef { | ||
296 | &self.arena[Idx::from_raw(id.into_raw())] | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /// `TraitRef` interner. | ||
301 | #[derive(Default, Debug, Eq, PartialEq)] | ||
302 | struct TraitRefStorage { | ||
303 | arena: Arena<Arc<TraitRef>>, | ||
304 | map: FxHashMap<Arc<TraitRef>, Idx<Arc<TraitRef>>>, | ||
305 | } | ||
306 | |||
307 | impl TraitRefStorage { | ||
308 | // Note: We lie about the `Idx<TraitRef>` to hide the interner details. | ||
309 | |||
310 | fn intern(&mut self, ty: TraitRef) -> Idx<TraitRef> { | ||
311 | if let Some(id) = self.map.get(&ty) { | ||
312 | return Idx::from_raw(id.into_raw()); | ||
313 | } | ||
314 | |||
315 | let ty = Arc::new(ty); | ||
316 | let idx = self.arena.alloc(ty.clone()); | ||
317 | self.map.insert(ty, idx); | ||
318 | Idx::from_raw(idx.into_raw()) | ||
319 | } | ||
320 | |||
321 | fn lookup(&self, id: Idx<TraitRef>) -> &TraitRef { | ||
322 | &self.arena[Idx::from_raw(id.into_raw())] | ||
323 | } | ||
324 | } | ||
325 | |||
326 | #[derive(Default, Debug, Eq, PartialEq)] | 270 | #[derive(Default, Debug, Eq, PartialEq)] |
327 | struct ItemTreeData { | 271 | struct ItemTreeData { |
328 | imports: Arena<Import>, | 272 | imports: Arena<Import>, |
@@ -346,8 +290,6 @@ struct ItemTreeData { | |||
346 | 290 | ||
347 | vis: ItemVisibilities, | 291 | vis: ItemVisibilities, |
348 | generics: GenericParamsStorage, | 292 | generics: GenericParamsStorage, |
349 | type_refs: TypeRefStorage, | ||
350 | trait_refs: TraitRefStorage, | ||
351 | 293 | ||
352 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 294 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
353 | } | 295 | } |
@@ -577,22 +519,6 @@ impl Index<GenericParamsId> for ItemTree { | |||
577 | } | 519 | } |
578 | } | 520 | } |
579 | 521 | ||
580 | impl Index<Idx<TypeRef>> for ItemTree { | ||
581 | type Output = TypeRef; | ||
582 | |||
583 | fn index(&self, id: Idx<TypeRef>) -> &Self::Output { | ||
584 | self.data().type_refs.lookup(id) | ||
585 | } | ||
586 | } | ||
587 | |||
588 | impl Index<Idx<TraitRef>> for ItemTree { | ||
589 | type Output = TraitRef; | ||
590 | |||
591 | fn index(&self, id: Idx<TraitRef>) -> &Self::Output { | ||
592 | self.data().trait_refs.lookup(id) | ||
593 | } | ||
594 | } | ||
595 | |||
596 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 522 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
597 | type Output = N; | 523 | type Output = N; |
598 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 524 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -603,7 +529,7 @@ impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | |||
603 | /// A desugared `use` import. | 529 | /// A desugared `use` import. |
604 | #[derive(Debug, Clone, Eq, PartialEq)] | 530 | #[derive(Debug, Clone, Eq, PartialEq)] |
605 | pub struct Import { | 531 | pub struct Import { |
606 | pub path: ModPath, | 532 | pub path: Interned<ModPath>, |
607 | pub alias: Option<ImportAlias>, | 533 | pub alias: Option<ImportAlias>, |
608 | pub visibility: RawVisibilityId, | 534 | pub visibility: RawVisibilityId, |
609 | pub is_glob: bool, | 535 | pub is_glob: bool, |
@@ -630,30 +556,33 @@ pub struct Function { | |||
630 | pub name: Name, | 556 | pub name: Name, |
631 | pub visibility: RawVisibilityId, | 557 | pub visibility: RawVisibilityId, |
632 | pub generic_params: GenericParamsId, | 558 | pub generic_params: GenericParamsId, |
633 | pub has_self_param: bool, | 559 | pub abi: Option<Interned<str>>, |
634 | pub has_body: bool, | ||
635 | pub qualifier: FunctionQualifier, | ||
636 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
637 | /// `extern "abi" fn`). | ||
638 | pub is_in_extern_block: bool, | ||
639 | pub params: IdRange<Param>, | 560 | pub params: IdRange<Param>, |
640 | pub ret_type: Idx<TypeRef>, | 561 | pub ret_type: Interned<TypeRef>, |
641 | pub ast_id: FileAstId<ast::Fn>, | 562 | pub ast_id: FileAstId<ast::Fn>, |
563 | pub(crate) flags: FnFlags, | ||
642 | } | 564 | } |
643 | 565 | ||
644 | #[derive(Debug, Clone, Eq, PartialEq)] | 566 | #[derive(Debug, Clone, Eq, PartialEq)] |
645 | pub enum Param { | 567 | pub enum Param { |
646 | Normal(Idx<TypeRef>), | 568 | Normal(Interned<TypeRef>), |
647 | Varargs, | 569 | Varargs, |
648 | } | 570 | } |
649 | 571 | ||
650 | #[derive(Debug, Clone, PartialEq, Eq)] | 572 | bitflags::bitflags! { |
651 | pub struct FunctionQualifier { | 573 | /// NOTE: Shared with `FunctionData` |
652 | pub is_default: bool, | 574 | pub(crate) struct FnFlags: u8 { |
653 | pub is_const: bool, | 575 | const HAS_SELF_PARAM = 1 << 0; |
654 | pub is_async: bool, | 576 | const HAS_BODY = 1 << 1; |
655 | pub is_unsafe: bool, | 577 | const IS_DEFAULT = 1 << 2; |
656 | pub abi: Option<SmolStr>, | 578 | const IS_CONST = 1 << 3; |
579 | const IS_ASYNC = 1 << 4; | ||
580 | const IS_UNSAFE = 1 << 5; | ||
581 | /// Whether the function is located in an `extern` block (*not* whether it is an | ||
582 | /// `extern "abi" fn`). | ||
583 | const IS_IN_EXTERN_BLOCK = 1 << 6; | ||
584 | const IS_VARARGS = 1 << 7; | ||
585 | } | ||
657 | } | 586 | } |
658 | 587 | ||
659 | #[derive(Debug, Clone, Eq, PartialEq)] | 588 | #[derive(Debug, Clone, Eq, PartialEq)] |
@@ -699,7 +628,7 @@ pub struct Const { | |||
699 | /// const _: () = (); | 628 | /// const _: () = (); |
700 | pub name: Option<Name>, | 629 | pub name: Option<Name>, |
701 | pub visibility: RawVisibilityId, | 630 | pub visibility: RawVisibilityId, |
702 | pub type_ref: Idx<TypeRef>, | 631 | pub type_ref: Interned<TypeRef>, |
703 | pub ast_id: FileAstId<ast::Const>, | 632 | pub ast_id: FileAstId<ast::Const>, |
704 | } | 633 | } |
705 | 634 | ||
@@ -710,7 +639,7 @@ pub struct Static { | |||
710 | pub mutable: bool, | 639 | pub mutable: bool, |
711 | /// Whether the static is in an `extern` block. | 640 | /// Whether the static is in an `extern` block. |
712 | pub is_extern: bool, | 641 | pub is_extern: bool, |
713 | pub type_ref: Idx<TypeRef>, | 642 | pub type_ref: Interned<TypeRef>, |
714 | pub ast_id: FileAstId<ast::Static>, | 643 | pub ast_id: FileAstId<ast::Static>, |
715 | } | 644 | } |
716 | 645 | ||
@@ -729,8 +658,8 @@ pub struct Trait { | |||
729 | #[derive(Debug, Clone, Eq, PartialEq)] | 658 | #[derive(Debug, Clone, Eq, PartialEq)] |
730 | pub struct Impl { | 659 | pub struct Impl { |
731 | pub generic_params: GenericParamsId, | 660 | pub generic_params: GenericParamsId, |
732 | pub target_trait: Option<Idx<TraitRef>>, | 661 | pub target_trait: Option<Interned<TraitRef>>, |
733 | pub self_ty: Idx<TypeRef>, | 662 | pub self_ty: Interned<TypeRef>, |
734 | pub is_negative: bool, | 663 | pub is_negative: bool, |
735 | pub items: Box<[AssocItem]>, | 664 | pub items: Box<[AssocItem]>, |
736 | pub ast_id: FileAstId<ast::Impl>, | 665 | pub ast_id: FileAstId<ast::Impl>, |
@@ -743,7 +672,7 @@ pub struct TypeAlias { | |||
743 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. | 672 | /// Bounds on the type alias itself. Only valid in trait declarations, eg. `type Assoc: Copy;`. |
744 | pub bounds: Box<[TypeBound]>, | 673 | pub bounds: Box<[TypeBound]>, |
745 | pub generic_params: GenericParamsId, | 674 | pub generic_params: GenericParamsId, |
746 | pub type_ref: Option<Idx<TypeRef>>, | 675 | pub type_ref: Option<Interned<TypeRef>>, |
747 | pub is_extern: bool, | 676 | pub is_extern: bool, |
748 | pub ast_id: FileAstId<ast::TypeAlias>, | 677 | pub ast_id: FileAstId<ast::TypeAlias>, |
749 | } | 678 | } |
@@ -768,7 +697,7 @@ pub enum ModKind { | |||
768 | #[derive(Debug, Clone, Eq, PartialEq)] | 697 | #[derive(Debug, Clone, Eq, PartialEq)] |
769 | pub struct MacroCall { | 698 | pub struct MacroCall { |
770 | /// Path to the called macro. | 699 | /// Path to the called macro. |
771 | pub path: ModPath, | 700 | pub path: Interned<ModPath>, |
772 | pub ast_id: FileAstId<ast::MacroCall>, | 701 | pub ast_id: FileAstId<ast::MacroCall>, |
773 | } | 702 | } |
774 | 703 | ||
@@ -933,6 +862,6 @@ pub enum Fields { | |||
933 | #[derive(Debug, Clone, PartialEq, Eq)] | 862 | #[derive(Debug, Clone, PartialEq, Eq)] |
934 | pub struct Field { | 863 | pub struct Field { |
935 | pub name: Name, | 864 | pub name: Name, |
936 | pub type_ref: Idx<TypeRef>, | 865 | pub type_ref: Interned<TypeRef>, |
937 | pub visibility: RawVisibilityId, | 866 | pub visibility: RawVisibilityId, |
938 | } | 867 | } |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 124dcc866..39e8403b0 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -362,7 +362,7 @@ impl Ctx { | |||
362 | } | 362 | } |
363 | } | 363 | } |
364 | }; | 364 | }; |
365 | let ty = self.data().type_refs.intern(self_type); | 365 | let ty = Interned::new(self_type); |
366 | let idx = self.data().params.alloc(Param::Normal(ty)); | 366 | let idx = self.data().params.alloc(Param::Normal(ty)); |
367 | self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); | 367 | self.add_attrs(idx.into(), RawAttrs::new(&self_param, &self.hygiene)); |
368 | has_self_param = true; | 368 | has_self_param = true; |
@@ -372,7 +372,7 @@ impl Ctx { | |||
372 | Some(_) => self.data().params.alloc(Param::Varargs), | 372 | Some(_) => self.data().params.alloc(Param::Varargs), |
373 | None => { | 373 | None => { |
374 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); | 374 | let type_ref = TypeRef::from_ast_opt(&self.body_ctx, param.ty()); |
375 | let ty = self.data().type_refs.intern(type_ref); | 375 | let ty = Interned::new(type_ref); |
376 | self.data().params.alloc(Param::Normal(ty)) | 376 | self.data().params.alloc(Param::Normal(ty)) |
377 | } | 377 | } |
378 | }; | 378 | }; |
@@ -395,41 +395,51 @@ impl Ctx { | |||
395 | ret_type | 395 | ret_type |
396 | }; | 396 | }; |
397 | 397 | ||
398 | let ret_type = self.data().type_refs.intern(ret_type); | 398 | let abi = func.abi().map(|abi| { |
399 | 399 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | |
400 | let has_body = func.body().is_some(); | 400 | match abi.syntax().last_token() { |
401 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | ||
402 | // FIXME: Better way to unescape? | ||
403 | Interned::new_str(tok.text().trim_matches('"')) | ||
404 | } | ||
405 | _ => { | ||
406 | // `extern` default to be `extern "C"`. | ||
407 | Interned::new_str("C") | ||
408 | } | ||
409 | } | ||
410 | }); | ||
401 | 411 | ||
402 | let ast_id = self.source_ast_id_map.ast_id(func); | 412 | let ast_id = self.source_ast_id_map.ast_id(func); |
403 | let qualifier = FunctionQualifier { | 413 | |
404 | is_default: func.default_token().is_some(), | 414 | let mut flags = FnFlags::empty(); |
405 | is_const: func.const_token().is_some(), | 415 | if func.body().is_some() { |
406 | is_async: func.async_token().is_some(), | 416 | flags |= FnFlags::HAS_BODY; |
407 | is_unsafe: func.unsafe_token().is_some(), | 417 | } |
408 | abi: func.abi().map(|abi| { | 418 | if has_self_param { |
409 | // FIXME: Abi::abi() -> Option<SyntaxToken>? | 419 | flags |= FnFlags::HAS_SELF_PARAM; |
410 | match abi.syntax().last_token() { | 420 | } |
411 | Some(tok) if tok.kind() == SyntaxKind::STRING => { | 421 | if func.default_token().is_some() { |
412 | // FIXME: Better way to unescape? | 422 | flags |= FnFlags::IS_DEFAULT; |
413 | tok.text().trim_matches('"').into() | 423 | } |
414 | } | 424 | if func.const_token().is_some() { |
415 | _ => { | 425 | flags |= FnFlags::IS_CONST; |
416 | // `extern` default to be `extern "C"`. | 426 | } |
417 | "C".into() | 427 | if func.async_token().is_some() { |
418 | } | 428 | flags |= FnFlags::IS_ASYNC; |
419 | } | 429 | } |
420 | }), | 430 | if func.unsafe_token().is_some() { |
421 | }; | 431 | flags |= FnFlags::IS_UNSAFE; |
432 | } | ||
433 | |||
422 | let mut res = Function { | 434 | let mut res = Function { |
423 | name, | 435 | name, |
424 | visibility, | 436 | visibility, |
425 | generic_params: GenericParamsId::EMPTY, | 437 | generic_params: GenericParamsId::EMPTY, |
426 | has_self_param, | 438 | abi, |
427 | has_body, | ||
428 | qualifier, | ||
429 | is_in_extern_block: false, | ||
430 | params, | 439 | params, |
431 | ret_type, | 440 | ret_type: Interned::new(ret_type), |
432 | ast_id, | 441 | ast_id, |
442 | flags, | ||
433 | }; | 443 | }; |
434 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); | 444 | res.generic_params = self.lower_generic_params(GenericsOwner::Function(&res), func); |
435 | 445 | ||
@@ -579,7 +589,7 @@ impl Ctx { | |||
579 | &self.hygiene, | 589 | &self.hygiene, |
580 | |path, _use_tree, is_glob, alias| { | 590 | |path, _use_tree, is_glob, alias| { |
581 | imports.push(id(tree.imports.alloc(Import { | 591 | imports.push(id(tree.imports.alloc(Import { |
582 | path, | 592 | path: Interned::new(path), |
583 | alias, | 593 | alias, |
584 | visibility, | 594 | visibility, |
585 | is_glob, | 595 | is_glob, |
@@ -608,7 +618,7 @@ impl Ctx { | |||
608 | } | 618 | } |
609 | 619 | ||
610 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { | 620 | fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { |
611 | let path = ModPath::from_src(m.path()?, &self.hygiene)?; | 621 | let path = Interned::new(ModPath::from_src(m.path()?, &self.hygiene)?); |
612 | let ast_id = self.source_ast_id_map.ast_id(m); | 622 | let ast_id = self.source_ast_id_map.ast_id(m); |
613 | let res = MacroCall { path, ast_id }; | 623 | let res = MacroCall { path, ast_id }; |
614 | Some(id(self.data().macro_calls.alloc(res))) | 624 | Some(id(self.data().macro_calls.alloc(res))) |
@@ -642,8 +652,10 @@ impl Ctx { | |||
642 | ast::ExternItem::Fn(ast) => { | 652 | ast::ExternItem::Fn(ast) => { |
643 | let func_id = self.lower_function(&ast)?; | 653 | let func_id = self.lower_function(&ast)?; |
644 | let func = &mut self.data().functions[func_id.index]; | 654 | let func = &mut self.data().functions[func_id.index]; |
645 | func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); | 655 | if is_intrinsic_fn_unsafe(&func.name) { |
646 | func.is_in_extern_block = true; | 656 | func.flags |= FnFlags::IS_UNSAFE; |
657 | } | ||
658 | func.flags |= FnFlags::IS_IN_EXTERN_BLOCK; | ||
647 | func_id.into() | 659 | func_id.into() |
648 | } | 660 | } |
649 | ast::ExternItem::Static(ast) => { | 661 | ast::ExternItem::Static(ast) => { |
@@ -694,8 +706,7 @@ impl Ctx { | |||
694 | generics.fill(&self.body_ctx, sm, node); | 706 | generics.fill(&self.body_ctx, sm, node); |
695 | // lower `impl Trait` in arguments | 707 | // lower `impl Trait` in arguments |
696 | for id in func.params.clone() { | 708 | for id in func.params.clone() { |
697 | if let Param::Normal(ty) = self.data().params[id] { | 709 | if let Param::Normal(ty) = &self.data().params[id] { |
698 | let ty = self.data().type_refs.lookup(ty); | ||
699 | generics.fill_implicit_impl_trait_args(ty); | 710 | generics.fill_implicit_impl_trait_args(ty); |
700 | } | 711 | } |
701 | } | 712 | } |
@@ -749,20 +760,20 @@ impl Ctx { | |||
749 | self.data().vis.alloc(vis) | 760 | self.data().vis.alloc(vis) |
750 | } | 761 | } |
751 | 762 | ||
752 | fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Idx<TraitRef>> { | 763 | fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Interned<TraitRef>> { |
753 | let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?; | 764 | let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?; |
754 | Some(self.data().trait_refs.intern(trait_ref)) | 765 | Some(Interned::new(trait_ref)) |
755 | } | 766 | } |
756 | 767 | ||
757 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { | 768 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Interned<TypeRef> { |
758 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); | 769 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); |
759 | self.data().type_refs.intern(tyref) | 770 | Interned::new(tyref) |
760 | } | 771 | } |
761 | 772 | ||
762 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { | 773 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Interned<TypeRef> { |
763 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { | 774 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { |
764 | Some(it) => it, | 775 | Some(it) => it, |
765 | None => self.data().type_refs.intern(TypeRef::Error), | 776 | None => Interned::new(TypeRef::Error), |
766 | } | 777 | } |
767 | } | 778 | } |
768 | 779 | ||
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs index c9e07de86..f408e510a 100644 --- a/crates/hir_def/src/lib.rs +++ b/crates/hir_def/src/lib.rs | |||
@@ -49,6 +49,7 @@ pub mod import_map; | |||
49 | 49 | ||
50 | #[cfg(test)] | 50 | #[cfg(test)] |
51 | mod test_db; | 51 | mod test_db; |
52 | mod intern; | ||
52 | 53 | ||
53 | use std::{ | 54 | use std::{ |
54 | hash::{Hash, Hasher}, | 55 | hash::{Hash, Hasher}, |
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs index 9e8e4e9ec..7dd68219f 100644 --- a/crates/hir_def/src/nameres.rs +++ b/crates/hir_def/src/nameres.rs | |||
@@ -409,6 +409,31 @@ impl DefMap { | |||
409 | } | 409 | } |
410 | } | 410 | } |
411 | } | 411 | } |
412 | |||
413 | fn shrink_to_fit(&mut self) { | ||
414 | // Exhaustive match to require handling new fields. | ||
415 | let Self { | ||
416 | _c: _, | ||
417 | exported_proc_macros, | ||
418 | extern_prelude, | ||
419 | diagnostics, | ||
420 | modules, | ||
421 | block: _, | ||
422 | edition: _, | ||
423 | krate: _, | ||
424 | prelude: _, | ||
425 | root: _, | ||
426 | } = self; | ||
427 | |||
428 | extern_prelude.shrink_to_fit(); | ||
429 | exported_proc_macros.shrink_to_fit(); | ||
430 | diagnostics.shrink_to_fit(); | ||
431 | modules.shrink_to_fit(); | ||
432 | for (_, module) in modules.iter_mut() { | ||
433 | module.children.shrink_to_fit(); | ||
434 | module.scope.shrink_to_fit(); | ||
435 | } | ||
436 | } | ||
412 | } | 437 | } |
413 | 438 | ||
414 | impl ModuleData { | 439 | impl ModuleData { |
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs index 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)] |
139 | struct Import { | 144 | struct 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 | ||
10 | fn 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] |
11 | fn unresolved_import() { | 16 | fn 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] |
210 | fn 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] | ||
205 | fn good_out_dir_diagnostic() { | 225 | fn good_out_dir_diagnostic() { |
206 | check_diagnostics( | 226 | check_diagnostics( |
207 | r#" | 227 | r#" |
diff --git a/crates/hir_def/src/path.rs b/crates/hir_def/src/path.rs index 8c923bb7b..a3e83e2cf 100644 --- a/crates/hir_def/src/path.rs +++ b/crates/hir_def/src/path.rs | |||
@@ -7,7 +7,7 @@ use std::{ | |||
7 | sync::Arc, | 7 | sync::Arc, |
8 | }; | 8 | }; |
9 | 9 | ||
10 | use crate::{body::LowerCtx, type_ref::LifetimeRef}; | 10 | use crate::{body::LowerCtx, intern::Interned, type_ref::LifetimeRef}; |
11 | use base_db::CrateId; | 11 | use base_db::CrateId; |
12 | use hir_expand::{ | 12 | use hir_expand::{ |
13 | hygiene::Hygiene, | 13 | hygiene::Hygiene, |
@@ -48,7 +48,7 @@ pub enum ImportAlias { | |||
48 | 48 | ||
49 | impl ModPath { | 49 | impl ModPath { |
50 | pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { | 50 | pub fn from_src(path: ast::Path, hygiene: &Hygiene) -> Option<ModPath> { |
51 | lower::lower_path(path, hygiene).map(|it| it.mod_path) | 51 | lower::lower_path(path, hygiene).map(|it| (*it.mod_path).clone()) |
52 | } | 52 | } |
53 | 53 | ||
54 | pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath { | 54 | pub fn from_segments(kind: PathKind, segments: impl IntoIterator<Item = Name>) -> ModPath { |
@@ -123,7 +123,7 @@ pub struct Path { | |||
123 | /// Type based path like `<T>::foo`. | 123 | /// Type based path like `<T>::foo`. |
124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. | 124 | /// Note that paths like `<Type as Trait>::foo` are desugard to `Trait::<Self=Type>::foo`. |
125 | type_anchor: Option<Box<TypeRef>>, | 125 | type_anchor: Option<Box<TypeRef>>, |
126 | mod_path: ModPath, | 126 | mod_path: Interned<ModPath>, |
127 | /// Invariant: the same len as `self.mod_path.segments` | 127 | /// Invariant: the same len as `self.mod_path.segments` |
128 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 128 | generic_args: Vec<Option<Arc<GenericArgs>>>, |
129 | } | 129 | } |
@@ -176,7 +176,7 @@ impl Path { | |||
176 | path: ModPath, | 176 | path: ModPath, |
177 | generic_args: Vec<Option<Arc<GenericArgs>>>, | 177 | generic_args: Vec<Option<Arc<GenericArgs>>>, |
178 | ) -> Path { | 178 | ) -> Path { |
179 | Path { type_anchor: None, mod_path: path, generic_args } | 179 | Path { type_anchor: None, mod_path: Interned::new(path), generic_args } |
180 | } | 180 | } |
181 | 181 | ||
182 | pub fn kind(&self) -> &PathKind { | 182 | pub fn kind(&self) -> &PathKind { |
@@ -204,10 +204,10 @@ impl Path { | |||
204 | } | 204 | } |
205 | let res = Path { | 205 | let res = Path { |
206 | type_anchor: self.type_anchor.clone(), | 206 | type_anchor: self.type_anchor.clone(), |
207 | mod_path: ModPath::from_segments( | 207 | mod_path: Interned::new(ModPath::from_segments( |
208 | self.mod_path.kind.clone(), | 208 | self.mod_path.kind.clone(), |
209 | self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(), | 209 | self.mod_path.segments[..self.mod_path.segments.len() - 1].iter().cloned(), |
210 | ), | 210 | )), |
211 | generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), | 211 | generic_args: self.generic_args[..self.generic_args.len() - 1].to_vec(), |
212 | }; | 212 | }; |
213 | Some(res) | 213 | Some(res) |
@@ -283,7 +283,7 @@ impl From<Name> for Path { | |||
283 | fn from(name: Name) -> Path { | 283 | fn from(name: Name) -> Path { |
284 | Path { | 284 | Path { |
285 | type_anchor: None, | 285 | type_anchor: None, |
286 | mod_path: ModPath::from_segments(PathKind::Plain, iter::once(name)), | 286 | mod_path: Interned::new(ModPath::from_segments(PathKind::Plain, iter::once(name))), |
287 | generic_args: vec![None], | 287 | generic_args: vec![None], |
288 | } | 288 | } |
289 | } | 289 | } |
diff --git a/crates/hir_def/src/path/lower.rs b/crates/hir_def/src/path/lower.rs index 4de951fd3..28f6244da 100644 --- a/crates/hir_def/src/path/lower.rs +++ b/crates/hir_def/src/path/lower.rs | |||
@@ -2,6 +2,7 @@ | |||
2 | 2 | ||
3 | mod lower_use; | 3 | mod lower_use; |
4 | 4 | ||
5 | use crate::intern::Interned; | ||
5 | use std::sync::Arc; | 6 | use std::sync::Arc; |
6 | 7 | ||
7 | use either::Either; | 8 | use either::Either; |
@@ -74,10 +75,11 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
74 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo | 75 | // <T as Trait<A>>::Foo desugars to Trait<Self=T, A>::Foo |
75 | Some(trait_ref) => { | 76 | Some(trait_ref) => { |
76 | let path = Path::from_src(trait_ref.path()?, hygiene)?; | 77 | let path = Path::from_src(trait_ref.path()?, hygiene)?; |
78 | let mod_path = (*path.mod_path).clone(); | ||
77 | let num_segments = path.mod_path.segments.len(); | 79 | let num_segments = path.mod_path.segments.len(); |
78 | kind = path.mod_path.kind; | 80 | kind = mod_path.kind; |
79 | 81 | ||
80 | let mut prefix_segments = path.mod_path.segments; | 82 | let mut prefix_segments = mod_path.segments; |
81 | prefix_segments.reverse(); | 83 | prefix_segments.reverse(); |
82 | segments.extend(prefix_segments); | 84 | segments.extend(prefix_segments); |
83 | 85 | ||
@@ -140,7 +142,7 @@ pub(super) fn lower_path(mut path: ast::Path, hygiene: &Hygiene) -> Option<Path> | |||
140 | } | 142 | } |
141 | } | 143 | } |
142 | 144 | ||
143 | let mod_path = ModPath::from_segments(kind, segments); | 145 | let mod_path = Interned::new(ModPath::from_segments(kind, segments)); |
144 | return Some(Path { type_anchor, mod_path, generic_args }); | 146 | return Some(Path { type_anchor, mod_path, generic_args }); |
145 | 147 | ||
146 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { | 148 | fn qualifier(path: &ast::Path) -> Option<ast::Path> { |
diff --git a/crates/hir_def/src/test_db.rs b/crates/hir_def/src/test_db.rs index 10977761c..dd36106f8 100644 --- a/crates/hir_def/src/test_db.rs +++ b/crates/hir_def/src/test_db.rs | |||
@@ -265,4 +265,17 @@ impl TestDB { | |||
265 | 265 | ||
266 | assert_eq!(annotations, actual); | 266 | assert_eq!(annotations, actual); |
267 | } | 267 | } |
268 | |||
269 | pub(crate) fn check_no_diagnostics(&self) { | ||
270 | let db: &TestDB = self; | ||
271 | let annotations = db.extract_annotations(); | ||
272 | assert!(annotations.is_empty()); | ||
273 | |||
274 | let mut has_diagnostics = false; | ||
275 | db.diagnostics(|_| { | ||
276 | has_diagnostics = true; | ||
277 | }); | ||
278 | |||
279 | assert!(!has_diagnostics); | ||
280 | } | ||
268 | } | 281 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 4d52904b9..75ec4196b 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -1,10 +1,10 @@ | |||
1 | //! Builtin macro | 1 | //! Builtin macro |
2 | use crate::{ | 2 | use 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 | ||
7 | use base_db::{AnchoredPath, FileId}; | 7 | use base_db::{AnchoredPath, Edition, FileId}; |
8 | use cfg::CfgExpr; | 8 | use cfg::CfgExpr; |
9 | use either::Either; | 9 | use either::Either; |
10 | use mbe::{parse_exprs_with_sep, parse_to_token_tree, ExpandResult}; | 10 | use 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 | ||
289 | fn 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 | |||
287 | fn unquote_str(lit: &tt::Literal) -> Option<String> { | 308 | fn 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(¯o_call)); | 588 | let call_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_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 | ||
203 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 197 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
204 | let arg = db.macro_arg_text(id)?; | 198 | let arg = db.macro_arg_text(id)?; |
205 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg))?; | 199 | let (tt, tmap) = mbe::syntax_node_to_token_tree(&SyntaxNode::new_root(arg)); |
206 | Some(Arc::new((tt, tmap))) | 200 | Some(Arc::new((tt, tmap))) |
207 | } | 201 | } |
208 | 202 | ||
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index 9eedc8461..9705526fa 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -106,7 +106,7 @@ pub fn expand_eager_macro( | |||
106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), | 106 | mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), |
107 | ) -> Result<EagerMacroId, ErrorEmitted> { | 107 | ) -> Result<EagerMacroId, ErrorEmitted> { |
108 | let parsed_args = diagnostic_sink.option_with( | 108 | let parsed_args = diagnostic_sink.option_with( |
109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?)?.0), | 109 | || Some(mbe::ast_to_token_tree(¯o_call.value.token_tree()?).0), |
110 | || err("malformed macro invocation"), | 110 | || err("malformed macro invocation"), |
111 | )?; | 111 | )?; |
112 | 112 | ||
@@ -161,7 +161,7 @@ pub fn expand_eager_macro( | |||
161 | } | 161 | } |
162 | 162 | ||
163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { | 163 | fn to_subtree(node: &SyntaxNode) -> Option<tt::Subtree> { |
164 | let mut subtree = mbe::syntax_node_to_token_tree(node)?.0; | 164 | let mut subtree = mbe::syntax_node_to_token_tree(node).0; |
165 | subtree.delimiter = None; | 165 | subtree.delimiter = None; |
166 | Some(subtree) | 166 | Some(subtree) |
167 | } | 167 | } |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 203ebbe85..a0f8766b0 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -208,6 +208,8 @@ pub mod known { | |||
208 | line, | 208 | line, |
209 | module_path, | 209 | module_path, |
210 | assert, | 210 | assert, |
211 | core_panic, | ||
212 | std_panic, | ||
211 | stringify, | 213 | stringify, |
212 | concat, | 214 | concat, |
213 | include, | 215 | include, |
diff --git a/crates/hir_expand/src/quote.rs b/crates/hir_expand/src/quote.rs index 08bc5aa49..c82487ef0 100644 --- a/crates/hir_expand/src/quote.rs +++ b/crates/hir_expand/src/quote.rs | |||
@@ -104,6 +104,7 @@ macro_rules! __quote { | |||
104 | ( . ) => {$crate::__quote!(@PUNCT '.')}; | 104 | ( . ) => {$crate::__quote!(@PUNCT '.')}; |
105 | ( < ) => {$crate::__quote!(@PUNCT '<')}; | 105 | ( < ) => {$crate::__quote!(@PUNCT '<')}; |
106 | ( > ) => {$crate::__quote!(@PUNCT '>')}; | 106 | ( > ) => {$crate::__quote!(@PUNCT '>')}; |
107 | ( ! ) => {$crate::__quote!(@PUNCT '!')}; | ||
107 | 108 | ||
108 | ( $first:tt $($tail:tt)+ ) => { | 109 | ( $first:tt $($tail:tt)+ ) => { |
109 | { | 110 | { |
diff --git a/crates/hir_ty/src/autoderef.rs b/crates/hir_ty/src/autoderef.rs index dc5fc759a..70c56cc45 100644 --- a/crates/hir_ty/src/autoderef.rs +++ b/crates/hir_ty/src/autoderef.rs | |||
@@ -13,11 +13,9 @@ use log::{info, warn}; | |||
13 | 13 | ||
14 | use crate::{ | 14 | use crate::{ |
15 | db::HirDatabase, | 15 | db::HirDatabase, |
16 | to_assoc_type_id, to_chalk_trait_id, | ||
17 | traits::{InEnvironment, Solution}, | 16 | traits::{InEnvironment, Solution}, |
18 | utils::generics, | 17 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, Ty, |
19 | AliasEq, AliasTy, BoundVar, Canonical, CanonicalVarKinds, DebruijnIndex, Interner, | 18 | TyBuilder, TyKind, |
20 | ProjectionTy, Substitution, TraitRef, Ty, TyKind, | ||
21 | }; | 19 | }; |
22 | 20 | ||
23 | const AUTODEREF_RECURSION_LIMIT: usize = 10; | 21 | const AUTODEREF_RECURSION_LIMIT: usize = 10; |
@@ -57,21 +55,20 @@ fn deref_by_trait( | |||
57 | }; | 55 | }; |
58 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; | 56 | let target = db.trait_data(deref_trait).associated_type_by_name(&name![Target])?; |
59 | 57 | ||
60 | let generic_params = generics(db.upcast(), target.into()); | 58 | let projection = { |
61 | if generic_params.len() != 1 { | 59 | let b = TyBuilder::assoc_type_projection(db, target); |
62 | // the Target type + Deref trait should only have one generic parameter, | 60 | if b.remaining() != 1 { |
63 | // namely Deref's Self type | 61 | // the Target type + Deref trait should only have one generic parameter, |
64 | return None; | 62 | // namely Deref's Self type |
65 | } | 63 | return None; |
64 | } | ||
65 | b.push(ty.goal.value.clone()).build() | ||
66 | }; | ||
66 | 67 | ||
67 | // FIXME make the Canonical / bound var handling nicer | 68 | // FIXME make the Canonical / bound var handling nicer |
68 | 69 | ||
69 | let parameters = | ||
70 | Substitution::build_for_generics(&generic_params).push(ty.goal.value.clone()).build(); | ||
71 | |||
72 | // Check that the type implements Deref at all | 70 | // Check that the type implements Deref at all |
73 | let trait_ref = | 71 | let trait_ref = projection.trait_ref(db); |
74 | TraitRef { trait_id: to_chalk_trait_id(deref_trait), substitution: parameters.clone() }; | ||
75 | let implements_goal = Canonical { | 72 | let implements_goal = Canonical { |
76 | binders: ty.goal.binders.clone(), | 73 | binders: ty.goal.binders.clone(), |
77 | value: InEnvironment { | 74 | value: InEnvironment { |
@@ -84,11 +81,8 @@ fn deref_by_trait( | |||
84 | } | 81 | } |
85 | 82 | ||
86 | // Now do the assoc type projection | 83 | // Now do the assoc type projection |
87 | let projection = AliasEq { | 84 | let alias_eq = AliasEq { |
88 | alias: AliasTy::Projection(ProjectionTy { | 85 | alias: AliasTy::Projection(projection), |
89 | associated_ty_id: to_assoc_type_id(target), | ||
90 | substitution: parameters, | ||
91 | }), | ||
92 | ty: TyKind::BoundVar(BoundVar::new( | 86 | ty: TyKind::BoundVar(BoundVar::new( |
93 | DebruijnIndex::INNERMOST, | 87 | DebruijnIndex::INNERMOST, |
94 | ty.goal.binders.len(&Interner), | 88 | ty.goal.binders.len(&Interner), |
@@ -96,9 +90,7 @@ fn deref_by_trait( | |||
96 | .intern(&Interner), | 90 | .intern(&Interner), |
97 | }; | 91 | }; |
98 | 92 | ||
99 | let obligation = projection.cast(&Interner); | 93 | let in_env = InEnvironment { goal: alias_eq.cast(&Interner), environment: ty.environment }; |
100 | |||
101 | let in_env = InEnvironment { goal: obligation, environment: ty.environment }; | ||
102 | 94 | ||
103 | let canonical = Canonical { | 95 | let canonical = Canonical { |
104 | value: in_env, | 96 | value: in_env, |
@@ -131,7 +123,7 @@ fn deref_by_trait( | |||
131 | // new variables in that case | 123 | // new variables in that case |
132 | 124 | ||
133 | for i in 1..vars.0.binders.len(&Interner) { | 125 | for i in 1..vars.0.binders.len(&Interner) { |
134 | if vars.0.value[i - 1].interned(&Interner) | 126 | if vars.0.value.at(&Interner, i - 1).assert_ty_ref(&Interner).kind(&Interner) |
135 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) | 127 | != &TyKind::BoundVar(BoundVar::new(DebruijnIndex::INNERMOST, i - 1)) |
136 | { | 128 | { |
137 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); | 129 | warn!("complex solution for derefing {:?}: {:?}, ignoring", ty.goal, solution); |
@@ -139,7 +131,12 @@ fn deref_by_trait( | |||
139 | } | 131 | } |
140 | } | 132 | } |
141 | Some(Canonical { | 133 | Some(Canonical { |
142 | value: vars.0.value[vars.0.value.len() - 1].clone(), | 134 | value: vars |
135 | .0 | ||
136 | .value | ||
137 | .at(&Interner, vars.0.value.len(&Interner) - 1) | ||
138 | .assert_ty_ref(&Interner) | ||
139 | .clone(), | ||
143 | binders: vars.0.binders.clone(), | 140 | binders: vars.0.binders.clone(), |
144 | }) | 141 | }) |
145 | } | 142 | } |
diff --git a/crates/hir_ty/src/builder.rs b/crates/hir_ty/src/builder.rs new file mode 100644 index 000000000..4a9a8058f --- /dev/null +++ b/crates/hir_ty/src/builder.rs | |||
@@ -0,0 +1,219 @@ | |||
1 | //! `TyBuilder`, a helper for building instances of `Ty` and related types. | ||
2 | |||
3 | use std::iter; | ||
4 | |||
5 | use chalk_ir::{ | ||
6 | cast::{Cast, CastTo, Caster}, | ||
7 | interner::HasInterner, | ||
8 | AdtId, BoundVar, DebruijnIndex, Safety, Scalar, | ||
9 | }; | ||
10 | use hir_def::{builtin_type::BuiltinType, GenericDefId, TraitId, TypeAliasId}; | ||
11 | use smallvec::SmallVec; | ||
12 | |||
13 | use crate::{ | ||
14 | db::HirDatabase, primitive, to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, | ||
15 | CallableSig, FnPointer, FnSig, GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, | ||
16 | TyDefId, TyKind, TypeWalk, ValueTyDefId, | ||
17 | }; | ||
18 | |||
19 | /// This is a builder for `Ty` or anything that needs a `Substitution`. | ||
20 | pub struct TyBuilder<D> { | ||
21 | /// The `data` field is used to keep track of what we're building (e.g. an | ||
22 | /// ADT, a `TraitRef`, ...). | ||
23 | data: D, | ||
24 | vec: SmallVec<[GenericArg; 2]>, | ||
25 | param_count: usize, | ||
26 | } | ||
27 | |||
28 | impl<D> TyBuilder<D> { | ||
29 | fn new(data: D, param_count: usize) -> TyBuilder<D> { | ||
30 | TyBuilder { data, param_count, vec: SmallVec::with_capacity(param_count) } | ||
31 | } | ||
32 | |||
33 | fn build_internal(self) -> (D, Substitution) { | ||
34 | assert_eq!(self.vec.len(), self.param_count); | ||
35 | // FIXME: would be good to have a way to construct a chalk_ir::Substitution from the interned form | ||
36 | let subst = Substitution(self.vec); | ||
37 | (self.data, subst) | ||
38 | } | ||
39 | |||
40 | pub fn push(mut self, arg: impl CastTo<GenericArg>) -> Self { | ||
41 | self.vec.push(arg.cast(&Interner)); | ||
42 | self | ||
43 | } | ||
44 | |||
45 | pub fn remaining(&self) -> usize { | ||
46 | self.param_count - self.vec.len() | ||
47 | } | ||
48 | |||
49 | pub fn fill_with_bound_vars(self, debruijn: DebruijnIndex, starting_from: usize) -> Self { | ||
50 | self.fill( | ||
51 | (starting_from..) | ||
52 | .map(|idx| TyKind::BoundVar(BoundVar::new(debruijn, idx)).intern(&Interner)), | ||
53 | ) | ||
54 | } | ||
55 | |||
56 | pub fn fill_with_unknown(self) -> Self { | ||
57 | self.fill(iter::repeat(TyKind::Unknown.intern(&Interner))) | ||
58 | } | ||
59 | |||
60 | pub fn fill(mut self, filler: impl Iterator<Item = impl CastTo<GenericArg>>) -> Self { | ||
61 | self.vec.extend(filler.take(self.remaining()).casted(&Interner)); | ||
62 | assert_eq!(self.remaining(), 0); | ||
63 | self | ||
64 | } | ||
65 | |||
66 | pub fn use_parent_substs(mut self, parent_substs: &Substitution) -> Self { | ||
67 | assert!(self.vec.is_empty()); | ||
68 | assert!(parent_substs.len(&Interner) <= self.param_count); | ||
69 | self.vec.extend(parent_substs.iter(&Interner).cloned()); | ||
70 | self | ||
71 | } | ||
72 | } | ||
73 | |||
74 | impl TyBuilder<()> { | ||
75 | pub fn unit() -> Ty { | ||
76 | TyKind::Tuple(0, Substitution::empty(&Interner)).intern(&Interner) | ||
77 | } | ||
78 | |||
79 | pub fn fn_ptr(sig: CallableSig) -> Ty { | ||
80 | TyKind::Function(FnPointer { | ||
81 | num_args: sig.params().len(), | ||
82 | sig: FnSig { abi: (), safety: Safety::Safe, variadic: sig.is_varargs }, | ||
83 | substs: Substitution::from_iter(&Interner, sig.params_and_return.iter().cloned()), | ||
84 | }) | ||
85 | .intern(&Interner) | ||
86 | } | ||
87 | |||
88 | pub fn builtin(builtin: BuiltinType) -> Ty { | ||
89 | match builtin { | ||
90 | BuiltinType::Char => TyKind::Scalar(Scalar::Char).intern(&Interner), | ||
91 | BuiltinType::Bool => TyKind::Scalar(Scalar::Bool).intern(&Interner), | ||
92 | BuiltinType::Str => TyKind::Str.intern(&Interner), | ||
93 | BuiltinType::Int(t) => { | ||
94 | TyKind::Scalar(Scalar::Int(primitive::int_ty_from_builtin(t))).intern(&Interner) | ||
95 | } | ||
96 | BuiltinType::Uint(t) => { | ||
97 | TyKind::Scalar(Scalar::Uint(primitive::uint_ty_from_builtin(t))).intern(&Interner) | ||
98 | } | ||
99 | BuiltinType::Float(t) => { | ||
100 | TyKind::Scalar(Scalar::Float(primitive::float_ty_from_builtin(t))).intern(&Interner) | ||
101 | } | ||
102 | } | ||
103 | } | ||
104 | |||
105 | pub fn type_params_subst(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> Substitution { | ||
106 | let params = generics(db.upcast(), def.into()); | ||
107 | params.type_params_subst(db) | ||
108 | } | ||
109 | |||
110 | pub fn subst_for_def(db: &dyn HirDatabase, def: impl Into<GenericDefId>) -> TyBuilder<()> { | ||
111 | let def = def.into(); | ||
112 | let params = generics(db.upcast(), def); | ||
113 | let param_count = params.len(); | ||
114 | TyBuilder::new((), param_count) | ||
115 | } | ||
116 | |||
117 | pub fn build(self) -> Substitution { | ||
118 | let ((), subst) = self.build_internal(); | ||
119 | subst | ||
120 | } | ||
121 | } | ||
122 | |||
123 | impl TyBuilder<hir_def::AdtId> { | ||
124 | pub fn adt(db: &dyn HirDatabase, adt: hir_def::AdtId) -> TyBuilder<hir_def::AdtId> { | ||
125 | let generics = generics(db.upcast(), adt.into()); | ||
126 | let param_count = generics.len(); | ||
127 | TyBuilder::new(adt, param_count) | ||
128 | } | ||
129 | |||
130 | pub fn fill_with_defaults( | ||
131 | mut self, | ||
132 | db: &dyn HirDatabase, | ||
133 | mut fallback: impl FnMut() -> Ty, | ||
134 | ) -> Self { | ||
135 | let defaults = db.generic_defaults(self.data.into()); | ||
136 | for default_ty in defaults.iter().skip(self.vec.len()) { | ||
137 | if default_ty.skip_binders().is_unknown() { | ||
138 | self.vec.push(fallback().cast(&Interner)); | ||
139 | } else { | ||
140 | // each default can depend on the previous parameters | ||
141 | let subst_so_far = Substitution(self.vec.clone()); | ||
142 | self.vec.push(default_ty.clone().subst(&subst_so_far).cast(&Interner)); | ||
143 | } | ||
144 | } | ||
145 | self | ||
146 | } | ||
147 | |||
148 | pub fn build(self) -> Ty { | ||
149 | let (adt, subst) = self.build_internal(); | ||
150 | TyKind::Adt(AdtId(adt), subst).intern(&Interner) | ||
151 | } | ||
152 | } | ||
153 | |||
154 | pub struct Tuple(usize); | ||
155 | impl TyBuilder<Tuple> { | ||
156 | pub fn tuple(size: usize) -> TyBuilder<Tuple> { | ||
157 | TyBuilder::new(Tuple(size), size) | ||
158 | } | ||
159 | |||
160 | pub fn build(self) -> Ty { | ||
161 | let (Tuple(size), subst) = self.build_internal(); | ||
162 | TyKind::Tuple(size, subst).intern(&Interner) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | impl TyBuilder<TraitId> { | ||
167 | pub fn trait_ref(db: &dyn HirDatabase, trait_id: TraitId) -> TyBuilder<TraitId> { | ||
168 | let generics = generics(db.upcast(), trait_id.into()); | ||
169 | let param_count = generics.len(); | ||
170 | TyBuilder::new(trait_id, param_count) | ||
171 | } | ||
172 | |||
173 | pub fn build(self) -> TraitRef { | ||
174 | let (trait_id, substitution) = self.build_internal(); | ||
175 | TraitRef { trait_id: to_chalk_trait_id(trait_id), substitution } | ||
176 | } | ||
177 | } | ||
178 | |||
179 | impl TyBuilder<TypeAliasId> { | ||
180 | pub fn assoc_type_projection( | ||
181 | db: &dyn HirDatabase, | ||
182 | type_alias: TypeAliasId, | ||
183 | ) -> TyBuilder<TypeAliasId> { | ||
184 | let generics = generics(db.upcast(), type_alias.into()); | ||
185 | let param_count = generics.len(); | ||
186 | TyBuilder::new(type_alias, param_count) | ||
187 | } | ||
188 | |||
189 | pub fn build(self) -> ProjectionTy { | ||
190 | let (type_alias, substitution) = self.build_internal(); | ||
191 | ProjectionTy { associated_ty_id: to_assoc_type_id(type_alias), substitution } | ||
192 | } | ||
193 | } | ||
194 | |||
195 | impl<T: TypeWalk + HasInterner<Interner = Interner>> TyBuilder<Binders<T>> { | ||
196 | fn subst_binders(b: Binders<T>) -> Self { | ||
197 | let param_count = b.num_binders; | ||
198 | TyBuilder::new(b, param_count) | ||
199 | } | ||
200 | |||
201 | pub fn build(self) -> T { | ||
202 | let (b, subst) = self.build_internal(); | ||
203 | b.subst(&subst) | ||
204 | } | ||
205 | } | ||
206 | |||
207 | impl TyBuilder<Binders<Ty>> { | ||
208 | pub fn def_ty(db: &dyn HirDatabase, def: TyDefId) -> TyBuilder<Binders<Ty>> { | ||
209 | TyBuilder::subst_binders(db.ty(def.into())) | ||
210 | } | ||
211 | |||
212 | pub fn impl_self_ty(db: &dyn HirDatabase, def: hir_def::ImplId) -> TyBuilder<Binders<Ty>> { | ||
213 | TyBuilder::subst_binders(db.impl_self_ty(def)) | ||
214 | } | ||
215 | |||
216 | pub fn value_ty(db: &dyn HirDatabase, def: ValueTyDefId) -> TyBuilder<Binders<Ty>> { | ||
217 | TyBuilder::subst_binders(db.value_ty(def)) | ||
218 | } | ||
219 | } | ||
diff --git a/crates/hir_ty/src/chalk_cast.rs b/crates/hir_ty/src/chalk_cast.rs index bf884ae15..df6492113 100644 --- a/crates/hir_ty/src/chalk_cast.rs +++ b/crates/hir_ty/src/chalk_cast.rs | |||
@@ -5,7 +5,7 @@ use chalk_ir::{ | |||
5 | interner::HasInterner, | 5 | interner::HasInterner, |
6 | }; | 6 | }; |
7 | 7 | ||
8 | use crate::{AliasEq, DomainGoal, Interner, TraitRef, WhereClause}; | 8 | use crate::{AliasEq, DomainGoal, GenericArg, GenericArgData, Interner, TraitRef, Ty, WhereClause}; |
9 | 9 | ||
10 | macro_rules! has_interner { | 10 | macro_rules! has_interner { |
11 | ($t:ty) => { | 11 | ($t:ty) => { |
@@ -17,6 +17,8 @@ macro_rules! has_interner { | |||
17 | 17 | ||
18 | has_interner!(WhereClause); | 18 | has_interner!(WhereClause); |
19 | has_interner!(DomainGoal); | 19 | has_interner!(DomainGoal); |
20 | has_interner!(GenericArg); | ||
21 | has_interner!(Ty); | ||
20 | 22 | ||
21 | impl CastTo<WhereClause> for TraitRef { | 23 | impl CastTo<WhereClause> for TraitRef { |
22 | fn cast_to(self, _interner: &Interner) -> WhereClause { | 24 | fn cast_to(self, _interner: &Interner) -> WhereClause { |
@@ -36,6 +38,12 @@ impl CastTo<DomainGoal> for WhereClause { | |||
36 | } | 38 | } |
37 | } | 39 | } |
38 | 40 | ||
41 | impl CastTo<GenericArg> for Ty { | ||
42 | fn cast_to(self, interner: &Interner) -> GenericArg { | ||
43 | GenericArg::new(interner, GenericArgData::Ty(self)) | ||
44 | } | ||
45 | } | ||
46 | |||
39 | macro_rules! transitive_impl { | 47 | macro_rules! transitive_impl { |
40 | ($a:ty, $b:ty, $c:ty) => { | 48 | ($a:ty, $b:ty, $c:ty) => { |
41 | impl CastTo<$c> for $a { | 49 | impl CastTo<$c> for $a { |
@@ -51,3 +59,15 @@ macro_rules! transitive_impl { | |||
51 | 59 | ||
52 | transitive_impl!(TraitRef, WhereClause, DomainGoal); | 60 | transitive_impl!(TraitRef, WhereClause, DomainGoal); |
53 | transitive_impl!(AliasEq, WhereClause, DomainGoal); | 61 | transitive_impl!(AliasEq, WhereClause, DomainGoal); |
62 | |||
63 | macro_rules! reflexive_impl { | ||
64 | ($a:ty) => { | ||
65 | impl CastTo<$a> for $a { | ||
66 | fn cast_to(self, _interner: &Interner) -> $a { | ||
67 | self | ||
68 | } | ||
69 | } | ||
70 | }; | ||
71 | } | ||
72 | |||
73 | reflexive_impl!(GenericArg); | ||
diff --git a/crates/hir_ty/src/chalk_ext.rs b/crates/hir_ty/src/chalk_ext.rs new file mode 100644 index 000000000..b7463366b --- /dev/null +++ b/crates/hir_ty/src/chalk_ext.rs | |||
@@ -0,0 +1,13 @@ | |||
1 | //! Various extensions traits for Chalk types. | ||
2 | |||
3 | use crate::{Interner, Ty, TyKind}; | ||
4 | |||
5 | pub trait TyExt { | ||
6 | fn is_unit(&self) -> bool; | ||
7 | } | ||
8 | |||
9 | impl TyExt for Ty { | ||
10 | fn is_unit(&self) -> bool { | ||
11 | matches!(self.kind(&Interner), TyKind::Tuple(0, _)) | ||
12 | } | ||
13 | } | ||
diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 33a0f4d7d..1c9f9ede7 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs | |||
@@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
91 | 91 | ||
92 | fn validate_func(&mut self, func: FunctionId) { | 92 | fn validate_func(&mut self, func: FunctionId) { |
93 | let data = self.db.function_data(func); | 93 | let data = self.db.function_data(func); |
94 | if data.is_in_extern_block { | 94 | if data.is_in_extern_block() { |
95 | cov_mark::hit!(extern_func_incorrect_case_ignored); | 95 | cov_mark::hit!(extern_func_incorrect_case_ignored); |
96 | return; | 96 | return; |
97 | } | 97 | } |
@@ -99,8 +99,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { | |||
99 | let body = self.db.body(func.into()); | 99 | let body = self.db.body(func.into()); |
100 | 100 | ||
101 | // Recursively validate inner scope items, such as static variables and constants. | 101 | // Recursively validate inner scope items, such as static variables and constants. |
102 | let db = self.db; | 102 | for (_, block_def_map) in body.blocks(self.db.upcast()) { |
103 | for block_def_map in body.block_scopes.iter().filter_map(|block| db.block_def_map(*block)) { | ||
104 | for (_, module) in block_def_map.modules() { | 103 | for (_, module) in block_def_map.modules() { |
105 | for def_id in module.scope.declarations() { | 104 | for def_id in module.scope.declarations() { |
106 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); | 105 | let mut validator = DeclValidator::new(self.db, self.krate, self.sink); |
diff --git a/crates/hir_ty/src/diagnostics/expr.rs b/crates/hir_ty/src/diagnostics/expr.rs index 3909ad354..8169b759f 100644 --- a/crates/hir_ty/src/diagnostics/expr.rs +++ b/crates/hir_ty/src/diagnostics/expr.rs | |||
@@ -15,7 +15,7 @@ use crate::{ | |||
15 | MissingPatFields, RemoveThisSemicolon, | 15 | MissingPatFields, RemoveThisSemicolon, |
16 | }, | 16 | }, |
17 | utils::variant_data, | 17 | utils::variant_data, |
18 | AdtId, InferenceResult, Interner, Ty, TyKind, | 18 | AdtId, InferenceResult, Interner, TyExt, TyKind, |
19 | }; | 19 | }; |
20 | 20 | ||
21 | pub(crate) use hir_def::{ | 21 | pub(crate) use hir_def::{ |
@@ -378,7 +378,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
378 | _ => return, | 378 | _ => return, |
379 | }; | 379 | }; |
380 | 380 | ||
381 | let (params, required) = match mismatch.expected.interned(&Interner) { | 381 | let (params, required) = match mismatch.expected.kind(&Interner) { |
382 | TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) | 382 | TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ref parameters) |
383 | if *enum_id == core_result_enum => | 383 | if *enum_id == core_result_enum => |
384 | { | 384 | { |
@@ -392,7 +392,9 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
392 | _ => return, | 392 | _ => return, |
393 | }; | 393 | }; |
394 | 394 | ||
395 | if params.len() > 0 && params[0] == mismatch.actual { | 395 | if params.len(&Interner) > 0 |
396 | && params.at(&Interner, 0).ty(&Interner) == Some(&mismatch.actual) | ||
397 | { | ||
396 | let (_, source_map) = db.body_with_source_map(self.owner); | 398 | let (_, source_map) = db.body_with_source_map(self.owner); |
397 | 399 | ||
398 | if let Ok(source_ptr) = source_map.expr_syntax(id) { | 400 | if let Ok(source_ptr) = source_map.expr_syntax(id) { |
@@ -421,7 +423,7 @@ impl<'a, 'b> ExprValidator<'a, 'b> { | |||
421 | None => return, | 423 | None => return, |
422 | }; | 424 | }; |
423 | 425 | ||
424 | if mismatch.actual != Ty::unit() || mismatch.expected != *possible_tail_ty { | 426 | if !mismatch.actual.is_unit() || mismatch.expected != *possible_tail_ty { |
425 | return; | 427 | return; |
426 | } | 428 | } |
427 | 429 | ||
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 9cb472b51..34291578a 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -626,7 +626,7 @@ pub(super) fn is_useful( | |||
626 | // - enum with no variants | 626 | // - enum with no variants |
627 | // - `!` type | 627 | // - `!` type |
628 | // In those cases, no match arm is useful. | 628 | // In those cases, no match arm is useful. |
629 | match cx.infer[cx.match_expr].strip_references().interned(&Interner) { | 629 | match cx.infer[cx.match_expr].strip_references().kind(&Interner) { |
630 | TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { | 630 | TyKind::Adt(AdtId(hir_def::AdtId::EnumId(enum_id)), ..) => { |
631 | if cx.db.enum_data(*enum_id).variants.is_empty() { | 631 | if cx.db.enum_data(*enum_id).variants.is_empty() { |
632 | return Ok(Usefulness::NotUseful); | 632 | return Ok(Usefulness::NotUseful); |
@@ -792,7 +792,10 @@ fn pat_constructor(cx: &MatchCheckCtx, pat: PatIdOrWild) -> MatchCheckResult<Opt | |||
792 | Pat::Tuple { .. } => { | 792 | Pat::Tuple { .. } => { |
793 | let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); | 793 | let pat_id = pat.as_id().expect("we already know this pattern is not a wild"); |
794 | Some(Constructor::Tuple { | 794 | Some(Constructor::Tuple { |
795 | arity: cx.infer.type_of_pat[pat_id].as_tuple().ok_or(MatchCheckErr::Unknown)?.len(), | 795 | arity: cx.infer.type_of_pat[pat_id] |
796 | .as_tuple() | ||
797 | .ok_or(MatchCheckErr::Unknown)? | ||
798 | .len(&Interner), | ||
796 | }) | 799 | }) |
797 | } | 800 | } |
798 | Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { | 801 | Pat::Lit(lit_expr) => match cx.body.exprs[lit_expr] { |
diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 1f49a4909..b5efe9df5 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs | |||
@@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { | |||
32 | let def = self.owner; | 32 | let def = self.owner; |
33 | let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); | 33 | let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); |
34 | let is_unsafe = match self.owner { | 34 | let is_unsafe = match self.owner { |
35 | DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, | 35 | DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe(), |
36 | DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, | 36 | DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, |
37 | }; | 37 | }; |
38 | if is_unsafe | 38 | if is_unsafe |
@@ -86,7 +86,7 @@ fn walk_unsafe( | |||
86 | match expr { | 86 | match expr { |
87 | &Expr::Call { callee, .. } => { | 87 | &Expr::Call { callee, .. } => { |
88 | if let Some(func) = infer[callee].as_fn_def(db) { | 88 | if let Some(func) = infer[callee].as_fn_def(db) { |
89 | if db.function_data(func).qualifier.is_unsafe { | 89 | if db.function_data(func).is_unsafe() { |
90 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 90 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
91 | } | 91 | } |
92 | } | 92 | } |
@@ -103,14 +103,14 @@ fn walk_unsafe( | |||
103 | Expr::MethodCall { .. } => { | 103 | Expr::MethodCall { .. } => { |
104 | if infer | 104 | if infer |
105 | .method_resolution(current) | 105 | .method_resolution(current) |
106 | .map(|func| db.function_data(func).qualifier.is_unsafe) | 106 | .map(|func| db.function_data(func).is_unsafe()) |
107 | .unwrap_or(false) | 107 | .unwrap_or(false) |
108 | { | 108 | { |
109 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 109 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
110 | } | 110 | } |
111 | } | 111 | } |
112 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { | 112 | Expr::UnaryOp { expr, op: UnaryOp::Deref } => { |
113 | if let TyKind::Raw(..) = &infer[*expr].interned(&Interner) { | 113 | if let TyKind::Raw(..) = &infer[*expr].kind(&Interner) { |
114 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); | 114 | unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); |
115 | } | 115 | } |
116 | } | 116 | } |
diff --git a/crates/hir_ty/src/display.rs b/crates/hir_ty/src/display.rs index 51480304b..385bd9405 100644 --- a/crates/hir_ty/src/display.rs +++ b/crates/hir_ty/src/display.rs | |||
@@ -8,7 +8,7 @@ use hir_def::{ | |||
8 | find_path, | 8 | find_path, |
9 | generics::TypeParamProvenance, | 9 | generics::TypeParamProvenance, |
10 | item_scope::ItemInNs, | 10 | item_scope::ItemInNs, |
11 | path::{GenericArg, Path, PathKind}, | 11 | path::{Path, PathKind}, |
12 | type_ref::{TypeBound, TypeRef}, | 12 | type_ref::{TypeBound, TypeRef}, |
13 | visibility::Visibility, | 13 | visibility::Visibility, |
14 | AssocContainerId, Lookup, ModuleId, TraitId, | 14 | AssocContainerId, Lookup, ModuleId, TraitId, |
@@ -18,8 +18,8 @@ use hir_expand::name::Name; | |||
18 | use crate::{ | 18 | use crate::{ |
19 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, | 19 | db::HirDatabase, from_assoc_type_id, from_foreign_def_id, from_placeholder_idx, primitive, |
20 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, | 20 | to_assoc_type_id, traits::chalk::from_chalk, utils::generics, AdtId, AliasEq, AliasTy, |
21 | CallableDefId, CallableSig, DomainGoal, ImplTraitId, Interner, Lifetime, OpaqueTy, | 21 | CallableDefId, CallableSig, DomainGoal, GenericArg, ImplTraitId, Interner, Lifetime, OpaqueTy, |
22 | ProjectionTy, QuantifiedWhereClause, Scalar, Substitution, TraitRef, Ty, TyKind, WhereClause, | 22 | ProjectionTy, QuantifiedWhereClause, Scalar, TraitRef, Ty, TyExt, TyKind, WhereClause, |
23 | }; | 23 | }; |
24 | 24 | ||
25 | pub struct HirFormatter<'a> { | 25 | pub struct HirFormatter<'a> { |
@@ -251,16 +251,16 @@ impl HirDisplay for ProjectionTy { | |||
251 | } | 251 | } |
252 | 252 | ||
253 | let trait_ = f.db.trait_data(self.trait_(f.db)); | 253 | let trait_ = f.db.trait_data(self.trait_(f.db)); |
254 | let first_parameter = self.substitution[0].into_displayable( | 254 | let first_parameter = self.self_type_parameter().into_displayable( |
255 | f.db, | 255 | f.db, |
256 | f.max_size, | 256 | f.max_size, |
257 | f.omit_verbose_types, | 257 | f.omit_verbose_types, |
258 | f.display_target, | 258 | f.display_target, |
259 | ); | 259 | ); |
260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; | 260 | write!(f, "<{} as {}", first_parameter, trait_.name)?; |
261 | if self.substitution.len() > 1 { | 261 | if self.substitution.len(&Interner) > 1 { |
262 | write!(f, "<")?; | 262 | write!(f, "<")?; |
263 | f.write_joined(&self.substitution[1..], ", ")?; | 263 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; |
264 | write!(f, ">")?; | 264 | write!(f, ">")?; |
265 | } | 265 | } |
266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; | 266 | write!(f, ">::{}", f.db.type_alias_data(from_assoc_type_id(self.associated_ty_id)).name)?; |
@@ -274,7 +274,15 @@ impl HirDisplay for OpaqueTy { | |||
274 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 274 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
275 | } | 275 | } |
276 | 276 | ||
277 | self.substitution[0].hir_fmt(f) | 277 | self.substitution.at(&Interner, 0).hir_fmt(f) |
278 | } | ||
279 | } | ||
280 | |||
281 | impl HirDisplay for GenericArg { | ||
282 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | ||
283 | match self.interned() { | ||
284 | crate::GenericArgData::Ty(ty) => ty.hir_fmt(f), | ||
285 | } | ||
278 | } | 286 | } |
279 | } | 287 | } |
280 | 288 | ||
@@ -284,7 +292,7 @@ impl HirDisplay for Ty { | |||
284 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 292 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
285 | } | 293 | } |
286 | 294 | ||
287 | match self.interned(&Interner) { | 295 | match self.kind(&Interner) { |
288 | TyKind::Never => write!(f, "!")?, | 296 | TyKind::Never => write!(f, "!")?, |
289 | TyKind::Str => write!(f, "str")?, | 297 | TyKind::Str => write!(f, "str")?, |
290 | TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, | 298 | TyKind::Scalar(Scalar::Bool) => write!(f, "bool")?, |
@@ -306,7 +314,7 @@ impl HirDisplay for Ty { | |||
306 | let ty_display = | 314 | let ty_display = |
307 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 315 | t.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
308 | 316 | ||
309 | if matches!(self.interned(&Interner), TyKind::Raw(..)) { | 317 | if matches!(self.kind(&Interner), TyKind::Raw(..)) { |
310 | write!( | 318 | write!( |
311 | f, | 319 | f, |
312 | "*{}", | 320 | "*{}", |
@@ -328,7 +336,7 @@ impl HirDisplay for Ty { | |||
328 | 336 | ||
329 | // FIXME: all this just to decide whether to use parentheses... | 337 | // FIXME: all this just to decide whether to use parentheses... |
330 | let datas; | 338 | let datas; |
331 | let predicates: Vec<_> = match t.interned(&Interner) { | 339 | let predicates: Vec<_> = match t.kind(&Interner) { |
332 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { | 340 | TyKind::Dyn(dyn_ty) if dyn_ty.bounds.skip_binders().interned().len() > 1 => { |
333 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() | 341 | dyn_ty.bounds.skip_binders().interned().iter().cloned().collect() |
334 | } | 342 | } |
@@ -373,9 +381,9 @@ impl HirDisplay for Ty { | |||
373 | } | 381 | } |
374 | } | 382 | } |
375 | TyKind::Tuple(_, substs) => { | 383 | TyKind::Tuple(_, substs) => { |
376 | if substs.len() == 1 { | 384 | if substs.len(&Interner) == 1 { |
377 | write!(f, "(")?; | 385 | write!(f, "(")?; |
378 | substs[0].hir_fmt(f)?; | 386 | substs.at(&Interner, 0).hir_fmt(f)?; |
379 | write!(f, ",)")?; | 387 | write!(f, ",)")?; |
380 | } else { | 388 | } else { |
381 | write!(f, "(")?; | 389 | write!(f, "(")?; |
@@ -399,7 +407,7 @@ impl HirDisplay for Ty { | |||
399 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? | 407 | write!(f, "{}", f.db.enum_data(e.parent).variants[e.local_id].name)? |
400 | } | 408 | } |
401 | }; | 409 | }; |
402 | if parameters.len() > 0 { | 410 | if parameters.len(&Interner) > 0 { |
403 | let generics = generics(f.db.upcast(), def.into()); | 411 | let generics = generics(f.db.upcast(), def.into()); |
404 | let (parent_params, self_param, type_params, _impl_trait_params) = | 412 | let (parent_params, self_param, type_params, _impl_trait_params) = |
405 | generics.provenance_split(); | 413 | generics.provenance_split(); |
@@ -415,7 +423,7 @@ impl HirDisplay for Ty { | |||
415 | f.write_joined(sig.params(), ", ")?; | 423 | f.write_joined(sig.params(), ", ")?; |
416 | write!(f, ")")?; | 424 | write!(f, ")")?; |
417 | let ret = sig.ret(); | 425 | let ret = sig.ret(); |
418 | if *ret != Ty::unit() { | 426 | if !ret.is_unit() { |
419 | let ret_display = ret.into_displayable( | 427 | let ret_display = ret.into_displayable( |
420 | f.db, | 428 | f.db, |
421 | f.max_size, | 429 | f.max_size, |
@@ -451,7 +459,7 @@ impl HirDisplay for Ty { | |||
451 | } | 459 | } |
452 | } | 460 | } |
453 | 461 | ||
454 | if parameters.len() > 0 { | 462 | if parameters.len(&Interner) > 0 { |
455 | let parameters_to_write = if f.display_target.is_source_code() | 463 | let parameters_to_write = if f.display_target.is_source_code() |
456 | || f.omit_verbose_types() | 464 | || f.omit_verbose_types() |
457 | { | 465 | { |
@@ -463,9 +471,11 @@ impl HirDisplay for Ty { | |||
463 | None => parameters.0.as_ref(), | 471 | None => parameters.0.as_ref(), |
464 | Some(default_parameters) => { | 472 | Some(default_parameters) => { |
465 | let mut default_from = 0; | 473 | let mut default_from = 0; |
466 | for (i, parameter) in parameters.iter().enumerate() { | 474 | for (i, parameter) in parameters.iter(&Interner).enumerate() { |
467 | match (parameter.interned(&Interner), default_parameters.get(i)) | 475 | match ( |
468 | { | 476 | parameter.assert_ty_ref(&Interner).kind(&Interner), |
477 | default_parameters.get(i), | ||
478 | ) { | ||
469 | (&TyKind::Unknown, _) | (_, None) => { | 479 | (&TyKind::Unknown, _) | (_, None) => { |
470 | default_from = i + 1; | 480 | default_from = i + 1; |
471 | } | 481 | } |
@@ -473,7 +483,8 @@ impl HirDisplay for Ty { | |||
473 | let actual_default = default_parameter | 483 | let actual_default = default_parameter |
474 | .clone() | 484 | .clone() |
475 | .subst(¶meters.prefix(i)); | 485 | .subst(¶meters.prefix(i)); |
476 | if parameter != &actual_default { | 486 | if parameter.assert_ty_ref(&Interner) != &actual_default |
487 | { | ||
477 | default_from = i + 1; | 488 | default_from = i + 1; |
478 | } | 489 | } |
479 | } | 490 | } |
@@ -504,7 +515,7 @@ impl HirDisplay for Ty { | |||
504 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) | 515 | // Use placeholder associated types when the target is test (https://rust-lang.github.io/chalk/book/clauses/type_equality.html#placeholder-associated-types) |
505 | if f.display_target.is_test() { | 516 | if f.display_target.is_test() { |
506 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; | 517 | write!(f, "{}::{}", trait_.name, type_alias_data.name)?; |
507 | if parameters.len() > 0 { | 518 | if parameters.len(&Interner) > 0 { |
508 | write!(f, "<")?; | 519 | write!(f, "<")?; |
509 | f.write_joined(&*parameters.0, ", ")?; | 520 | f.write_joined(&*parameters.0, ", ")?; |
510 | write!(f, ">")?; | 521 | write!(f, ">")?; |
@@ -537,7 +548,7 @@ impl HirDisplay for Ty { | |||
537 | } | 548 | } |
538 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { | 549 | ImplTraitId::AsyncBlockTypeImplTrait(..) => { |
539 | write!(f, "impl Future<Output = ")?; | 550 | write!(f, "impl Future<Output = ")?; |
540 | parameters[0].hir_fmt(f)?; | 551 | parameters.at(&Interner, 0).hir_fmt(f)?; |
541 | write!(f, ">")?; | 552 | write!(f, ">")?; |
542 | } | 553 | } |
543 | } | 554 | } |
@@ -548,7 +559,7 @@ impl HirDisplay for Ty { | |||
548 | DisplaySourceCodeError::Closure, | 559 | DisplaySourceCodeError::Closure, |
549 | )); | 560 | )); |
550 | } | 561 | } |
551 | let sig = substs[0].callable_sig(f.db); | 562 | let sig = substs.at(&Interner, 0).assert_ty_ref(&Interner).callable_sig(f.db); |
552 | if let Some(sig) = sig { | 563 | if let Some(sig) = sig { |
553 | if sig.params().is_empty() { | 564 | if sig.params().is_empty() { |
554 | write!(f, "||")?; | 565 | write!(f, "||")?; |
@@ -580,7 +591,7 @@ impl HirDisplay for Ty { | |||
580 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? | 591 | write!(f, "{}", param_data.name.clone().unwrap_or_else(Name::missing))? |
581 | } | 592 | } |
582 | TypeParamProvenance::ArgumentImplTrait => { | 593 | TypeParamProvenance::ArgumentImplTrait => { |
583 | let substs = Substitution::type_params_for_generics(f.db, &generics); | 594 | let substs = generics.type_params_subst(f.db); |
584 | let bounds = f | 595 | let bounds = f |
585 | .db | 596 | .db |
586 | .generic_predicates(id.parent) | 597 | .generic_predicates(id.parent) |
@@ -652,7 +663,7 @@ impl HirDisplay for CallableSig { | |||
652 | } | 663 | } |
653 | write!(f, ")")?; | 664 | write!(f, ")")?; |
654 | let ret = self.ret(); | 665 | let ret = self.ret(); |
655 | if *ret != Ty::unit() { | 666 | if !ret.is_unit() { |
656 | let ret_display = | 667 | let ret_display = |
657 | ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); | 668 | ret.into_displayable(f.db, f.max_size, f.omit_verbose_types, f.display_target); |
658 | write!(f, " -> {}", ret_display)?; | 669 | write!(f, " -> {}", ret_display)?; |
@@ -718,7 +729,9 @@ fn write_bounds_like_dyn_trait( | |||
718 | write!(f, "{}", f.db.trait_data(trait_).name)?; | 729 | write!(f, "{}", f.db.trait_data(trait_).name)?; |
719 | if let [_, params @ ..] = &*trait_ref.substitution.0 { | 730 | if let [_, params @ ..] = &*trait_ref.substitution.0 { |
720 | if is_fn_trait { | 731 | if is_fn_trait { |
721 | if let Some(args) = params.first().and_then(|it| it.as_tuple()) { | 732 | if let Some(args) = |
733 | params.first().and_then(|it| it.assert_ty_ref(&Interner).as_tuple()) | ||
734 | { | ||
722 | write!(f, "(")?; | 735 | write!(f, "(")?; |
723 | f.write_joined(&*args.0, ", ")?; | 736 | f.write_joined(&*args.0, ", ")?; |
724 | write!(f, ")")?; | 737 | write!(f, ")")?; |
@@ -767,16 +780,16 @@ impl TraitRef { | |||
767 | return write!(f, "{}", TYPE_HINT_TRUNCATION); | 780 | return write!(f, "{}", TYPE_HINT_TRUNCATION); |
768 | } | 781 | } |
769 | 782 | ||
770 | self.substitution[0].hir_fmt(f)?; | 783 | self.self_type_parameter().hir_fmt(f)?; |
771 | if use_as { | 784 | if use_as { |
772 | write!(f, " as ")?; | 785 | write!(f, " as ")?; |
773 | } else { | 786 | } else { |
774 | write!(f, ": ")?; | 787 | write!(f, ": ")?; |
775 | } | 788 | } |
776 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; | 789 | write!(f, "{}", f.db.trait_data(self.hir_trait_id()).name)?; |
777 | if self.substitution.len() > 1 { | 790 | if self.substitution.len(&Interner) > 1 { |
778 | write!(f, "<")?; | 791 | write!(f, "<")?; |
779 | f.write_joined(&self.substitution[1..], ", ")?; | 792 | f.write_joined(&self.substitution.interned(&Interner)[1..], ", ")?; |
780 | write!(f, ">")?; | 793 | write!(f, ">")?; |
781 | } | 794 | } |
782 | Ok(()) | 795 | Ok(()) |
@@ -1016,11 +1029,11 @@ impl HirDisplay for Path { | |||
1016 | } | 1029 | } |
1017 | } | 1030 | } |
1018 | 1031 | ||
1019 | impl HirDisplay for GenericArg { | 1032 | impl HirDisplay for hir_def::path::GenericArg { |
1020 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { | 1033 | fn hir_fmt(&self, f: &mut HirFormatter) -> Result<(), HirDisplayError> { |
1021 | match self { | 1034 | match self { |
1022 | GenericArg::Type(ty) => ty.hir_fmt(f), | 1035 | hir_def::path::GenericArg::Type(ty) => ty.hir_fmt(f), |
1023 | GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), | 1036 | hir_def::path::GenericArg::Lifetime(lifetime) => write!(f, "{}", lifetime.name), |
1024 | } | 1037 | } |
1025 | } | 1038 | } |
1026 | } | 1039 | } |
diff --git a/crates/hir_ty/src/infer.rs b/crates/hir_ty/src/infer.rs index 497a1beb7..1b1d4458c 100644 --- a/crates/hir_ty/src/infer.rs +++ b/crates/hir_ty/src/infer.rs | |||
@@ -38,11 +38,11 @@ use syntax::SmolStr; | |||
38 | 38 | ||
39 | use super::{ | 39 | use super::{ |
40 | traits::{DomainGoal, Guidance, Solution}, | 40 | traits::{DomainGoal, Guidance, Solution}, |
41 | InEnvironment, ProjectionTy, Substitution, TraitEnvironment, TraitRef, Ty, TypeWalk, | 41 | InEnvironment, ProjectionTy, TraitEnvironment, TraitRef, Ty, TypeWalk, |
42 | }; | 42 | }; |
43 | use crate::{ | 43 | use crate::{ |
44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, | 44 | db::HirDatabase, infer::diagnostics::InferenceDiagnostic, lower::ImplTraitLoweringMode, |
45 | to_assoc_type_id, to_chalk_trait_id, AliasEq, AliasTy, Interner, TyKind, | 45 | to_assoc_type_id, AliasEq, AliasTy, Interner, TyBuilder, TyKind, |
46 | }; | 46 | }; |
47 | 47 | ||
48 | // This lint has a false positive here. See the link below for details. | 48 | // This lint has a false positive here. See the link below for details. |
@@ -325,7 +325,7 @@ impl<'a> InferenceContext<'a> { | |||
325 | 325 | ||
326 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. | 326 | /// Replaces Ty::Unknown by a new type var, so we can maybe still infer it. |
327 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { | 327 | fn insert_type_vars_shallow(&mut self, ty: Ty) -> Ty { |
328 | match ty.interned(&Interner) { | 328 | match ty.kind(&Interner) { |
329 | TyKind::Unknown => self.table.new_type_var(), | 329 | TyKind::Unknown => self.table.new_type_var(), |
330 | _ => ty, | 330 | _ => ty, |
331 | } | 331 | } |
@@ -340,6 +340,8 @@ impl<'a> InferenceContext<'a> { | |||
340 | // no change | 340 | // no change |
341 | return; | 341 | return; |
342 | } | 342 | } |
343 | let _span = profile::span("resolve_obligations_as_possible"); | ||
344 | |||
343 | self.last_obligations_check = Some(self.table.revision); | 345 | self.last_obligations_check = Some(self.table.revision); |
344 | let obligations = mem::replace(&mut self.obligations, Vec::new()); | 346 | let obligations = mem::replace(&mut self.obligations, Vec::new()); |
345 | for obligation in obligations { | 347 | for obligation in obligations { |
@@ -407,16 +409,14 @@ impl<'a> InferenceContext<'a> { | |||
407 | _ => panic!("resolve_associated_type called with non-associated type"), | 409 | _ => panic!("resolve_associated_type called with non-associated type"), |