diff options
29 files changed, 208 insertions, 91 deletions
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 4ee08ef21..97f162315 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -44,6 +44,7 @@ use hir_def::{ | |||
44 | per_ns::PerNs, | 44 | per_ns::PerNs, |
45 | resolver::{HasResolver, Resolver}, | 45 | resolver::{HasResolver, Resolver}, |
46 | src::HasSource as _, | 46 | src::HasSource as _, |
47 | type_ref::TraitRef, | ||
47 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, | 48 | AdtId, AssocContainerId, AssocItemId, AssocItemLoc, AttrDefId, ConstId, ConstParamId, |
48 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, | 49 | DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, ImplId, LifetimeParamId, |
49 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, | 50 | LocalEnumVariantId, LocalFieldId, Lookup, ModuleId, StaticId, StructId, TraitId, TypeAliasId, |
@@ -1573,9 +1574,9 @@ impl Impl { | |||
1573 | }; | 1574 | }; |
1574 | 1575 | ||
1575 | let filter = |impl_def: &Impl| { | 1576 | let filter = |impl_def: &Impl| { |
1576 | let target_ty = impl_def.target_ty(db); | 1577 | let self_ty = impl_def.self_ty(db); |
1577 | let rref = target_ty.remove_ref(); | 1578 | let rref = self_ty.remove_ref(); |
1578 | ty.equals_ctor(rref.as_ref().map_or(&target_ty.ty, |it| &it.ty)) | 1579 | ty.equals_ctor(rref.as_ref().map_or(&self_ty.ty, |it| &it.ty)) |
1579 | }; | 1580 | }; |
1580 | 1581 | ||
1581 | let mut all = Vec::new(); | 1582 | let mut all = Vec::new(); |
@@ -1613,16 +1614,16 @@ impl Impl { | |||
1613 | 1614 | ||
1614 | // FIXME: the return type is wrong. This should be a hir version of | 1615 | // FIXME: the return type is wrong. This should be a hir version of |
1615 | // `TraitRef` (ie, resolved `TypeRef`). | 1616 | // `TraitRef` (ie, resolved `TypeRef`). |
1616 | pub fn target_trait(self, db: &dyn HirDatabase) -> Option<TypeRef> { | 1617 | pub fn trait_(self, db: &dyn HirDatabase) -> Option<TraitRef> { |
1617 | db.impl_data(self.id).target_trait.clone() | 1618 | db.impl_data(self.id).target_trait.clone() |
1618 | } | 1619 | } |
1619 | 1620 | ||
1620 | pub fn target_ty(self, db: &dyn HirDatabase) -> Type { | 1621 | pub fn self_ty(self, db: &dyn HirDatabase) -> Type { |
1621 | let impl_data = db.impl_data(self.id); | 1622 | let impl_data = db.impl_data(self.id); |
1622 | let resolver = self.id.resolver(db.upcast()); | 1623 | let resolver = self.id.resolver(db.upcast()); |
1623 | let krate = self.id.lookup(db.upcast()).container.krate(); | 1624 | let krate = self.id.lookup(db.upcast()).container.krate(); |
1624 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); | 1625 | let ctx = hir_ty::TyLoweringContext::new(db, &resolver); |
1625 | let ty = ctx.lower_ty(&impl_data.target_type); | 1626 | let ty = ctx.lower_ty(&impl_data.self_ty); |
1626 | Type::new_with_resolver_inner(db, krate, &resolver, ty) | 1627 | Type::new_with_resolver_inner(db, krate, &resolver, ty) |
1627 | } | 1628 | } |
1628 | 1629 | ||
diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index 0be868ba2..214bcc648 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs | |||
@@ -10,7 +10,7 @@ use crate::{ | |||
10 | body::Expander, | 10 | body::Expander, |
11 | db::DefDatabase, | 11 | db::DefDatabase, |
12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, | 12 | item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem, Param}, |
13 | type_ref::{TypeBound, TypeRef}, | 13 | type_ref::{TraitRef, TypeBound, TypeRef}, |
14 | visibility::RawVisibility, | 14 | visibility::RawVisibility, |
15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, | 15 | AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, |
16 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, | 16 | Intern, Lookup, ModuleId, StaticId, TraitId, TypeAliasId, TypeAliasLoc, |
@@ -156,8 +156,8 @@ impl TraitData { | |||
156 | 156 | ||
157 | #[derive(Debug, Clone, PartialEq, Eq)] | 157 | #[derive(Debug, Clone, PartialEq, Eq)] |
158 | pub struct ImplData { | 158 | pub struct ImplData { |
159 | pub target_trait: Option<TypeRef>, | 159 | pub target_trait: Option<TraitRef>, |
160 | pub target_type: TypeRef, | 160 | pub self_ty: TypeRef, |
161 | pub items: Vec<AssocItemId>, | 161 | pub items: Vec<AssocItemId>, |
162 | pub is_negative: bool, | 162 | pub is_negative: bool, |
163 | } | 163 | } |
@@ -170,7 +170,7 @@ impl ImplData { | |||
170 | let item_tree = impl_loc.id.item_tree(db); | 170 | let item_tree = impl_loc.id.item_tree(db); |
171 | let impl_def = &item_tree[impl_loc.id.value]; | 171 | let impl_def = &item_tree[impl_loc.id.value]; |
172 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); | 172 | let target_trait = impl_def.target_trait.map(|id| item_tree[id].clone()); |
173 | let target_type = item_tree[impl_def.target_type].clone(); | 173 | let self_ty = item_tree[impl_def.self_ty].clone(); |
174 | let is_negative = impl_def.is_negative; | 174 | let is_negative = impl_def.is_negative; |
175 | let module_id = impl_loc.container; | 175 | let module_id = impl_loc.container; |
176 | let container = AssocContainerId::ImplId(id); | 176 | let container = AssocContainerId::ImplId(id); |
@@ -187,7 +187,7 @@ impl ImplData { | |||
187 | ); | 187 | ); |
188 | let items = items.into_iter().map(|(_, item)| item).collect(); | 188 | let items = items.into_iter().map(|(_, item)| item).collect(); |
189 | 189 | ||
190 | Arc::new(ImplData { target_trait, target_type, items, is_negative }) | 190 | Arc::new(ImplData { target_trait, self_ty, items, is_negative }) |
191 | } | 191 | } |
192 | } | 192 | } |
193 | 193 | ||
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index ca0048b16..5449bbf5d 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs | |||
@@ -31,7 +31,7 @@ use crate::{ | |||
31 | db::DefDatabase, | 31 | db::DefDatabase, |
32 | generics::GenericParams, | 32 | generics::GenericParams, |
33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, | 33 | path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind}, |
34 | type_ref::{Mutability, TypeBound, TypeRef}, | 34 | type_ref::{Mutability, TraitRef, TypeBound, TypeRef}, |
35 | visibility::RawVisibility, | 35 | visibility::RawVisibility, |
36 | }; | 36 | }; |
37 | 37 | ||
@@ -147,6 +147,7 @@ impl ItemTree { | |||
147 | vis, | 147 | vis, |
148 | generics, | 148 | generics, |
149 | type_refs, | 149 | type_refs, |
150 | trait_refs, | ||
150 | inner_items, | 151 | inner_items, |
151 | } = &mut **data; | 152 | } = &mut **data; |
152 | 153 | ||
@@ -173,6 +174,7 @@ impl ItemTree { | |||
173 | generics.arena.shrink_to_fit(); | 174 | generics.arena.shrink_to_fit(); |
174 | type_refs.arena.shrink_to_fit(); | 175 | type_refs.arena.shrink_to_fit(); |
175 | type_refs.map.shrink_to_fit(); | 176 | type_refs.map.shrink_to_fit(); |
177 | trait_refs.map.shrink_to_fit(); | ||
176 | 178 | ||
177 | inner_items.shrink_to_fit(); | 179 | inner_items.shrink_to_fit(); |
178 | } | 180 | } |
@@ -295,6 +297,32 @@ impl TypeRefStorage { | |||
295 | } | 297 | } |
296 | } | 298 | } |
297 | 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 | |||
298 | #[derive(Default, Debug, Eq, PartialEq)] | 326 | #[derive(Default, Debug, Eq, PartialEq)] |
299 | struct ItemTreeData { | 327 | struct ItemTreeData { |
300 | imports: Arena<Import>, | 328 | imports: Arena<Import>, |
@@ -319,6 +347,7 @@ struct ItemTreeData { | |||
319 | vis: ItemVisibilities, | 347 | vis: ItemVisibilities, |
320 | generics: GenericParamsStorage, | 348 | generics: GenericParamsStorage, |
321 | type_refs: TypeRefStorage, | 349 | type_refs: TypeRefStorage, |
350 | trait_refs: TraitRefStorage, | ||
322 | 351 | ||
323 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, | 352 | inner_items: FxHashMap<FileAstId<ast::BlockExpr>, SmallVec<[ModItem; 1]>>, |
324 | } | 353 | } |
@@ -556,6 +585,14 @@ impl Index<Idx<TypeRef>> for ItemTree { | |||
556 | } | 585 | } |
557 | } | 586 | } |
558 | 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 | |||
559 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { | 596 | impl<N: ItemTreeNode> Index<FileItemTreeId<N>> for ItemTree { |
560 | type Output = N; | 597 | type Output = N; |
561 | fn index(&self, id: FileItemTreeId<N>) -> &N { | 598 | fn index(&self, id: FileItemTreeId<N>) -> &N { |
@@ -692,8 +729,8 @@ pub struct Trait { | |||
692 | #[derive(Debug, Clone, Eq, PartialEq)] | 729 | #[derive(Debug, Clone, Eq, PartialEq)] |
693 | pub struct Impl { | 730 | pub struct Impl { |
694 | pub generic_params: GenericParamsId, | 731 | pub generic_params: GenericParamsId, |
695 | pub target_trait: Option<Idx<TypeRef>>, | 732 | pub target_trait: Option<Idx<TraitRef>>, |
696 | pub target_type: Idx<TypeRef>, | 733 | pub self_ty: Idx<TypeRef>, |
697 | pub is_negative: bool, | 734 | pub is_negative: bool, |
698 | pub items: Box<[AssocItem]>, | 735 | pub items: Box<[AssocItem]>, |
699 | pub ast_id: FileAstId<ast::Impl>, | 736 | pub ast_id: FileAstId<ast::Impl>, |
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 3f558edd8..8d3862811 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs | |||
@@ -11,7 +11,7 @@ use syntax::{ | |||
11 | 11 | ||
12 | use crate::{ | 12 | use crate::{ |
13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, | 13 | generics::{GenericParams, TypeParamData, TypeParamProvenance}, |
14 | type_ref::LifetimeRef, | 14 | type_ref::{LifetimeRef, TraitRef}, |
15 | }; | 15 | }; |
16 | 16 | ||
17 | use super::*; | 17 | use super::*; |
@@ -536,8 +536,11 @@ impl Ctx { | |||
536 | fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { | 536 | fn lower_impl(&mut self, impl_def: &ast::Impl) -> Option<FileItemTreeId<Impl>> { |
537 | let generic_params = | 537 | let generic_params = |
538 | self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); | 538 | self.lower_generic_params_and_inner_items(GenericsOwner::Impl, impl_def); |
539 | let target_trait = impl_def.trait_().map(|tr| self.lower_type_ref(&tr)); | 539 | // FIXME: If trait lowering fails, due to a non PathType for example, we treat this impl |
540 | let target_type = self.lower_type_ref(&impl_def.self_ty()?); | 540 | // as if it was an non-trait impl. Ideally we want to create a unique missing ref that only |
541 | // equals itself. | ||
542 | let target_trait = impl_def.trait_().and_then(|tr| self.lower_trait_ref(&tr)); | ||
543 | let self_ty = self.lower_type_ref(&impl_def.self_ty()?); | ||
541 | let is_negative = impl_def.excl_token().is_some(); | 544 | let is_negative = impl_def.excl_token().is_some(); |
542 | 545 | ||
543 | // We cannot use `assoc_items()` here as that does not include macro calls. | 546 | // We cannot use `assoc_items()` here as that does not include macro calls. |
@@ -554,7 +557,7 @@ impl Ctx { | |||
554 | }) | 557 | }) |
555 | .collect(); | 558 | .collect(); |
556 | let ast_id = self.source_ast_id_map.ast_id(impl_def); | 559 | let ast_id = self.source_ast_id_map.ast_id(impl_def); |
557 | let res = Impl { generic_params, target_trait, target_type, is_negative, items, ast_id }; | 560 | let res = Impl { generic_params, target_trait, self_ty, is_negative, items, ast_id }; |
558 | Some(id(self.data().impls.alloc(res))) | 561 | Some(id(self.data().impls.alloc(res))) |
559 | } | 562 | } |
560 | 563 | ||
@@ -740,10 +743,16 @@ impl Ctx { | |||
740 | self.data().vis.alloc(vis) | 743 | self.data().vis.alloc(vis) |
741 | } | 744 | } |
742 | 745 | ||
746 | fn lower_trait_ref(&mut self, trait_ref: &ast::Type) -> Option<Idx<TraitRef>> { | ||
747 | let trait_ref = TraitRef::from_ast(&self.body_ctx, trait_ref.clone())?; | ||
748 | Some(self.data().trait_refs.intern(trait_ref)) | ||
749 | } | ||
750 | |||
743 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { | 751 | fn lower_type_ref(&mut self, type_ref: &ast::Type) -> Idx<TypeRef> { |
744 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); | 752 | let tyref = TypeRef::from_ast(&self.body_ctx, type_ref.clone()); |
745 | self.data().type_refs.intern(tyref) | 753 | self.data().type_refs.intern(tyref) |
746 | } | 754 | } |
755 | |||
747 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { | 756 | fn lower_type_ref_opt(&mut self, type_ref: Option<ast::Type>) -> Idx<TypeRef> { |
748 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { | 757 | match type_ref.map(|ty| self.lower_type_ref(&ty)) { |
749 | Some(it) => it, | 758 | Some(it) => it, |
diff --git a/crates/hir_def/src/type_ref.rs b/crates/hir_def/src/type_ref.rs index 049b2e462..4c24aae94 100644 --- a/crates/hir_def/src/type_ref.rs +++ b/crates/hir_def/src/type_ref.rs | |||
@@ -51,6 +51,23 @@ impl Rawness { | |||
51 | } | 51 | } |
52 | } | 52 | } |
53 | 53 | ||
54 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | ||
55 | pub struct TraitRef { | ||
56 | pub path: Path, | ||
57 | } | ||
58 | |||
59 | impl TraitRef { | ||
60 | /// Converts an `ast::PathType` to a `hir::TraitRef`. | ||
61 | pub(crate) fn from_ast(ctx: &LowerCtx, node: ast::Type) -> Option<Self> { | ||
62 | // FIXME: Use `Path::from_src` | ||
63 | match node { | ||
64 | ast::Type::PathType(path) => { | ||
65 | path.path().and_then(|it| ctx.lower_path(it)).map(|path| TraitRef { path }) | ||
66 | } | ||
67 | _ => None, | ||
68 | } | ||
69 | } | ||
70 | } | ||
54 | /// Compare ty::Ty | 71 | /// Compare ty::Ty |
55 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | 72 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
56 | pub enum TypeRef { | 73 | pub enum TypeRef { |
diff --git a/crates/hir_ty/src/diagnostics/match_check.rs b/crates/hir_ty/src/diagnostics/match_check.rs index 5a5cdcbf3..9cb472b51 100644 --- a/crates/hir_ty/src/diagnostics/match_check.rs +++ b/crates/hir_ty/src/diagnostics/match_check.rs | |||
@@ -539,7 +539,7 @@ impl Matrix { | |||
539 | if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { | 539 | if let Some(Pat::Or(pat_ids)) = row.get_head().map(|pat_id| pat_id.as_pat(cx)) { |
540 | // Or patterns are expanded here | 540 | // Or patterns are expanded here |
541 | for pat_id in pat_ids { | 541 | for pat_id in pat_ids { |
542 | self.0.push(PatStack::from_pattern(pat_id)); | 542 | self.0.push(row.replace_head_with([pat_id].iter())); |
543 | } | 543 | } |
544 | } else { | 544 | } else { |
545 | self.0.push(row); | 545 | self.0.push(row); |
@@ -1085,6 +1085,20 @@ fn main() { | |||
1085 | } | 1085 | } |
1086 | 1086 | ||
1087 | #[test] | 1087 | #[test] |
1088 | fn or_pattern_no_diagnostic() { | ||
1089 | check_diagnostics( | ||
1090 | r#" | ||
1091 | enum Either {A, B} | ||
1092 | |||
1093 | fn main() { | ||
1094 | match (Either::A, Either::B) { | ||
1095 | (Either::A | Either::B, _) => (), | ||
1096 | } | ||
1097 | }"#, | ||
1098 | ) | ||
1099 | } | ||
1100 | |||
1101 | #[test] | ||
1088 | fn mismatched_types() { | 1102 | fn mismatched_types() { |
1089 | // Match statements with arms that don't match the | 1103 | // Match statements with arms that don't match the |
1090 | // expression pattern do not fire this diagnostic. | 1104 | // expression pattern do not fire this diagnostic. |
@@ -1336,30 +1350,6 @@ fn bang(never: !) { | |||
1336 | } | 1350 | } |
1337 | 1351 | ||
1338 | #[test] | 1352 | #[test] |
1339 | fn or_pattern_panic() { | ||
1340 | check_diagnostics( | ||
1341 | r#" | ||
1342 | pub enum Category { Infinity, Zero } | ||
1343 | |||
1344 | fn panic(a: Category, b: Category) { | ||
1345 | match (a, b) { | ||
1346 | (Category::Zero | Category::Infinity, _) => (), | ||
1347 | (_, Category::Zero | Category::Infinity) => (), | ||
1348 | } | ||
1349 | |||
1350 | // FIXME: This is a false positive, but the code used to cause a panic in the match checker, | ||
1351 | // so this acts as a regression test for that. | ||
1352 | match (a, b) { | ||
1353 | //^^^^^^ Missing match arm | ||
1354 | (Category::Infinity, Category::Infinity) | (Category::Zero, Category::Zero) => (), | ||
1355 | (Category::Infinity | Category::Zero, _) => (), | ||
1356 | } | ||
1357 | } | ||
1358 | "#, | ||
1359 | ); | ||
1360 | } | ||
1361 | |||
1362 | #[test] | ||
1363 | fn unknown_type() { | 1353 | fn unknown_type() { |
1364 | check_diagnostics( | 1354 | check_diagnostics( |
1365 | r#" | 1355 | r#" |
diff --git a/crates/hir_ty/src/lower.rs b/crates/hir_ty/src/lower.rs index c87789d45..afbfa12d5 100644 --- a/crates/hir_ty/src/lower.rs +++ b/crates/hir_ty/src/lower.rs | |||
@@ -15,7 +15,7 @@ use hir_def::{ | |||
15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, | 15 | generics::{TypeParamProvenance, WherePredicate, WherePredicateTypeTarget}, |
16 | path::{GenericArg, Path, PathSegment, PathSegments}, | 16 | path::{GenericArg, Path, PathSegment, PathSegments}, |
17 | resolver::{HasResolver, Resolver, TypeNs}, | 17 | resolver::{HasResolver, Resolver, TypeNs}, |
18 | type_ref::{TypeBound, TypeRef}, | 18 | type_ref::{TraitRef as HirTraitRef, TypeBound, TypeRef}, |
19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, | 19 | AdtId, AssocContainerId, AssocItemId, ConstId, ConstParamId, EnumId, EnumVariantId, FunctionId, |
20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, | 20 | GenericDefId, HasModule, ImplId, LocalFieldId, Lookup, StaticId, StructId, TraitId, |
21 | TypeAliasId, TypeParamId, UnionId, VariantId, | 21 | TypeAliasId, TypeParamId, UnionId, VariantId, |
@@ -667,14 +667,10 @@ impl<'a> TyLoweringContext<'a> { | |||
667 | 667 | ||
668 | fn lower_trait_ref( | 668 | fn lower_trait_ref( |
669 | &self, | 669 | &self, |
670 | type_ref: &TypeRef, | 670 | trait_ref: &HirTraitRef, |
671 | explicit_self_ty: Option<Ty>, | 671 | explicit_self_ty: Option<Ty>, |
672 | ) -> Option<TraitRef> { | 672 | ) -> Option<TraitRef> { |
673 | let path = match type_ref { | 673 | self.lower_trait_ref_from_path(&trait_ref.path, explicit_self_ty) |
674 | TypeRef::Path(path) => path, | ||
675 | _ => return None, | ||
676 | }; | ||
677 | self.lower_trait_ref_from_path(path, explicit_self_ty) | ||
678 | } | 674 | } |
679 | 675 | ||
680 | fn trait_ref_substs_from_path( | 676 | fn trait_ref_substs_from_path( |
@@ -1253,7 +1249,7 @@ pub(crate) fn impl_self_ty_query(db: &dyn HirDatabase, impl_id: ImplId) -> Binde | |||
1253 | let generics = generics(db.upcast(), impl_id.into()); | 1249 | let generics = generics(db.upcast(), impl_id.into()); |
1254 | let ctx = | 1250 | let ctx = |
1255 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); | 1251 | TyLoweringContext::new(db, &resolver).with_type_param_mode(TypeParamLoweringMode::Variable); |
1256 | Binders::new(generics.len(), ctx.lower_ty(&impl_data.target_type)) | 1252 | Binders::new(generics.len(), ctx.lower_ty(&impl_data.self_ty)) |
1257 | } | 1253 | } |
1258 | 1254 | ||
1259 | pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { | 1255 | pub(crate) fn const_param_ty_query(db: &dyn HirDatabase, def: ConstParamId) -> Ty { |
diff --git a/crates/ide/src/doc_links.rs b/crates/ide/src/doc_links.rs index 99276168f..67e2e5a1c 100644 --- a/crates/ide/src/doc_links.rs +++ b/crates/ide/src/doc_links.rs | |||
@@ -237,7 +237,7 @@ fn get_doc_link(db: &RootDatabase, definition: Definition) -> Option<String> { | |||
237 | .and_then(|assoc| match assoc.container(db) { | 237 | .and_then(|assoc| match assoc.container(db) { |
238 | AssocItemContainer::Trait(t) => Some(t.into()), | 238 | AssocItemContainer::Trait(t) => Some(t.into()), |
239 | AssocItemContainer::Impl(impld) => { | 239 | AssocItemContainer::Impl(impld) => { |
240 | impld.target_ty(db).as_adt().map(|adt| adt.into()) | 240 | impld.self_ty(db).as_adt().map(|adt| adt.into()) |
241 | } | 241 | } |
242 | }) | 242 | }) |
243 | .unwrap_or_else(|| f.clone().into()), | 243 | .unwrap_or_else(|| f.clone().into()), |
diff --git a/crates/ide/src/hover.rs b/crates/ide/src/hover.rs index 02a1a5b37..7e35a1450 100644 --- a/crates/ide/src/hover.rs +++ b/crates/ide/src/hover.rs | |||
@@ -195,7 +195,7 @@ fn show_implementations_action(db: &RootDatabase, def: Definition) -> Option<Hov | |||
195 | let adt = match def { | 195 | let adt = match def { |
196 | Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action), | 196 | Definition::ModuleDef(ModuleDef::Trait(it)) => return it.try_to_nav(db).map(to_action), |
197 | Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it), | 197 | Definition::ModuleDef(ModuleDef::Adt(it)) => Some(it), |
198 | Definition::SelfType(it) => it.target_ty(db).as_adt(), | 198 | Definition::SelfType(it) => it.self_ty(db).as_adt(), |
199 | _ => None, | 199 | _ => None, |
200 | }?; | 200 | }?; |
201 | adt.try_to_nav(db).map(to_action) | 201 | adt.try_to_nav(db).map(to_action) |
@@ -318,7 +318,7 @@ fn definition_owner_name(db: &RootDatabase, def: &Definition) -> Option<String> | |||
318 | Definition::ModuleDef(md) => match md { | 318 | Definition::ModuleDef(md) => match md { |
319 | ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) { | 319 | ModuleDef::Function(f) => match f.as_assoc_item(db)?.container(db) { |
320 | AssocItemContainer::Trait(t) => Some(t.name(db)), | 320 | AssocItemContainer::Trait(t) => Some(t.name(db)), |
321 | AssocItemContainer::Impl(i) => i.target_ty(db).as_adt().map(|adt| adt.name(db)), | 321 | AssocItemContainer::Impl(i) => i.self_ty(db).as_adt().map(|adt| adt.name(db)), |
322 | }, | 322 | }, |
323 | ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)), | 323 | ModuleDef::Variant(e) => Some(e.parent_enum(db).name(db)), |
324 | _ => None, | 324 | _ => None, |
@@ -376,7 +376,7 @@ fn hover_for_definition( | |||
376 | }, | 376 | }, |
377 | Definition::Local(it) => hover_for_local(it, db), | 377 | Definition::Local(it) => hover_for_local(it, db), |
378 | Definition::SelfType(impl_def) => { | 378 | Definition::SelfType(impl_def) => { |
379 | impl_def.target_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path)) | 379 | impl_def.self_ty(db).as_adt().and_then(|adt| from_hir_fmt(db, adt, mod_path)) |
380 | } | 380 | } |
381 | Definition::GenericParam(it) => from_hir_fmt(db, it, None), | 381 | Definition::GenericParam(it) => from_hir_fmt(db, it, None), |
382 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), | 382 | Definition::Label(it) => Some(Markup::fenced_block(&it.name(db))), |
diff --git a/crates/ide/src/references/rename.rs b/crates/ide/src/references/rename.rs index 26d6dc9c9..98456967a 100644 --- a/crates/ide/src/references/rename.rs +++ b/crates/ide/src/references/rename.rs | |||
@@ -307,7 +307,7 @@ fn rename_to_self(sema: &Semantics<RootDatabase>, local: hir::Local) -> RenameRe | |||
307 | hir::AssocItemContainer::Impl(impl_) => impl_, | 307 | hir::AssocItemContainer::Impl(impl_) => impl_, |
308 | }; | 308 | }; |
309 | let first_param_ty = first_param.ty(); | 309 | let first_param_ty = first_param.ty(); |
310 | let impl_ty = impl_.target_ty(sema.db); | 310 | let impl_ty = impl_.self_ty(sema.db); |
311 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { | 311 | let (ty, self_param) = if impl_ty.remove_ref().is_some() { |
312 | // if the impl is a ref to the type we can just match the `&T` with self directly | 312 | // if the impl is a ref to the type we can just match the `&T` with self directly |
313 | (first_param_ty.clone(), "self") | 313 | (first_param_ty.clone(), "self") |
diff --git a/crates/ide/src/runnables.rs b/crates/ide/src/runnables.rs index 7e4c5a078..11bd385bb 100644 --- a/crates/ide/src/runnables.rs +++ b/crates/ide/src/runnables.rs | |||
@@ -298,7 +298,7 @@ fn module_def_doctest(sema: &Semantics<RootDatabase>, def: hir::ModuleDef) -> Op | |||
298 | // FIXME: this also looks very wrong | 298 | // FIXME: this also looks very wrong |
299 | if let Some(assoc_def) = assoc_def { | 299 | if let Some(assoc_def) = assoc_def { |
300 | if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) { | 300 | if let hir::AssocItemContainer::Impl(imp) = assoc_def.container(sema.db) { |
301 | let ty = imp.target_ty(sema.db); | 301 | let ty = imp.self_ty(sema.db); |
302 | if let Some(adt) = ty.as_adt() { | 302 | if let Some(adt) = ty.as_adt() { |
303 | let name = adt.name(sema.db); | 303 | let name = adt.name(sema.db); |
304 | let idx = path.rfind(':').map_or(0, |idx| idx + 1); | 304 | let idx = path.rfind(':').map_or(0, |idx| idx + 1); |
diff --git a/crates/ide/src/syntax_highlighting/highlight.rs b/crates/ide/src/syntax_highlighting/highlight.rs index b0cfdd8b7..5ccb84714 100644 --- a/crates/ide/src/syntax_highlighting/highlight.rs +++ b/crates/ide/src/syntax_highlighting/highlight.rs | |||
@@ -1,6 +1,6 @@ | |||
1 | //! Computes color for a single element. | 1 | //! Computes color for a single element. |
2 | 2 | ||
3 | use hir::{AsAssocItem, Semantics, VariantDef}; | 3 | use hir::{AsAssocItem, AssocItemContainer, Semantics, VariantDef}; |
4 | use ide_db::{ | 4 | use ide_db::{ |
5 | defs::{Definition, NameClass, NameRefClass}, | 5 | defs::{Definition, NameClass, NameRefClass}, |
6 | RootDatabase, SymbolKind, | 6 | RootDatabase, SymbolKind, |
@@ -275,12 +275,24 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
275 | hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module), | 275 | hir::ModuleDef::Module(_) => HlTag::Symbol(SymbolKind::Module), |
276 | hir::ModuleDef::Function(func) => { | 276 | hir::ModuleDef::Function(func) => { |
277 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); | 277 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Function)); |
278 | if func.as_assoc_item(db).is_some() { | 278 | if let Some(item) = func.as_assoc_item(db) { |
279 | h |= HlMod::Associated; | 279 | h |= HlMod::Associated; |
280 | if func.self_param(db).is_none() { | 280 | if func.self_param(db).is_none() { |
281 | h |= HlMod::Static | 281 | h |= HlMod::Static |
282 | } | 282 | } |
283 | |||
284 | match item.container(db) { | ||
285 | AssocItemContainer::Impl(i) => { | ||
286 | if i.trait_(db).is_some() { | ||
287 | h |= HlMod::Trait; | ||
288 | } | ||
289 | } | ||
290 | AssocItemContainer::Trait(_t) => { | ||
291 | h |= HlMod::Trait; | ||
292 | } | ||
293 | } | ||
283 | } | 294 | } |
295 | |||
284 | if func.is_unsafe(db) { | 296 | if func.is_unsafe(db) { |
285 | h |= HlMod::Unsafe; | 297 | h |= HlMod::Unsafe; |
286 | } | 298 | } |
@@ -292,9 +304,20 @@ fn highlight_def(db: &RootDatabase, def: Definition) -> Highlight { | |||
292 | hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant), | 304 | hir::ModuleDef::Variant(_) => HlTag::Symbol(SymbolKind::Variant), |
293 | hir::ModuleDef::Const(konst) => { | 305 | hir::ModuleDef::Const(konst) => { |
294 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); | 306 | let mut h = Highlight::new(HlTag::Symbol(SymbolKind::Const)); |
295 | if konst.as_assoc_item(db).is_some() { | 307 | if let Some(item) = konst.as_assoc_item(db) { |
296 | h |= HlMod::Associated | 308 | h |= HlMod::Associated; |
309 | match item.container(db) { | ||
310 | AssocItemContainer::Impl(i) => { | ||
311 | if i.trait_(db).is_some() { | ||
312 | h |= HlMod::Trait; | ||
313 | } | ||
314 | } | ||
315 | AssocItemContainer::Trait(_t) => { | ||
316 | h |= HlMod::Trait; | ||
317 | } | ||
318 | } | ||
297 | } | 319 | } |
320 | |||
298 | return h; | 321 | return h; |
299 | } | 322 | } |
300 | hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait), | 323 | hir::ModuleDef::Trait(_) => HlTag::Symbol(SymbolKind::Trait), |
@@ -362,6 +385,10 @@ fn highlight_method_call( | |||
362 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { | 385 | if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { |
363 | h |= HlMod::Unsafe; | 386 | h |= HlMod::Unsafe; |
364 | } | 387 | } |
388 | if func.as_assoc_item(sema.db).and_then(|it| it.containing_trait(sema.db)).is_some() { | ||
389 | h |= HlMod::Trait | ||
390 | } | ||
391 | |||
365 | if let Some(self_param) = func.self_param(sema.db) { | 392 | if let Some(self_param) = func.self_param(sema.db) { |
366 | match self_param.access(sema.db) { | 393 | match self_param.access(sema.db) { |
367 | hir::Access::Shared => (), | 394 | hir::Access::Shared => (), |
diff --git a/crates/ide/src/syntax_highlighting/tags.rs b/crates/ide/src/syntax_highlighting/tags.rs index 93db79b89..1cec991aa 100644 --- a/crates/ide/src/syntax_highlighting/tags.rs +++ b/crates/ide/src/syntax_highlighting/tags.rs | |||
@@ -58,6 +58,8 @@ pub enum HlMod { | |||
58 | Associated, | 58 | Associated, |
59 | /// Used for intra doc links in doc injection. | 59 | /// Used for intra doc links in doc injection. |
60 | IntraDocLink, | 60 | IntraDocLink, |
61 | /// Used for items in traits and trait impls. | ||
62 | Trait, | ||
61 | 63 | ||
62 | /// Keep this last! | 64 | /// Keep this last! |
63 | Unsafe, | 65 | Unsafe, |
@@ -158,6 +160,7 @@ impl HlMod { | |||
158 | HlMod::Callable, | 160 | HlMod::Callable, |
159 | HlMod::Static, | 161 | HlMod::Static, |
160 | HlMod::Associated, | 162 | HlMod::Associated, |
163 | HlMod::Trait, | ||
161 | HlMod::Unsafe, | 164 | HlMod::Unsafe, |
162 | ]; | 165 | ]; |
163 | 166 | ||
@@ -174,6 +177,7 @@ impl HlMod { | |||
174 | HlMod::IntraDocLink => "intra_doc_link", | 177 | HlMod::IntraDocLink => "intra_doc_link", |
175 | HlMod::Mutable => "mutable", | 178 | HlMod::Mutable => "mutable", |
176 | HlMod::Static => "static", | 179 | HlMod::Static => "static", |
180 | HlMod::Trait => "trait", | ||
177 | HlMod::Unsafe => "unsafe", | 181 | HlMod::Unsafe => "unsafe", |
178 | } | 182 | } |
179 | } | 183 | } |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html index 4635ea927..8cde3906c 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_assoc_functions.html | |||
@@ -47,12 +47,12 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
47 | <span class="brace">}</span> | 47 | <span class="brace">}</span> |
48 | 48 | ||
49 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> | 49 | <span class="keyword">trait</span> <span class="trait declaration">t</span> <span class="brace">{</span> |
50 | <span class="keyword">fn</span> <span class="function declaration static associated">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 50 | <span class="keyword">fn</span> <span class="function declaration static associated trait">t_is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
51 | <span class="keyword">fn</span> <span class="function declaration associated">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 51 | <span class="keyword">fn</span> <span class="function declaration associated trait">t_is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
52 | <span class="brace">}</span> | 52 | <span class="brace">}</span> |
53 | 53 | ||
54 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> | 54 | <span class="keyword">impl</span> <span class="trait">t</span> <span class="keyword">for</span> <span class="struct">foo</span> <span class="brace">{</span> |
55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 55 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration static associated trait">is_static</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
56 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 56 | <span class="keyword">pub</span> <span class="keyword">fn</span> <span class="function declaration associated trait">is_not_static</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
57 | <span class="brace">}</span> | 57 | <span class="brace">}</span> |
58 | </code></pre> \ No newline at end of file | 58 | </code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html index 9215ddd9e..7c6694a27 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_injection.html | |||
@@ -42,7 +42,7 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
42 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 42 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
43 | <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> | 43 | <span class="function">fixture</span><span class="parenthesis">(</span><span class="string_literal">r#"</span> |
44 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> | 44 | <span class="keyword">trait</span> <span class="trait declaration">Foo</span> <span class="brace">{</span> |
45 | <span class="keyword">fn</span> <span class="function declaration static associated">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 45 | <span class="keyword">fn</span> <span class="function declaration static associated trait">foo</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
46 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 46 | <span class="macro">println!</span><span class="parenthesis">(</span><span class="string_literal">"2 + 2 = {}"</span><span class="comma">,</span> <span class="numeric_literal">4</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
47 | <span class="brace">}</span> | 47 | <span class="brace">}</span> |
48 | <span class="brace">}</span><span class="string_literal">"#</span> | 48 | <span class="brace">}</span><span class="string_literal">"#</span> |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html index 6a6555208..72910421d 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_unsafe.html | |||
@@ -62,11 +62,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
62 | <span class="brace">}</span> | 62 | <span class="brace">}</span> |
63 | 63 | ||
64 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> | 64 | <span class="keyword">trait</span> <span class="trait declaration">DoTheAutoref</span> <span class="brace">{</span> |
65 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 65 | <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
66 | <span class="brace">}</span> | 66 | <span class="brace">}</span> |
67 | 67 | ||
68 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> | 68 | <span class="keyword">impl</span> <span class="trait">DoTheAutoref</span> <span class="keyword">for</span> <span class="builtin_type">u16</span> <span class="brace">{</span> |
69 | <span class="keyword">fn</span> <span class="function declaration associated">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> | 69 | <span class="keyword">fn</span> <span class="function declaration associated trait">calls_autoref</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="brace">{</span><span class="brace">}</span> |
70 | <span class="brace">}</span> | 70 | <span class="brace">}</span> |
71 | 71 | ||
72 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> | 72 | <span class="keyword">fn</span> <span class="function declaration">main</span><span class="parenthesis">(</span><span class="parenthesis">)</span> <span class="brace">{</span> |
@@ -96,6 +96,6 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
96 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span> | 96 | <span class="keyword">let</span> <span class="struct">Packed</span> <span class="brace">{</span> <span class="field">a</span><span class="colon">:</span> <span class="keyword unsafe">ref</span> <span class="variable declaration">_a</span> <span class="brace">}</span> <span class="operator">=</span> <span class="variable">packed</span><span class="semicolon">;</span> |
97 | 97 | ||
98 | <span class="comment">// unsafe auto ref of packed field</span> | 98 | <span class="comment">// unsafe auto ref of packed field</span> |
99 | <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> | 99 | <span class="variable">packed</span><span class="operator">.</span><span class="field">a</span><span class="operator">.</span><span class="function associated trait unsafe">calls_autoref</span><span class="parenthesis">(</span><span class="parenthesis">)</span><span class="semicolon">;</span> |
100 | <span class="brace">}</span> | 100 | <span class="brace">}</span> |
101 | <span class="brace">}</span></code></pre> \ No newline at end of file | 101 | <span class="brace">}</span></code></pre> \ No newline at end of file |
diff --git a/crates/ide/src/syntax_highlighting/test_data/highlighting.html b/crates/ide/src/syntax_highlighting/test_data/highlighting.html index 1eaa7b75b..973173254 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlighting.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlighting.html | |||
@@ -67,11 +67,11 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd | |||
67 | <span class="brace">}</span> | 67 | <span class="brace">}</span> |
68 | 68 | ||
69 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> | 69 | <span class="keyword">trait</span> <span class="trait declaration">Bar</span> <span class="brace">{</span> |
70 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="semicolon">;</span> | 70 | <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span><span class="semicolon">;</span> |
71 | <span class="brace">}</span> | 71 | <span class="brace">}</span> |
72 | 72 | ||
73 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> | 73 | <span class="keyword">impl</span> <span class="trait">Bar</span> <span class="keyword">for</span> <span class="struct">Foo</span> <span class="brace">{</span> |
74 | <span class="keyword">fn</span> <span class="function declaration associated">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> | 74 | <span class="keyword">fn</span> <span class="function declaration associated trait">bar</span><span class="parenthesis">(</span><span class="operator">&</span><span class="self_keyword declaration">self</span><span class="parenthesis">)</span> <span class="operator">-></span> <span class="builtin_type">i32</span> <span class="brace">{</span> |
75 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> | 75 | <span class="self_keyword">self</span><span class="operator">.</span><span class="field">x</span> |
76 | <span class="brace">}</span> | 76 | <span class="brace">}</span> |
77 | <span class="brace">}</span> | 77 | <span class="brace">}</span> |
diff --git a/crates/ide_assists/src/handlers/generate_default_from_new.rs b/crates/ide_assists/src/handlers/generate_default_from_new.rs index 81c54ba3e..dc14552d6 100644 --- a/crates/ide_assists/src/handlers/generate_default_from_new.rs +++ b/crates/ide_assists/src/handlers/generate_default_from_new.rs | |||
@@ -92,7 +92,7 @@ fn is_default_implemented(ctx: &AssistContext, impl_: &Impl) -> bool { | |||
92 | None => return false, | 92 | None => return false, |
93 | }; | 93 | }; |
94 | 94 | ||
95 | let ty = impl_def.target_ty(db); | 95 | let ty = impl_def.self_ty(db); |
96 | let krate = impl_def.module(db).krate(); | 96 | let krate = impl_def.module(db).krate(); |
97 | let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default(); | 97 | let default = FamousDefs(&ctx.sema, Some(krate)).core_default_Default(); |
98 | let default_trait = match default { | 98 | let default_trait = match default { |
diff --git a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs index b8834d283..910010a04 100644 --- a/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs +++ b/crates/ide_assists/src/handlers/generate_is_empty_from_len.rs | |||
@@ -91,7 +91,7 @@ fn get_impl_method( | |||
91 | 91 | ||
92 | let scope = ctx.sema.scope(impl_.syntax()); | 92 | let scope = ctx.sema.scope(impl_.syntax()); |
93 | let krate = impl_def.module(db).krate(); | 93 | let krate = impl_def.module(db).krate(); |
94 | let ty = impl_def.target_ty(db); | 94 | let ty = impl_def.self_ty(db); |
95 | let traits_in_scope = scope.traits_in_scope(); | 95 | let traits_in_scope = scope.traits_in_scope(); |
96 | ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) | 96 | ty.iterate_method_candidates(db, krate, &traits_in_scope, Some(fn_name), |_, func| Some(func)) |
97 | } | 97 | } |
diff --git a/crates/ide_assists/src/utils.rs b/crates/ide_assists/src/utils.rs index 5f630ec75..d67524937 100644 --- a/crates/ide_assists/src/utils.rs +++ b/crates/ide_assists/src/utils.rs | |||
@@ -338,11 +338,11 @@ pub(crate) fn find_struct_impl( | |||
338 | // (we currently use the wrong type parameter) | 338 | // (we currently use the wrong type parameter) |
339 | // also we wouldn't want to use e.g. `impl S<u32>` | 339 | // also we wouldn't want to use e.g. `impl S<u32>` |
340 | 340 | ||
341 | let same_ty = match blk.target_ty(db).as_adt() { | 341 | let same_ty = match blk.self_ty(db).as_adt() { |
342 | Some(def) => def == struct_def, | 342 | Some(def) => def == struct_def, |
343 | None => false, | 343 | None => false, |
344 | }; | 344 | }; |
345 | let not_trait_impl = blk.target_trait(db).is_none(); | 345 | let not_trait_impl = blk.trait_(db).is_none(); |
346 | 346 | ||
347 | if !(same_ty && not_trait_impl) { | 347 | if !(same_ty && not_trait_impl) { |
348 | None | 348 | None |
diff --git a/crates/ide_completion/src/completions.rs b/crates/ide_completion/src/completions.rs index 6d572a836..e2994eed4 100644 --- a/crates/ide_completion/src/completions.rs +++ b/crates/ide_completion/src/completions.rs | |||
@@ -220,7 +220,7 @@ fn complete_enum_variants( | |||
220 | }; | 220 | }; |
221 | 221 | ||
222 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { | 222 | if let Some(impl_) = ctx.impl_def.as_ref().and_then(|impl_| ctx.sema.to_def(impl_)) { |
223 | if impl_.target_ty(ctx.db) == *ty { | 223 | if impl_.self_ty(ctx.db) == *ty { |
224 | for &variant in &variants { | 224 | for &variant in &variants { |
225 | let self_path = hir::ModPath::from_segments( | 225 | let self_path = hir::ModPath::from_segments( |
226 | hir::PathKind::Plain, | 226 | hir::PathKind::Plain, |
diff --git a/crates/ide_completion/src/completions/pattern.rs b/crates/ide_completion/src/completions/pattern.rs index b06498e6d..808d7ff7e 100644 --- a/crates/ide_completion/src/completions/pattern.rs +++ b/crates/ide_completion/src/completions/pattern.rs | |||
@@ -40,7 +40,7 @@ pub(crate) fn complete_pattern(acc: &mut Completions, ctx: &CompletionContext) { | |||
40 | _ => false, | 40 | _ => false, |
41 | }, | 41 | }, |
42 | hir::ScopeDef::MacroDef(_) => true, | 42 | hir::ScopeDef::MacroDef(_) => true, |
43 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.target_ty(ctx.db).as_adt() { | 43 | hir::ScopeDef::ImplSelfType(impl_) => match impl_.self_ty(ctx.db).as_adt() { |
44 | Some(hir::Adt::Struct(strukt)) => { | 44 | Some(hir::Adt::Struct(strukt)) => { |
45 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); | 45 | acc.add_struct_pat(ctx, strukt, Some(name.clone())); |
46 | true | 46 | true |
diff --git a/crates/ide_completion/src/completions/qualified_path.rs b/crates/ide_completion/src/completions/qualified_path.rs index 105ff6013..1891eb5b3 100644 --- a/crates/ide_completion/src/completions/qualified_path.rs +++ b/crates/ide_completion/src/completions/qualified_path.rs | |||
@@ -117,7 +117,7 @@ pub(crate) fn complete_qualified_path(acc: &mut Completions, ctx: &CompletionCon | |||
117 | if let Some(krate) = ctx.krate { | 117 | if let Some(krate) = ctx.krate { |
118 | let ty = match resolution { | 118 | let ty = match resolution { |
119 | PathResolution::TypeParam(param) => param.ty(ctx.db), | 119 | PathResolution::TypeParam(param) => param.ty(ctx.db), |
120 | PathResolution::SelfType(impl_def) => impl_def.target_ty(ctx.db), | 120 | PathResolution::SelfType(impl_def) => impl_def.self_ty(ctx.db), |
121 | _ => return, | 121 | _ => return, |
122 | }; | 122 | }; |
123 | 123 | ||
diff --git a/crates/ide_db/src/helpers/import_assets.rs b/crates/ide_db/src/helpers/import_assets.rs index 3deb0d159..8ce648367 100644 --- a/crates/ide_db/src/helpers/import_assets.rs +++ b/crates/ide_db/src/helpers/import_assets.rs | |||
@@ -361,7 +361,7 @@ fn item_for_path_search(db: &RootDatabase, item: ItemInNs) -> Option<ItemInNs> { | |||
361 | Some(assoc_item) => match assoc_item.container(db) { | 361 | Some(assoc_item) => match assoc_item.container(db) { |
362 | AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)), | 362 | AssocItemContainer::Trait(trait_) => ItemInNs::from(ModuleDef::from(trait_)), |
363 | AssocItemContainer::Impl(impl_) => { | 363 | AssocItemContainer::Impl(impl_) => { |
364 | ItemInNs::from(ModuleDef::from(impl_.target_ty(db).as_adt()?)) | 364 | ItemInNs::from(ModuleDef::from(impl_.self_ty(db).as_adt()?)) |
365 | } | 365 | } |
366 | }, | 366 | }, |
367 | None => item, | 367 | None => item, |
diff --git a/crates/profile/src/google_cpu_profiler.rs b/crates/profile/src/google_cpu_profiler.rs index db865c65b..cae6caeaa 100644 --- a/crates/profile/src/google_cpu_profiler.rs +++ b/crates/profile/src/google_cpu_profiler.rs | |||
@@ -14,26 +14,31 @@ extern "C" { | |||
14 | fn ProfilerStop(); | 14 | fn ProfilerStop(); |
15 | } | 15 | } |
16 | 16 | ||
17 | static PROFILER_STATE: AtomicUsize = AtomicUsize::new(OFF); | ||
18 | const OFF: usize = 0; | 17 | const OFF: usize = 0; |
19 | const ON: usize = 1; | 18 | const ON: usize = 1; |
20 | const PENDING: usize = 2; | 19 | const PENDING: usize = 2; |
21 | 20 | ||
22 | pub fn start(path: &Path) { | 21 | fn transition(current: usize, new: usize) -> bool { |
23 | if PROFILER_STATE.compare_and_swap(OFF, PENDING, Ordering::SeqCst) != OFF { | 22 | static STATE: AtomicUsize = AtomicUsize::new(OFF); |
23 | |||
24 | STATE.compare_exchange(current, new, Ordering::SeqCst, Ordering::SeqCst).is_ok() | ||
25 | } | ||
26 | |||
27 | pub(crate) fn start(path: &Path) { | ||
28 | if !transition(OFF, PENDING) { | ||
24 | panic!("profiler already started"); | 29 | panic!("profiler already started"); |
25 | } | 30 | } |
26 | let path = CString::new(path.display().to_string()).unwrap(); | 31 | let path = CString::new(path.display().to_string()).unwrap(); |
27 | if unsafe { ProfilerStart(path.as_ptr()) } == 0 { | 32 | if unsafe { ProfilerStart(path.as_ptr()) } == 0 { |
28 | panic!("profiler failed to start") | 33 | panic!("profiler failed to start") |
29 | } | 34 | } |
30 | assert!(PROFILER_STATE.compare_and_swap(PENDING, ON, Ordering::SeqCst) == PENDING); | 35 | assert!(transition(PENDING, ON)); |
31 | } | 36 | } |
32 | 37 | ||
33 | pub fn stop() { | 38 | pub(crate) fn stop() { |
34 | if PROFILER_STATE.compare_and_swap(ON, PENDING, Ordering::SeqCst) != ON { | 39 | if !transition(ON, PENDING) { |
35 | panic!("profiler is not started") | 40 | panic!("profiler is not started") |
36 | } | 41 | } |
37 | unsafe { ProfilerStop() }; | 42 | unsafe { ProfilerStop() }; |
38 | assert!(PROFILER_STATE.compare_and_swap(PENDING, OFF, Ordering::SeqCst) == PENDING); | 43 | assert!(transition(PENDING, OFF)); |
39 | } | 44 | } |
diff --git a/crates/profile/src/lib.rs b/crates/profile/src/lib.rs index 9ca6341db..a31fb8f43 100644 --- a/crates/profile/src/lib.rs +++ b/crates/profile/src/lib.rs | |||
@@ -52,7 +52,7 @@ impl Drop for Scope { | |||
52 | /// Usage: | 52 | /// Usage: |
53 | /// 1. Install gpref_tools (https://github.com/gperftools/gperftools), probably packaged with your Linux distro. | 53 | /// 1. Install gpref_tools (https://github.com/gperftools/gperftools), probably packaged with your Linux distro. |
54 | /// 2. Build with `cpu_profiler` feature. | 54 | /// 2. Build with `cpu_profiler` feature. |
55 | /// 3. Tun the code, the *raw* output would be in the `./out.profile` file. | 55 | /// 3. Run the code, the *raw* output would be in the `./out.profile` file. |
56 | /// 4. Install pprof for visualization (https://github.com/google/pprof). | 56 | /// 4. Install pprof for visualization (https://github.com/google/pprof). |
57 | /// 5. Bump sampling frequency to once per ms: `export CPUPROFILE_FREQUENCY=1000` | 57 | /// 5. Bump sampling frequency to once per ms: `export CPUPROFILE_FREQUENCY=1000` |
58 | /// 6. Use something like `pprof -svg target/release/rust-analyzer ./out.profile` to see the results. | 58 | /// 6. Use something like `pprof -svg target/release/rust-analyzer ./out.profile` to see the results. |
@@ -60,8 +60,17 @@ impl Drop for Scope { | |||
60 | /// For example, here's how I run profiling on NixOS: | 60 | /// For example, here's how I run profiling on NixOS: |
61 | /// | 61 | /// |
62 | /// ```bash | 62 | /// ```bash |
63 | /// $ nix-shell -p gperftools --run \ | 63 | /// $ bat -p shell.nix |
64 | /// 'cargo run --release -p rust-analyzer -- parse < ~/projects/rustbench/parser.rs > /dev/null' | 64 | /// with import <nixpkgs> {}; |
65 | /// mkShell { | ||
66 | /// buildInputs = [ gperftools ]; | ||
67 | /// shellHook = '' | ||
68 | /// export LD_LIBRARY_PATH="${gperftools}/lib:" | ||
69 | /// ''; | ||
70 | /// } | ||
71 | /// $ set -x CPUPROFILE_FREQUENCY 1000 | ||
72 | /// $ nix-shell --run 'cargo test --release --package rust-analyzer --lib -- benchmarks::benchmark_integrated_highlighting --exact --nocapture' | ||
73 | /// $ pprof -svg target/release/deps/rust_analyzer-8739592dc93d63cb crates/rust-analyzer/out.profile > profile.svg | ||
65 | /// ``` | 74 | /// ``` |
66 | /// | 75 | /// |
67 | /// See this diff for how to profile completions: | 76 | /// See this diff for how to profile completions: |
@@ -81,7 +90,9 @@ pub fn cpu_span() -> CpuSpan { | |||
81 | 90 | ||
82 | #[cfg(not(feature = "cpu_profiler"))] | 91 | #[cfg(not(feature = "cpu_profiler"))] |
83 | { | 92 | { |
84 | eprintln!("cpu_profiler feature is disabled") | 93 | eprintln!( |
94 | r#"cpu profiling is disabled, uncomment `default = [ "cpu_profiler" ]` in Cargo.toml to enable."# | ||
95 | ) | ||
85 | } | 96 | } |
86 | 97 | ||
87 | CpuSpan { _private: () } | 98 | CpuSpan { _private: () } |
@@ -91,7 +102,23 @@ impl Drop for CpuSpan { | |||
91 | fn drop(&mut self) { | 102 | fn drop(&mut self) { |
92 | #[cfg(feature = "cpu_profiler")] | 103 | #[cfg(feature = "cpu_profiler")] |
93 | { | 104 | { |
94 | google_cpu_profiler::stop() | 105 | google_cpu_profiler::stop(); |
106 | let profile_data = std::env::current_dir().unwrap().join("out.profile"); | ||
107 | eprintln!("Profile data saved to:\n\n {}\n", profile_data.display()); | ||
108 | let mut cmd = std::process::Command::new("pprof"); | ||
109 | cmd.arg("-svg").arg(std::env::current_exe().unwrap()).arg(&profile_data); | ||
110 | let out = cmd.output(); | ||
111 | |||
112 | match out { | ||
113 | Ok(out) if out.status.success() => { | ||
114 | let svg = profile_data.with_extension("svg"); | ||
115 | std::fs::write(&svg, &out.stdout).unwrap(); | ||
116 | eprintln!("Profile rendered to:\n\n {}\n", svg.display()); | ||
117 | } | ||
118 | _ => { | ||
119 | eprintln!("Failed to run:\n\n {:?}\n", cmd); | ||
120 | } | ||
121 | } | ||
95 | } | 122 | } |
96 | } | 123 | } |
97 | } | 124 | } |
diff --git a/crates/rust-analyzer/src/benchmarks.rs b/crates/rust-analyzer/src/benchmarks.rs index a6f997af8..bf569b40b 100644 --- a/crates/rust-analyzer/src/benchmarks.rs +++ b/crates/rust-analyzer/src/benchmarks.rs | |||
@@ -51,6 +51,7 @@ fn benchmark_integrated_highlighting() { | |||
51 | } | 51 | } |
52 | 52 | ||
53 | profile::init_from("*>100"); | 53 | profile::init_from("*>100"); |
54 | // let _s = profile::heartbeat_span(); | ||
54 | 55 | ||
55 | { | 56 | { |
56 | let _it = stdx::timeit("change"); | 57 | let _it = stdx::timeit("change"); |
@@ -63,6 +64,7 @@ fn benchmark_integrated_highlighting() { | |||
63 | 64 | ||
64 | { | 65 | { |
65 | let _it = stdx::timeit("after change"); | 66 | let _it = stdx::timeit("after change"); |
67 | let _span = profile::cpu_span(); | ||
66 | let analysis = host.analysis(); | 68 | let analysis = host.analysis(); |
67 | analysis.highlight_as_html(file_id, false).unwrap(); | 69 | analysis.highlight_as_html(file_id, false).unwrap(); |
68 | } | 70 | } |
diff --git a/crates/rust-analyzer/src/semantic_tokens.rs b/crates/rust-analyzer/src/semantic_tokens.rs index a3c5e9ccf..2dc8a42f1 100644 --- a/crates/rust-analyzer/src/semantic_tokens.rs +++ b/crates/rust-analyzer/src/semantic_tokens.rs | |||
@@ -88,6 +88,7 @@ define_semantic_token_modifiers![ | |||
88 | (CONSUMING, "consuming"), | 88 | (CONSUMING, "consuming"), |
89 | (UNSAFE, "unsafe"), | 89 | (UNSAFE, "unsafe"), |
90 | (ATTRIBUTE_MODIFIER, "attribute"), | 90 | (ATTRIBUTE_MODIFIER, "attribute"), |
91 | (TRAIT_MODIFIER, "trait"), | ||
91 | (CALLABLE, "callable"), | 92 | (CALLABLE, "callable"), |
92 | (INTRA_DOC_LINK, "intraDocLink"), | 93 | (INTRA_DOC_LINK, "intraDocLink"), |
93 | ]; | 94 | ]; |
diff --git a/crates/rust-analyzer/src/to_proto.rs b/crates/rust-analyzer/src/to_proto.rs index e297a72e6..c3820944b 100644 --- a/crates/rust-analyzer/src/to_proto.rs +++ b/crates/rust-analyzer/src/to_proto.rs | |||
@@ -474,6 +474,7 @@ fn semantic_token_type_and_modifiers( | |||
474 | HlMod::Callable => semantic_tokens::CALLABLE, | 474 | HlMod::Callable => semantic_tokens::CALLABLE, |
475 | HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, | 475 | HlMod::Static => lsp_types::SemanticTokenModifier::STATIC, |
476 | HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, | 476 | HlMod::IntraDocLink => semantic_tokens::INTRA_DOC_LINK, |
477 | HlMod::Trait => semantic_tokens::TRAIT_MODIFIER, | ||
477 | HlMod::Associated => continue, | 478 | HlMod::Associated => continue, |
478 | }; | 479 | }; |
479 | mods |= modifier; | 480 | mods |= modifier; |