Introduce FunctionQualifier for hir::FunctionData
This commit is contained in:
parent
b9c172a977
commit
2bb8956a10
@ -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) {
|
||||
|
@ -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(),
|
||||
})
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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) => {
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 });
|
||||
|
Loading…
Reference in New Issue
Block a user