From 2bb8956a102cb2efbea35e414a8214fba2efcaf6 Mon Sep 17 00:00:00 2001 From: oxalica Date: Sun, 14 Mar 2021 18:00:11 +0800 Subject: Introduce FunctionQualifier for hir::FunctionData --- crates/hir/src/lib.rs | 2 +- crates/hir_def/src/data.rs | 10 +++++----- crates/hir_def/src/item_tree.rs | 15 ++++++++++++--- crates/hir_def/src/item_tree/lower.rs | 27 +++++++++++++++++++++++---- crates/hir_ty/src/diagnostics/decl_check.rs | 2 +- crates/hir_ty/src/diagnostics/unsafe_check.rs | 6 +++--- 6 files changed, 45 insertions(+), 17 deletions(-) diff --git a/crates/hir/src/lib.rs b/crates/hir/src/lib.rs index 469ed5b5e..0d0e757fc 100644 --- a/crates/hir/src/lib.rs +++ b/crates/hir/src/lib.rs @@ -844,7 +844,7 @@ impl Function { } pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool { - db.function_data(self.id).is_unsafe + db.function_data(self.id).qualifier.is_unsafe } pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { diff --git a/crates/hir_def/src/data.rs b/crates/hir_def/src/data.rs index aea53d527..b09da0697 100644 --- a/crates/hir_def/src/data.rs +++ b/crates/hir_def/src/data.rs @@ -9,7 +9,7 @@ use crate::{ attr::Attrs, body::Expander, db::DefDatabase, - item_tree::{AssocItem, ItemTreeId, ModItem}, + item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem}, type_ref::{TypeBound, TypeRef}, visibility::RawVisibility, AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId, @@ -26,9 +26,9 @@ pub struct FunctionData { /// can be called as a method. pub has_self_param: bool, pub has_body: bool, - pub is_unsafe: bool, + pub qualifier: FunctionQualifier, + pub is_in_extern_block: bool, pub is_varargs: bool, - pub is_extern: bool, pub visibility: RawVisibility, } @@ -46,9 +46,9 @@ impl FunctionData { attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()), has_self_param: func.has_self_param, has_body: func.has_body, - is_unsafe: func.is_unsafe, + qualifier: func.qualifier.clone(), + is_in_extern_block: func.is_in_extern_block, is_varargs: func.is_varargs, - is_extern: func.is_extern, visibility: item_tree[func.visibility].clone(), }) } diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs index 09bcb10dc..d8f22d442 100644 --- a/crates/hir_def/src/item_tree.rs +++ b/crates/hir_def/src/item_tree.rs @@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx}; use profile::Count; use rustc_hash::FxHashMap; use smallvec::SmallVec; -use syntax::{ast, match_ast, SyntaxKind}; +use syntax::{ast, match_ast, SmolStr, SyntaxKind}; use crate::{ attr::{Attrs, RawAttrs}, @@ -551,16 +551,25 @@ pub struct Function { pub generic_params: GenericParamsId, pub has_self_param: bool, pub has_body: bool, - pub is_unsafe: bool, + pub qualifier: FunctionQualifier, /// Whether the function is located in an `extern` block (*not* whether it is an /// `extern "abi" fn`). - pub is_extern: bool, + pub is_in_extern_block: bool, pub params: Box<[Idx]>, pub is_varargs: bool, pub ret_type: Idx, pub ast_id: FileAstId, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct FunctionQualifier { + pub is_default: bool, + pub is_const: bool, + pub is_async: bool, + pub is_unsafe: bool, + pub abi: Option, +} + #[derive(Debug, Clone, Eq, PartialEq)] pub struct Struct { pub name: Name, diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs index 240fdacf9..6b5438dc9 100644 --- a/crates/hir_def/src/item_tree/lower.rs +++ b/crates/hir_def/src/item_tree/lower.rs @@ -391,14 +391,33 @@ impl Ctx { let has_body = func.body().is_some(); let ast_id = self.source_ast_id_map.ast_id(func); + let qualifier = FunctionQualifier { + is_default: func.default_token().is_some(), + is_const: func.const_token().is_some(), + is_async: func.async_token().is_some(), + is_unsafe: func.unsafe_token().is_some(), + abi: func.abi().map(|abi| { + // FIXME: Abi::abi() -> Option? + match abi.syntax().last_token() { + Some(tok) if tok.kind() == SyntaxKind::STRING => { + // FIXME: Better way to unescape? + tok.text().trim_matches('"').into() + } + _ => { + // `extern` default to be `extern "C"`. + "C".into() + } + } + }), + }; let mut res = Function { name, visibility, generic_params: GenericParamsId::EMPTY, has_self_param, has_body, - is_unsafe: func.unsafe_token().is_some(), - is_extern: false, + qualifier, + is_in_extern_block: false, params, is_varargs, ret_type, @@ -608,8 +627,8 @@ impl Ctx { ast::ExternItem::Fn(ast) => { let func_id = self.lower_function(&ast)?; let func = &mut self.data().functions[func_id.index]; - func.is_unsafe = is_intrinsic_fn_unsafe(&func.name); - func.is_extern = true; + func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name); + func.is_in_extern_block = true; func_id.into() } ast::ExternItem::Static(ast) => { diff --git a/crates/hir_ty/src/diagnostics/decl_check.rs b/crates/hir_ty/src/diagnostics/decl_check.rs index 3605ca581..982ad5b9e 100644 --- a/crates/hir_ty/src/diagnostics/decl_check.rs +++ b/crates/hir_ty/src/diagnostics/decl_check.rs @@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> { fn validate_func(&mut self, func: FunctionId) { let data = self.db.function_data(func); - if data.is_extern { + if data.is_in_extern_block { cov_mark::hit!(extern_func_incorrect_case_ignored); return; } diff --git a/crates/hir_ty/src/diagnostics/unsafe_check.rs b/crates/hir_ty/src/diagnostics/unsafe_check.rs index 20bb64827..44a7e5506 100644 --- a/crates/hir_ty/src/diagnostics/unsafe_check.rs +++ b/crates/hir_ty/src/diagnostics/unsafe_check.rs @@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> { let def = self.owner.into(); let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def); let is_unsafe = match self.owner { - DefWithBodyId::FunctionId(it) => db.function_data(it).is_unsafe, + DefWithBodyId::FunctionId(it) => db.function_data(it).qualifier.is_unsafe, DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false, }; if is_unsafe @@ -86,7 +86,7 @@ fn walk_unsafe( match expr { &Expr::Call { callee, .. } => { if let Some(func) = infer[callee].as_fn_def(db) { - if db.function_data(func).is_unsafe { + if db.function_data(func).qualifier.is_unsafe { unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); } } @@ -103,7 +103,7 @@ fn walk_unsafe( Expr::MethodCall { .. } => { if infer .method_resolution(current) - .map(|func| db.function_data(func).is_unsafe) + .map(|func| db.function_data(func).qualifier.is_unsafe) .unwrap_or(false) { unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block }); -- cgit v1.2.3