aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir/src/code_model.rs53
-rw-r--r--crates/hir/src/lib.rs8
-rw-r--r--crates/hir/src/semantics.rs12
-rw-r--r--crates/ide/src/completion/complete_dot.rs2
-rw-r--r--crates/ide/src/completion/complete_trait_impl.rs2
-rw-r--r--crates/ide/src/completion/presentation.rs4
-rw-r--r--crates/ide/src/syntax_highlighting.rs20
-rw-r--r--crates/ssr/src/matching.rs2
-rw-r--r--crates/ssr/src/resolving.rs2
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.
690pub enum Access {
691 Shared,
692 Exclusive,
693 Owned,
694}
695
696impl 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)]
706pub struct SelfParam {
707 func: FunctionId,
708}
709
710impl 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
701impl HasVisibility for Function { 724impl 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
33pub use crate::{ 33pub 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
23use crate::{ 23use 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)]
5mod tests; 5mod tests;
6 6
7use hir::{Mutability, Name, SelfKind, Semantics, VariantDef}; 7use hir::{Name, SelfKind, Semantics, VariantDef};
8use ide_db::{ 8use 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