Introduce FunctionQualifier for hir::FunctionData

This commit is contained in:
oxalica 2021-03-14 18:00:11 +08:00
parent b9c172a977
commit 2bb8956a10
No known key found for this signature in database
GPG Key ID: CED392DE0C483D00
6 changed files with 45 additions and 17 deletions

View File

@ -844,7 +844,7 @@ pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
}
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) {

View File

@ -9,7 +9,7 @@
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 @@ pub(crate) fn fn_data_query(db: &dyn DefDatabase, func: FunctionId) -> Arc<Funct
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(),
})
}

View File

@ -24,7 +24,7 @@
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<TypeRef>]>,
pub is_varargs: bool,
pub ret_type: Idx<TypeRef>,
pub ast_id: FileAstId<ast::Fn>,
}
#[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<SmolStr>,
}
#[derive(Debug, Clone, Eq, PartialEq)]
pub struct Struct {
pub name: Name,

View File

@ -391,14 +391,33 @@ fn lower_function(&mut self, func: &ast::Fn) -> Option<FileItemTreeId<Function>>
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<SyntaxToken>?
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 @@ fn lower_extern_block(&mut self, block: &ast::ExternBlock) -> Vec<ModItem> {
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) => {

View File

@ -91,7 +91,7 @@ fn allowed(&self, id: AttrDefId, allow_name: &str) -> bool {
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;
}

View File

@ -32,7 +32,7 @@ pub(super) fn validate_body(&mut self, db: &dyn HirDatabase) {
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 });