diff options
-rw-r--r-- | crates/hir/src/code_model.rs | 53 | ||||
-rw-r--r-- | crates/hir/src/lib.rs | 8 | ||||
-rw-r--r-- | crates/hir/src/semantics.rs | 12 | ||||
-rw-r--r-- | crates/ide/src/completion/complete_dot.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/completion/complete_trait_impl.rs | 2 | ||||
-rw-r--r-- | crates/ide/src/completion/presentation.rs | 4 | ||||
-rw-r--r-- | crates/ide/src/syntax_highlighting.rs | 20 | ||||
-rw-r--r-- | crates/ssr/src/matching.rs | 2 | ||||
-rw-r--r-- | crates/ssr/src/resolving.rs | 2 |
9 files changed, 62 insertions, 43 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 31d5276b0..3254f316b 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs | |||
@@ -666,23 +666,11 @@ impl Function { | |||
666 | db.function_data(self.id).name.clone() | 666 | db.function_data(self.id).name.clone() |
667 | } | 667 | } |
668 | 668 | ||
669 | pub fn has_self_param(self, db: &dyn HirDatabase) -> bool { | 669 | pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> { |
670 | db.function_data(self.id).has_self_param | 670 | if !db.function_data(self.id).has_self_param { |
671 | } | ||
672 | |||
673 | pub fn mutability_of_self_param(self, db: &dyn HirDatabase) -> Option<Mutability> { | ||
674 | let func_data = db.function_data(self.id); | ||
675 | if !func_data.has_self_param { | ||
676 | return None; | 671 | return None; |
677 | } | 672 | } |
678 | 673 | Some(SelfParam { func: self.id }) | |
679 | func_data.params.first().and_then(|param| { | ||
680 | if let TypeRef::Reference(_, mutability) = param { | ||
681 | Some(*mutability) | ||
682 | } else { | ||
683 | None | ||
684 | } | ||
685 | }) | ||
686 | } | 674 | } |
687 | 675 | ||
688 | pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { | 676 | pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> { |
@@ -698,6 +686,41 @@ impl Function { | |||
698 | } | 686 | } |
699 | } | 687 | } |
700 | 688 | ||
689 | // Note: logically, this belongs to `hir_ty`, but we are not using it there yet. | ||
690 | pub enum Access { | ||
691 | Shared, | ||
692 | Exclusive, | ||
693 | Owned, | ||
694 | } | ||
695 | |||
696 | impl From<Mutability> for Access { | ||
697 | fn from(mutability: Mutability) -> Access { | ||
698 | match mutability { | ||
699 | Mutability::Shared => Access::Shared, | ||
700 | Mutability::Mut => Access::Exclusive, | ||
701 | } | ||
702 | } | ||
703 | } | ||
704 | |||
705 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | ||
706 | pub struct SelfParam { | ||
707 | func: FunctionId, | ||
708 | } | ||
709 | |||
710 | impl SelfParam { | ||
711 | pub fn access(self, db: &dyn HirDatabase) -> Access { | ||
712 | let func_data = db.function_data(self.func); | ||
713 | func_data | ||
714 | .params | ||
715 | .first() | ||
716 | .map(|param| match *param { | ||
717 | TypeRef::Reference(_, mutability) => mutability.into(), | ||
718 | _ => Access::Owned, | ||
719 | }) | ||
720 | .unwrap_or(Access::Owned) | ||
721 | } | ||
722 | } | ||
723 | |||
701 | impl HasVisibility for Function { | 724 | impl HasVisibility for Function { |
702 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { | 725 | fn visibility(&self, db: &dyn HirDatabase) -> Visibility { |
703 | let function_data = db.function_data(self.id); | 726 | let function_data = db.function_data(self.id); |
diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index fc1c1ccd3..447e60698 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs | |||
@@ -32,10 +32,10 @@ mod has_source; | |||
32 | 32 | ||
33 | pub use crate::{ | 33 | pub use crate::{ |
34 | code_model::{ | 34 | code_model::{ |
35 | Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const, | 35 | Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, |
36 | Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function, | 36 | Const, Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, |
37 | GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef, | 37 | Function, GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, |
38 | Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, | 38 | ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, |
39 | }, | 39 | }, |
40 | has_source::HasSource, | 40 | has_source::HasSource, |
41 | semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope}, | 41 | semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope}, |
diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index 621ebcbe3..cabeaaf98 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs | |||
@@ -21,13 +21,13 @@ use syntax::{ | |||
21 | }; | 21 | }; |
22 | 22 | ||
23 | use crate::{ | 23 | use crate::{ |
24 | code_model::Access, | ||
24 | db::HirDatabase, | 25 | db::HirDatabase, |
25 | diagnostics::Diagnostic, | 26 | diagnostics::Diagnostic, |
26 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, | 27 | semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx}, |
27 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, | 28 | source_analyzer::{resolve_hir_path, SourceAnalyzer}, |
28 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, | 29 | AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef, |
29 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef, | 30 | Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef, |
30 | VariantDef, | ||
31 | }; | 31 | }; |
32 | 32 | ||
33 | #[derive(Debug, Clone, PartialEq, Eq)] | 33 | #[derive(Debug, Clone, PartialEq, Eq)] |
@@ -627,9 +627,11 @@ impl<'db> SemanticsImpl<'db> { | |||
627 | } | 627 | } |
628 | 628 | ||
629 | let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; | 629 | let func = self.resolve_method_call(&method_call_expr).map(Function::from)?; |
630 | let is_unsafe = func.has_self_param(self.db) | 630 | let res = match func.self_param(self.db)?.access(self.db) { |
631 | && matches!(func.params(self.db).first(), Some(TypeRef::Reference(..))); | 631 | Access::Shared | Access::Exclusive => true, |
632 | Some(is_unsafe) | 632 | Access::Owned => false, |
633 | }; | ||
634 | Some(res) | ||
633 | }) | 635 | }) |
634 | .unwrap_or(false) | 636 | .unwrap_or(false) |
635 | } | 637 | } |
diff --git a/crates/ide/src/completion/complete_dot.rs b/crates/ide/src/completion/complete_dot.rs index 532665285..5488db43f 100644 --- a/crates/ide/src/completion/complete_dot.rs +++ b/crates/ide/src/completion/complete_dot.rs | |||
@@ -48,7 +48,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T | |||
48 | let mut seen_methods = FxHashSet::default(); | 48 | let mut seen_methods = FxHashSet::default(); |
49 | let traits_in_scope = ctx.scope.traits_in_scope(); | 49 | let traits_in_scope = ctx.scope.traits_in_scope(); |
50 | receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { | 50 | receiver.iterate_method_candidates(ctx.db, krate, &traits_in_scope, None, |_ty, func| { |
51 | if func.has_self_param(ctx.db) | 51 | if func.self_param(ctx.db).is_some() |
52 | && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m)) | 52 | && ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m)) |
53 | && seen_methods.insert(func.name(ctx.db)) | 53 | && seen_methods.insert(func.name(ctx.db)) |
54 | { | 54 | { |
diff --git a/crates/ide/src/completion/complete_trait_impl.rs b/crates/ide/src/completion/complete_trait_impl.rs index d69b6b468..d0d3a9f34 100644 --- a/crates/ide/src/completion/complete_trait_impl.rs +++ b/crates/ide/src/completion/complete_trait_impl.rs | |||
@@ -136,7 +136,7 @@ fn add_function_impl( | |||
136 | .lookup_by(fn_name) | 136 | .lookup_by(fn_name) |
137 | .set_documentation(func.docs(ctx.db)); | 137 | .set_documentation(func.docs(ctx.db)); |
138 | 138 | ||
139 | let completion_kind = if func.has_self_param(ctx.db) { | 139 | let completion_kind = if func.self_param(ctx.db).is_some() { |
140 | CompletionItemKind::Method | 140 | CompletionItemKind::Method |
141 | } else { | 141 | } else { |
142 | CompletionItemKind::Function | 142 | CompletionItemKind::Function |
diff --git a/crates/ide/src/completion/presentation.rs b/crates/ide/src/completion/presentation.rs index e1b1ea4ce..a73f8ab0b 100644 --- a/crates/ide/src/completion/presentation.rs +++ b/crates/ide/src/completion/presentation.rs | |||
@@ -191,14 +191,12 @@ impl Completions { | |||
191 | func: hir::Function, | 191 | func: hir::Function, |
192 | local_name: Option<String>, | 192 | local_name: Option<String>, |
193 | ) { | 193 | ) { |
194 | let has_self_param = func.has_self_param(ctx.db); | ||
195 | |||
196 | let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); | 194 | let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string()); |
197 | let ast_node = func.source(ctx.db).value; | 195 | let ast_node = func.source(ctx.db).value; |
198 | 196 | ||
199 | let mut builder = | 197 | let mut builder = |
200 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) | 198 | CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.clone()) |
201 | .kind(if has_self_param { | 199 | .kind(if func.self_param(ctx.db).is_some() { |
202 | CompletionItemKind::Method | 200 | CompletionItemKind::Method |
203 | } else { | 201 | } else { |
204 | CompletionItemKind::Function | 202 | CompletionItemKind::Function |
diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index 9827c68af..fc4f56550 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs | |||
@@ -4,7 +4,7 @@ mod injection; | |||
4 | #[cfg(test)] | 4 | #[cfg(test)] |
5 | mod tests; | 5 | mod tests; |
6 | 6 | ||
7 | use hir::{Mutability, Name, SelfKind, Semantics, VariantDef}; | 7 | use hir::{Name, SelfKind, Semantics, VariantDef}; |
8 | use ide_db::{ | 8 | use ide_db::{ |
9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, | 9 | defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, |
10 | RootDatabase, | 10 | RootDatabase, |
@@ -761,17 +761,13 @@ fn highlight_name( | |||
761 | h |= HighlightModifier::Unsafe; | 761 | h |= HighlightModifier::Unsafe; |
762 | } | 762 | } |
763 | 763 | ||
764 | return if func.has_self_param(db) { | 764 | match func.self_param(db) { |
765 | match func.mutability_of_self_param(db) { | 765 | None => h, |
766 | Some(mutability) => match mutability { | 766 | Some(self_param) => match self_param.access(db) { |
767 | Mutability::Mut => h | HighlightModifier::Mutable, | 767 | hir::Access::Exclusive => h | HighlightModifier::Mutable, |
768 | Mutability::Shared => h, | 768 | hir::Access::Shared | hir::Access::Owned => h, |
769 | }, | 769 | }, |
770 | None => h, | 770 | } |
771 | } | ||
772 | } else { | ||
773 | h | ||
774 | }; | ||
775 | }); | 771 | }); |
776 | } | 772 | } |
777 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, | 773 | hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct, |
diff --git a/crates/ssr/src/matching.rs b/crates/ssr/src/matching.rs index 8bb5ced90..26968c474 100644 --- a/crates/ssr/src/matching.rs +++ b/crates/ssr/src/matching.rs | |||
@@ -545,7 +545,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> { | |||
545 | // If the function we're calling takes a self parameter, then we store additional | 545 | // If the function we're calling takes a self parameter, then we store additional |
546 | // information on the placeholder match about autoderef and autoref. This allows us to use | 546 | // information on the placeholder match about autoderef and autoref. This allows us to use |
547 | // the placeholder in a context where autoderef and autoref don't apply. | 547 | // the placeholder in a context where autoderef and autoref don't apply. |
548 | if code_resolved_function.has_self_param(self.sema.db) { | 548 | if code_resolved_function.self_param(self.sema.db).is_some() { |
549 | if let (Some(pattern_type), Some(expr)) = (&pattern_ufcs.qualifier_type, &code.expr()) { | 549 | if let (Some(pattern_type), Some(expr)) = (&pattern_ufcs.qualifier_type, &code.expr()) { |
550 | let deref_count = self.check_expr_type(pattern_type, expr)?; | 550 | let deref_count = self.check_expr_type(pattern_type, expr)?; |
551 | let pattern_receiver = pattern_args.next(); | 551 | let pattern_receiver = pattern_args.next(); |
diff --git a/crates/ssr/src/resolving.rs b/crates/ssr/src/resolving.rs index b932132d5..5d2cbec47 100644 --- a/crates/ssr/src/resolving.rs +++ b/crates/ssr/src/resolving.rs | |||
@@ -165,7 +165,7 @@ impl Resolver<'_, '_> { | |||
165 | fn ok_to_use_path_resolution(&self, resolution: &hir::PathResolution) -> bool { | 165 | fn ok_to_use_path_resolution(&self, resolution: &hir::PathResolution) -> bool { |
166 | match resolution { | 166 | match resolution { |
167 | hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) => { | 167 | hir::PathResolution::AssocItem(hir::AssocItem::Function(function)) => { |
168 | if function.has_self_param(self.resolution_scope.scope.db) { | 168 | if function.self_param(self.resolution_scope.scope.db).is_some() { |
169 | // If we don't use this path resolution, then we won't be able to match method | 169 | // If we don't use this path resolution, then we won't be able to match method |
170 | // calls. e.g. `Foo::bar($s)` should match `x.bar()`. | 170 | // calls. e.g. `Foo::bar($s)` should match `x.bar()`. |
171 | true | 171 | true |