Skip to content

Commit e8d266f

Browse files
bors[bot]matklad
andauthored
Merge #5814
5814: Add SelfParam to code_model r=matklad a=matklad bors r+ 🤖 Co-authored-by: Aleksey Kladov <[email protected]>
2 parents 422856d + b9b4693 commit e8d266f

File tree

9 files changed

+62
-43
lines changed

9 files changed

+62
-43
lines changed

crates/hir/src/code_model.rs

Lines changed: 38 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -666,23 +666,11 @@ impl Function {
666666
db.function_data(self.id).name.clone()
667667
}
668668

669-
pub fn has_self_param(self, db: &dyn HirDatabase) -> bool {
670-
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 {
669+
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
670+
if !db.function_data(self.id).has_self_param {
676671
return None;
677672
}
678-
679-
func_data.params.first().and_then(|param| {
680-
if let TypeRef::Reference(_, mutability) = param {
681-
Some(*mutability)
682-
} else {
683-
None
684-
}
685-
})
673+
Some(SelfParam { func: self.id })
686674
}
687675

688676
pub fn params(self, db: &dyn HirDatabase) -> Vec<TypeRef> {
@@ -698,6 +686,41 @@ impl Function {
698686
}
699687
}
700688

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+
701724
impl HasVisibility for Function {
702725
fn visibility(&self, db: &dyn HirDatabase) -> Visibility {
703726
let function_data = db.function_data(self.id);

crates/hir/src/lib.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,10 @@ mod has_source;
3232

3333
pub use crate::{
3434
code_model::{
35-
Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind, Const,
36-
Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource, Function,
37-
GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef, ScopeDef,
38-
Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
35+
Access, Adt, AsAssocItem, AssocItem, AssocItemContainer, AttrDef, Callable, CallableKind,
36+
Const, Crate, CrateDependency, DefWithBody, Docs, Enum, EnumVariant, Field, FieldSource,
37+
Function, GenericDef, HasAttrs, HasVisibility, ImplDef, Local, MacroDef, Module, ModuleDef,
38+
ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
3939
},
4040
has_source::HasSource,
4141
semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope},

crates/hir/src/semantics.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,13 @@ use syntax::{
2121
};
2222

2323
use crate::{
24+
code_model::Access,
2425
db::HirDatabase,
2526
diagnostics::Diagnostic,
2627
semantics::source_to_def::{ChildContainer, SourceToDefCache, SourceToDefCtx},
2728
source_analyzer::{resolve_hir_path, SourceAnalyzer},
2829
AssocItem, Callable, Crate, Field, Function, HirFileId, ImplDef, InFile, Local, MacroDef,
29-
Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, TypeRef,
30-
VariantDef,
30+
Module, ModuleDef, Name, Origin, Path, ScopeDef, Trait, Type, TypeAlias, TypeParam, VariantDef,
3131
};
3232

3333
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -627,9 +627,11 @@ impl<'db> SemanticsImpl<'db> {
627627
}
628628

629629
let func = self.resolve_method_call(&method_call_expr).map(Function::from)?;
630-
let is_unsafe = func.has_self_param(self.db)
631-
&& matches!(func.params(self.db).first(), Some(TypeRef::Reference(..)));
632-
Some(is_unsafe)
630+
let res = match func.self_param(self.db)?.access(self.db) {
631+
Access::Shared | Access::Exclusive => true,
632+
Access::Owned => false,
633+
};
634+
Some(res)
633635
})
634636
.unwrap_or(false)
635637
}

crates/ide/src/completion/complete_dot.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ fn complete_methods(acc: &mut Completions, ctx: &CompletionContext, receiver: &T
4848
let mut seen_methods = FxHashSet::default();
4949
let traits_in_scope = ctx.scope.traits_in_scope();
5050
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()
5252
&& ctx.scope.module().map_or(true, |m| func.is_visible_from(ctx.db, m))
5353
&& seen_methods.insert(func.name(ctx.db))
5454
{

crates/ide/src/completion/complete_trait_impl.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ fn add_function_impl(
136136
.lookup_by(fn_name)
137137
.set_documentation(func.docs(ctx.db));
138138

139-
let completion_kind = if func.has_self_param(ctx.db) {
139+
let completion_kind = if func.self_param(ctx.db).is_some() {
140140
CompletionItemKind::Method
141141
} else {
142142
CompletionItemKind::Function

crates/ide/src/completion/presentation.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -191,14 +191,12 @@ impl Completions {
191191
func: hir::Function,
192192
local_name: Option<String>,
193193
) {
194-
let has_self_param = func.has_self_param(ctx.db);
195-
196194
let name = local_name.unwrap_or_else(|| func.name(ctx.db).to_string());
197195
let ast_node = func.source(ctx.db).value;
198196

199197
let mut builder =
200198
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() {
202200
CompletionItemKind::Method
203201
} else {
204202
CompletionItemKind::Function

crates/ide/src/syntax_highlighting.rs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ mod injection;
44
#[cfg(test)]
55
mod tests;
66

7-
use hir::{Mutability, Name, SelfKind, Semantics, VariantDef};
7+
use hir::{Name, SelfKind, Semantics, VariantDef};
88
use ide_db::{
99
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
1010
RootDatabase,
@@ -761,17 +761,13 @@ fn highlight_name(
761761
h |= HighlightModifier::Unsafe;
762762
}
763763

764-
return if func.has_self_param(db) {
765-
match func.mutability_of_self_param(db) {
766-
Some(mutability) => match mutability {
767-
Mutability::Mut => h | HighlightModifier::Mutable,
768-
Mutability::Shared => h,
769-
},
770-
None => h,
771-
}
772-
} else {
773-
h
774-
};
764+
match func.self_param(db) {
765+
None => h,
766+
Some(self_param) => match self_param.access(db) {
767+
hir::Access::Exclusive => h | HighlightModifier::Mutable,
768+
hir::Access::Shared | hir::Access::Owned => h,
769+
},
770+
}
775771
});
776772
}
777773
hir::ModuleDef::Adt(hir::Adt::Struct(_)) => HighlightTag::Struct,

crates/ssr/src/matching.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -545,7 +545,7 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
545545
// If the function we're calling takes a self parameter, then we store additional
546546
// information on the placeholder match about autoderef and autoref. This allows us to use
547547
// 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() {
549549
if let (Some(pattern_type), Some(expr)) = (&pattern_ufcs.qualifier_type, &code.expr()) {
550550
let deref_count = self.check_expr_type(pattern_type, expr)?;
551551
let pattern_receiver = pattern_args.next();

crates/ssr/src/resolving.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -165,7 +165,7 @@ impl Resolver<'_, '_> {
165165
fn ok_to_use_path_resolution(&self, resolution: &hir::PathResolution) -> bool {
166166
match resolution {
167167
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() {
169169
// If we don't use this path resolution, then we won't be able to match method
170170
// calls. e.g. `Foo::bar($s)` should match `x.bar()`.
171171
true

0 commit comments

Comments
 (0)