Introduce FunctionQualifier for hir::FunctionData
This commit is contained in:
parent
b9c172a977
commit
2bb8956a10
@ -844,7 +844,7 @@ impl Function {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
|
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) {
|
pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) {
|
||||||
|
@ -9,7 +9,7 @@ use crate::{
|
|||||||
attr::Attrs,
|
attr::Attrs,
|
||||||
body::Expander,
|
body::Expander,
|
||||||
db::DefDatabase,
|
db::DefDatabase,
|
||||||
item_tree::{AssocItem, ItemTreeId, ModItem},
|
item_tree::{AssocItem, FunctionQualifier, ItemTreeId, ModItem},
|
||||||
type_ref::{TypeBound, TypeRef},
|
type_ref::{TypeBound, TypeRef},
|
||||||
visibility::RawVisibility,
|
visibility::RawVisibility,
|
||||||
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
|
AssocContainerId, AssocItemId, ConstId, ConstLoc, FunctionId, FunctionLoc, HasModule, ImplId,
|
||||||
@ -26,9 +26,9 @@ pub struct FunctionData {
|
|||||||
/// can be called as a method.
|
/// can be called as a method.
|
||||||
pub has_self_param: bool,
|
pub has_self_param: bool,
|
||||||
pub has_body: bool,
|
pub has_body: bool,
|
||||||
pub is_unsafe: bool,
|
pub qualifier: FunctionQualifier,
|
||||||
|
pub is_in_extern_block: bool,
|
||||||
pub is_varargs: bool,
|
pub is_varargs: bool,
|
||||||
pub is_extern: bool,
|
|
||||||
pub visibility: RawVisibility,
|
pub visibility: RawVisibility,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,9 +46,9 @@ impl FunctionData {
|
|||||||
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
|
attrs: item_tree.attrs(db, krate, ModItem::from(loc.id.value).into()),
|
||||||
has_self_param: func.has_self_param,
|
has_self_param: func.has_self_param,
|
||||||
has_body: func.has_body,
|
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_varargs: func.is_varargs,
|
||||||
is_extern: func.is_extern,
|
|
||||||
visibility: item_tree[func.visibility].clone(),
|
visibility: item_tree[func.visibility].clone(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ use la_arena::{Arena, Idx, RawIdx};
|
|||||||
use profile::Count;
|
use profile::Count;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
use syntax::{ast, match_ast, SyntaxKind};
|
use syntax::{ast, match_ast, SmolStr, SyntaxKind};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
attr::{Attrs, RawAttrs},
|
attr::{Attrs, RawAttrs},
|
||||||
@ -551,16 +551,25 @@ pub struct Function {
|
|||||||
pub generic_params: GenericParamsId,
|
pub generic_params: GenericParamsId,
|
||||||
pub has_self_param: bool,
|
pub has_self_param: bool,
|
||||||
pub has_body: 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
|
/// Whether the function is located in an `extern` block (*not* whether it is an
|
||||||
/// `extern "abi" fn`).
|
/// `extern "abi" fn`).
|
||||||
pub is_extern: bool,
|
pub is_in_extern_block: bool,
|
||||||
pub params: Box<[Idx<TypeRef>]>,
|
pub params: Box<[Idx<TypeRef>]>,
|
||||||
pub is_varargs: bool,
|
pub is_varargs: bool,
|
||||||
pub ret_type: Idx<TypeRef>,
|
pub ret_type: Idx<TypeRef>,
|
||||||
pub ast_id: FileAstId<ast::Fn>,
|
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)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
pub struct Struct {
|
pub struct Struct {
|
||||||
pub name: Name,
|
pub name: Name,
|
||||||
|
@ -391,14 +391,33 @@ impl Ctx {
|
|||||||
let has_body = func.body().is_some();
|
let has_body = func.body().is_some();
|
||||||
|
|
||||||
let ast_id = self.source_ast_id_map.ast_id(func);
|
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 {
|
let mut res = Function {
|
||||||
name,
|
name,
|
||||||
visibility,
|
visibility,
|
||||||
generic_params: GenericParamsId::EMPTY,
|
generic_params: GenericParamsId::EMPTY,
|
||||||
has_self_param,
|
has_self_param,
|
||||||
has_body,
|
has_body,
|
||||||
is_unsafe: func.unsafe_token().is_some(),
|
qualifier,
|
||||||
is_extern: false,
|
is_in_extern_block: false,
|
||||||
params,
|
params,
|
||||||
is_varargs,
|
is_varargs,
|
||||||
ret_type,
|
ret_type,
|
||||||
@ -608,8 +627,8 @@ impl Ctx {
|
|||||||
ast::ExternItem::Fn(ast) => {
|
ast::ExternItem::Fn(ast) => {
|
||||||
let func_id = self.lower_function(&ast)?;
|
let func_id = self.lower_function(&ast)?;
|
||||||
let func = &mut self.data().functions[func_id.index];
|
let func = &mut self.data().functions[func_id.index];
|
||||||
func.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
|
func.qualifier.is_unsafe = is_intrinsic_fn_unsafe(&func.name);
|
||||||
func.is_extern = true;
|
func.is_in_extern_block = true;
|
||||||
func_id.into()
|
func_id.into()
|
||||||
}
|
}
|
||||||
ast::ExternItem::Static(ast) => {
|
ast::ExternItem::Static(ast) => {
|
||||||
|
@ -91,7 +91,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
|
|||||||
|
|
||||||
fn validate_func(&mut self, func: FunctionId) {
|
fn validate_func(&mut self, func: FunctionId) {
|
||||||
let data = self.db.function_data(func);
|
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);
|
cov_mark::hit!(extern_func_incorrect_case_ignored);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -32,7 +32,7 @@ impl<'a, 'b> UnsafeValidator<'a, 'b> {
|
|||||||
let def = self.owner.into();
|
let def = self.owner.into();
|
||||||
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
|
let unsafe_expressions = unsafe_expressions(db, self.infer.as_ref(), def);
|
||||||
let is_unsafe = match self.owner {
|
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,
|
DefWithBodyId::StaticId(_) | DefWithBodyId::ConstId(_) => false,
|
||||||
};
|
};
|
||||||
if is_unsafe
|
if is_unsafe
|
||||||
@ -86,7 +86,7 @@ fn walk_unsafe(
|
|||||||
match expr {
|
match expr {
|
||||||
&Expr::Call { callee, .. } => {
|
&Expr::Call { callee, .. } => {
|
||||||
if let Some(func) = infer[callee].as_fn_def(db) {
|
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 });
|
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -103,7 +103,7 @@ fn walk_unsafe(
|
|||||||
Expr::MethodCall { .. } => {
|
Expr::MethodCall { .. } => {
|
||||||
if infer
|
if infer
|
||||||
.method_resolution(current)
|
.method_resolution(current)
|
||||||
.map(|func| db.function_data(func).is_unsafe)
|
.map(|func| db.function_data(func).qualifier.is_unsafe)
|
||||||
.unwrap_or(false)
|
.unwrap_or(false)
|
||||||
{
|
{
|
||||||
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
|
unsafe_exprs.push(UnsafeExpr { expr: current, inside_unsafe_block });
|
||||||
|
Loading…
x
Reference in New Issue
Block a user