mirror of
https://github.com/rust-lang/rust-analyzer
synced 2024-11-15 09:27:27 +00:00
Merge #5817
5817: Better API factoring around self access modes
r=matklad a=matklad
bors r+
🤖
Co-authored-by: Aleksey Kladov <aleksey.kladov@gmail.com>
This commit is contained in:
commit
a4b7ce94ba
4 changed files with 30 additions and 56 deletions
|
@ -12,6 +12,7 @@ use hir_def::{
|
||||||
docs::Documentation,
|
docs::Documentation,
|
||||||
expr::{BindingAnnotation, Pat, PatId},
|
expr::{BindingAnnotation, Pat, PatId},
|
||||||
import_map,
|
import_map,
|
||||||
|
lang_item::LangItemTarget,
|
||||||
path::ModPath,
|
path::ModPath,
|
||||||
per_ns::PerNs,
|
per_ns::PerNs,
|
||||||
resolver::{HasResolver, Resolver},
|
resolver::{HasResolver, Resolver},
|
||||||
|
@ -36,7 +37,7 @@ use rustc_hash::FxHashSet;
|
||||||
use stdx::impl_from;
|
use stdx::impl_from;
|
||||||
use syntax::{
|
use syntax::{
|
||||||
ast::{self, AttrsOwner, NameOwner},
|
ast::{self, AttrsOwner, NameOwner},
|
||||||
AstNode,
|
AstNode, SmolStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -1287,6 +1288,15 @@ impl Type {
|
||||||
db.trait_solve(self.krate, goal).is_some()
|
db.trait_solve(self.krate, goal).is_some()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn is_copy(&self, db: &dyn HirDatabase) -> bool {
|
||||||
|
let lang_item = db.lang_item(self.krate, SmolStr::new("copy"));
|
||||||
|
let copy_trait = match lang_item {
|
||||||
|
Some(LangItemTarget::TraitId(it)) => it,
|
||||||
|
_ => return false,
|
||||||
|
};
|
||||||
|
self.impls_trait(db, copy_trait.into(), &[])
|
||||||
|
}
|
||||||
|
|
||||||
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
pub fn as_callable(&self, db: &dyn HirDatabase) -> Option<Callable> {
|
||||||
let def = match self.ty.value {
|
let def = match self.ty.value {
|
||||||
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
|
Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def),
|
||||||
|
|
|
@ -38,7 +38,7 @@ pub use crate::{
|
||||||
ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
|
ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility,
|
||||||
},
|
},
|
||||||
has_source::HasSource,
|
has_source::HasSource,
|
||||||
semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope},
|
semantics::{original_range, PathResolution, Semantics, SemanticsScope},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub use hir_def::{
|
pub use hir_def::{
|
||||||
|
|
|
@ -6,10 +6,8 @@ use std::{cell::RefCell, fmt, iter::successors};
|
||||||
|
|
||||||
use base_db::{FileId, FileRange};
|
use base_db::{FileId, FileRange};
|
||||||
use hir_def::{
|
use hir_def::{
|
||||||
lang_item::LangItemTarget,
|
|
||||||
resolver::{self, HasResolver, Resolver, TypeNs},
|
resolver::{self, HasResolver, Resolver, TypeNs},
|
||||||
src::HasSource,
|
AsMacroCall, FunctionId, TraitId, VariantId,
|
||||||
AsMacroCall, FunctionId, Lookup, TraitId, VariantId,
|
|
||||||
};
|
};
|
||||||
use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
|
use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo};
|
||||||
use hir_ty::associated_type_shorthand_candidates;
|
use hir_ty::associated_type_shorthand_candidates;
|
||||||
|
@ -17,7 +15,7 @@ use itertools::Itertools;
|
||||||
use rustc_hash::{FxHashMap, FxHashSet};
|
use rustc_hash::{FxHashMap, FxHashSet};
|
||||||
use syntax::{
|
use syntax::{
|
||||||
algo::{find_node_at_offset, skip_trivia_token},
|
algo::{find_node_at_offset, skip_trivia_token},
|
||||||
ast, AstNode, Direction, SmolStr, SyntaxNode, SyntaxToken, TextRange, TextSize,
|
ast, AstNode, Direction, SyntaxNode, SyntaxToken, TextRange, TextSize,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -81,13 +79,6 @@ impl PathResolution {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub enum SelfKind {
|
|
||||||
Shared,
|
|
||||||
Mutable,
|
|
||||||
Consuming,
|
|
||||||
Copied,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Primary API to get semantic information, like types, from syntax trees.
|
/// Primary API to get semantic information, like types, from syntax trees.
|
||||||
pub struct Semantics<'db, DB> {
|
pub struct Semantics<'db, DB> {
|
||||||
pub db: &'db DB,
|
pub db: &'db DB,
|
||||||
|
@ -197,10 +188,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
|
||||||
self.imp.type_of_self(param)
|
self.imp.type_of_self(param)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
|
|
||||||
self.imp.method_receiver_kind(call)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
|
pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<Function> {
|
||||||
self.imp.resolve_method_call(call).map(Function::from)
|
self.imp.resolve_method_call(call).map(Function::from)
|
||||||
}
|
}
|
||||||
|
@ -423,35 +410,6 @@ impl<'db> SemanticsImpl<'db> {
|
||||||
self.analyze(param.syntax()).type_of_self(self.db, ¶m)
|
self.analyze(param.syntax()).type_of_self(self.db, ¶m)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option<SelfKind> {
|
|
||||||
self.resolve_method_call(call).and_then(|func| {
|
|
||||||
let lookup = func.lookup(self.db.upcast());
|
|
||||||
let src = lookup.source(self.db.upcast());
|
|
||||||
let param_list = src.value.param_list()?;
|
|
||||||
let self_param = param_list.self_param()?;
|
|
||||||
if self_param.amp_token().is_some() {
|
|
||||||
return Some(if self_param.mut_token().is_some() {
|
|
||||||
SelfKind::Mutable
|
|
||||||
} else {
|
|
||||||
SelfKind::Shared
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let ty = self.type_of_expr(&call.expr()?)?;
|
|
||||||
let krate = Function::from(func).krate(self.db)?;
|
|
||||||
let lang_item = self.db.lang_item(krate.id, SmolStr::new("copy"));
|
|
||||||
let copy_trait = match lang_item? {
|
|
||||||
LangItemTarget::TraitId(copy_trait) => Trait::from(copy_trait),
|
|
||||||
_ => return None,
|
|
||||||
};
|
|
||||||
Some(if ty.impls_trait(self.db, copy_trait, &[]) {
|
|
||||||
SelfKind::Copied
|
|
||||||
} else {
|
|
||||||
SelfKind::Consuming
|
|
||||||
})
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
|
fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option<FunctionId> {
|
||||||
self.analyze(call.syntax()).resolve_method_call(self.db, call)
|
self.analyze(call.syntax()).resolve_method_call(self.db, call)
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,7 +4,7 @@ mod injection;
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests;
|
mod tests;
|
||||||
|
|
||||||
use hir::{Name, SelfKind, Semantics, VariantDef};
|
use hir::{Name, Semantics, VariantDef};
|
||||||
use ide_db::{
|
use ide_db::{
|
||||||
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass},
|
||||||
RootDatabase,
|
RootDatabase,
|
||||||
|
@ -720,15 +720,21 @@ fn highlight_method_call(
|
||||||
if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
|
if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) {
|
||||||
h |= HighlightModifier::Unsafe;
|
h |= HighlightModifier::Unsafe;
|
||||||
}
|
}
|
||||||
|
if let Some(self_param) = func.self_param(sema.db) {
|
||||||
sema.method_reciever_kind(&method_call)
|
match self_param.access(sema.db) {
|
||||||
.map(|self_kind| match self_kind {
|
hir::Access::Shared => (),
|
||||||
SelfKind::Shared => h,
|
hir::Access::Exclusive => h |= HighlightModifier::Mutable,
|
||||||
SelfKind::Mutable => h | HighlightModifier::Mutable,
|
hir::Access::Owned => {
|
||||||
SelfKind::Consuming => h | HighlightModifier::Consuming,
|
if let Some(receiver_ty) = method_call.expr().and_then(|it| sema.type_of_expr(&it))
|
||||||
SelfKind::Copied => h,
|
{
|
||||||
})
|
if !receiver_ty.is_copy(sema.db) {
|
||||||
.or_else(|| Some(h))
|
h |= HighlightModifier::Consuming
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(h)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn highlight_name(
|
fn highlight_name(
|
||||||
|
|
Loading…
Reference in a new issue