From 61754678fb4923738c91f2702bba6628230dff6e Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 19 Aug 2020 17:02:50 +0200 Subject: Better API factoring around self access modes --- crates/hir/src/code_model.rs | 12 ++++++++- crates/hir/src/lib.rs | 2 +- crates/hir/src/semantics.rs | 46 ++--------------------------------- crates/ide/src/syntax_highlighting.rs | 26 ++++++++++++-------- 4 files changed, 30 insertions(+), 56 deletions(-) diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 68ccedc60..3d92d0c0d 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -12,6 +12,7 @@ use hir_def::{ docs::Documentation, expr::{BindingAnnotation, Pat, PatId}, import_map, + lang_item::LangItemTarget, path::ModPath, per_ns::PerNs, resolver::{HasResolver, Resolver}, @@ -36,7 +37,7 @@ use rustc_hash::FxHashSet; use stdx::impl_from; use syntax::{ ast::{self, AttrsOwner, NameOwner}, - AstNode, + AstNode, SmolStr, }; use crate::{ @@ -1287,6 +1288,15 @@ impl Type { 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 { let def = match self.ty.value { Ty::Apply(ApplicationTy { ctor: TypeCtor::FnDef(def), parameters: _ }) => Some(def), diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 447e60698..78d8651cb 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -38,7 +38,7 @@ pub use crate::{ ScopeDef, Static, Struct, Trait, Type, TypeAlias, TypeParam, Union, VariantDef, Visibility, }, has_source::HasSource, - semantics::{original_range, PathResolution, SelfKind, Semantics, SemanticsScope}, + semantics::{original_range, PathResolution, Semantics, SemanticsScope}, }; pub use hir_def::{ diff --git a/crates/hir/src/semantics.rs b/crates/hir/src/semantics.rs index cabeaaf98..8c5f2ff98 100644 --- a/crates/hir/src/semantics.rs +++ b/crates/hir/src/semantics.rs @@ -6,10 +6,8 @@ use std::{cell::RefCell, fmt, iter::successors}; use base_db::{FileId, FileRange}; use hir_def::{ - lang_item::LangItemTarget, resolver::{self, HasResolver, Resolver, TypeNs}, - src::HasSource, - AsMacroCall, FunctionId, Lookup, TraitId, VariantId, + AsMacroCall, FunctionId, TraitId, VariantId, }; use hir_expand::{hygiene::Hygiene, name::AsName, ExpansionInfo}; use hir_ty::associated_type_shorthand_candidates; @@ -17,7 +15,7 @@ use itertools::Itertools; use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ 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::{ @@ -81,13 +79,6 @@ impl PathResolution { } } -pub enum SelfKind { - Shared, - Mutable, - Consuming, - Copied, -} - /// Primary API to get semantic information, like types, from syntax trees. pub struct Semantics<'db, DB> { pub db: &'db DB, @@ -197,10 +188,6 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> { self.imp.type_of_self(param) } - pub fn method_reciever_kind(&self, call: &ast::MethodCallExpr) -> Option { - self.imp.method_receiver_kind(call) - } - pub fn resolve_method_call(&self, call: &ast::MethodCallExpr) -> Option { 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) } - fn method_receiver_kind(&self, call: &ast::MethodCallExpr) -> Option { - 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 { self.analyze(call.syntax()).resolve_method_call(self.db, call) } diff --git a/crates/ide/src/syntax_highlighting.rs b/crates/ide/src/syntax_highlighting.rs index fc4f56550..5521fd2b1 100644 --- a/crates/ide/src/syntax_highlighting.rs +++ b/crates/ide/src/syntax_highlighting.rs @@ -4,7 +4,7 @@ mod injection; #[cfg(test)] mod tests; -use hir::{Name, SelfKind, Semantics, VariantDef}; +use hir::{Name, Semantics, VariantDef}; use ide_db::{ defs::{classify_name, classify_name_ref, Definition, NameClass, NameRefClass}, RootDatabase, @@ -720,15 +720,21 @@ fn highlight_method_call( if func.is_unsafe(sema.db) || sema.is_unsafe_method_call(&method_call) { h |= HighlightModifier::Unsafe; } - - sema.method_reciever_kind(&method_call) - .map(|self_kind| match self_kind { - SelfKind::Shared => h, - SelfKind::Mutable => h | HighlightModifier::Mutable, - SelfKind::Consuming => h | HighlightModifier::Consuming, - SelfKind::Copied => h, - }) - .or_else(|| Some(h)) + if let Some(self_param) = func.self_param(sema.db) { + match self_param.access(sema.db) { + hir::Access::Shared => (), + hir::Access::Exclusive => h |= HighlightModifier::Mutable, + hir::Access::Owned => { + if let Some(receiver_ty) = method_call.expr().and_then(|it| sema.type_of_expr(&it)) + { + if !receiver_ty.is_copy(sema.db) { + h |= HighlightModifier::Consuming + } + } + } + } + } + Some(h) } fn highlight_name( -- cgit v1.2.3