Skip to content

Commit 3047ae8

Browse files
Enable diagnostics in const and static items
1 parent 99e67f8 commit 3047ae8

File tree

2 files changed

+129
-75
lines changed

2 files changed

+129
-75
lines changed

crates/hir/src/lib.rs

+116-75
Original file line numberDiff line numberDiff line change
@@ -347,12 +347,36 @@ impl ModuleDef {
347347
};
348348

349349
let mut acc = Vec::new();
350-
for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) {
351-
acc.push(diag.into())
350+
351+
match self.as_def_with_body() {
352+
Some(def) => {
353+
def.diagnostics(db, &mut acc);
354+
}
355+
None => {
356+
for diag in hir_ty::diagnostics::validate_module_item(db, module.id.krate(), id) {
357+
acc.push(diag.into())
358+
}
359+
}
352360
}
361+
353362
acc
354363
}
355364

365+
pub fn as_def_with_body(self) -> Option<DefWithBody> {
366+
match self {
367+
ModuleDef::Function(it) => Some(it.into()),
368+
ModuleDef::Const(it) => Some(it.into()),
369+
ModuleDef::Static(it) => Some(it.into()),
370+
371+
ModuleDef::Module(_)
372+
| ModuleDef::Adt(_)
373+
| ModuleDef::Variant(_)
374+
| ModuleDef::Trait(_)
375+
| ModuleDef::TypeAlias(_)
376+
| ModuleDef::BuiltinType(_) => None,
377+
}
378+
}
379+
356380
pub fn attrs(&self, db: &dyn HirDatabase) -> Option<AttrsWithOwner> {
357381
Some(match self {
358382
ModuleDef::Module(it) => it.attrs(db),
@@ -624,7 +648,6 @@ impl Module {
624648
}
625649
for decl in self.declarations(db) {
626650
match decl {
627-
ModuleDef::Function(f) => f.diagnostics(db, acc),
628651
ModuleDef::Module(m) => {
629652
// Only add diagnostics from inline modules
630653
if def_map[m.id.local_id].origin.is_inline() {
@@ -637,9 +660,13 @@ impl Module {
637660

638661
for impl_def in self.impl_defs(db) {
639662
for item in impl_def.items(db) {
640-
if let AssocItem::Function(f) = item {
641-
f.diagnostics(db, acc);
642-
}
663+
let def: DefWithBody = match item {
664+
AssocItem::Function(it) => it.into(),
665+
AssocItem::Const(it) => it.into(),
666+
AssocItem::TypeAlias(_) => continue,
667+
};
668+
669+
def.diagnostics(db, acc);
643670
}
644671
}
645672
}
@@ -999,76 +1026,20 @@ impl DefWithBody {
9991026
DefWithBody::Const(c) => c.name(db),
10001027
}
10011028
}
1002-
}
1003-
1004-
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1005-
pub struct Function {
1006-
pub(crate) id: FunctionId,
1007-
}
1008-
1009-
impl Function {
1010-
pub fn module(self, db: &dyn HirDatabase) -> Module {
1011-
self.id.lookup(db.upcast()).module(db.upcast()).into()
1012-
}
1013-
1014-
pub fn name(self, db: &dyn HirDatabase) -> Name {
1015-
db.function_data(self.id).name.clone()
1016-
}
10171029

1018-
/// Get this function's return type
1019-
pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
1020-
let resolver = self.id.resolver(db.upcast());
1021-
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
1022-
let ret_type = &db.function_data(self.id).ret_type;
1023-
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1024-
let ty = ctx.lower_ty(ret_type);
1025-
Type::new_with_resolver_inner(db, krate, &resolver, ty)
1026-
}
1027-
1028-
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1029-
if !db.function_data(self.id).has_self_param() {
1030-
return None;
1031-
}
1032-
Some(SelfParam { func: self.id })
1033-
}
1034-
1035-
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
1036-
let resolver = self.id.resolver(db.upcast());
1037-
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
1038-
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1039-
let environment = db.trait_environment(self.id.into());
1040-
db.function_data(self.id)
1041-
.params
1042-
.iter()
1043-
.enumerate()
1044-
.map(|(idx, type_ref)| {
1045-
let ty = Type { krate, env: environment.clone(), ty: ctx.lower_ty(type_ref) };
1046-
Param { func: self, ty, idx }
1047-
})
1048-
.collect()
1049-
}
1050-
1051-
pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
1052-
if self.self_param(db).is_none() {
1053-
return None;
1030+
/// Returns the type this def's body has to evaluate to.
1031+
pub fn body_type(self, db: &dyn HirDatabase) -> Type {
1032+
match self {
1033+
DefWithBody::Function(it) => it.ret_type(db),
1034+
DefWithBody::Static(it) => it.ty(db),
1035+
DefWithBody::Const(it) => it.ty(db),
10541036
}
1055-
let mut res = self.assoc_fn_params(db);
1056-
res.remove(0);
1057-
Some(res)
1058-
}
1059-
1060-
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
1061-
db.function_data(self.id).is_unsafe()
1062-
}
1063-
1064-
pub fn is_async(self, db: &dyn HirDatabase) -> bool {
1065-
db.function_data(self.id).is_async()
10661037
}
10671038

10681039
pub fn diagnostics(self, db: &dyn HirDatabase, acc: &mut Vec<AnyDiagnostic>) {
10691040
let krate = self.module(db).id.krate();
10701041

1071-
let source_map = db.body_with_source_map(self.id.into()).1;
1042+
let source_map = db.body_with_source_map(self.into()).1;
10721043
for diag in source_map.diagnostics() {
10731044
match diag {
10741045
BodyDiagnostic::InactiveCode { node, cfg, opts } => acc.push(
@@ -1096,8 +1067,8 @@ impl Function {
10961067
}
10971068
}
10981069

1099-
let infer = db.infer(self.id.into());
1100-
let source_map = Lazy::new(|| db.body_with_source_map(self.id.into()).1);
1070+
let infer = db.infer(self.into());
1071+
let source_map = Lazy::new(|| db.body_with_source_map(self.into()).1);
11011072
for d in &infer.diagnostics {
11021073
match d {
11031074
hir_ty::InferenceDiagnostic::NoSuchField { expr } => {
@@ -1113,7 +1084,7 @@ impl Function {
11131084
}
11141085
}
11151086

1116-
for expr in hir_ty::diagnostics::missing_unsafe(db, self.id.into()) {
1087+
for expr in hir_ty::diagnostics::missing_unsafe(db, self.into()) {
11171088
match source_map.expr_syntax(expr) {
11181089
Ok(expr) => acc.push(MissingUnsafe { expr }.into()),
11191090
Err(SyntheticSyntax) => {
@@ -1123,7 +1094,7 @@ impl Function {
11231094
}
11241095
}
11251096

1126-
for diagnostic in BodyValidationDiagnostic::collect(db, self.id.into()) {
1097+
for diagnostic in BodyValidationDiagnostic::collect(db, self.into()) {
11271098
match diagnostic {
11281099
BodyValidationDiagnostic::RecordMissingFields {
11291100
record,
@@ -1220,7 +1191,7 @@ impl Function {
12201191
MissingOkOrSomeInTailExpr {
12211192
expr,
12221193
required,
1223-
expected: self.ret_type(db),
1194+
expected: self.body_type(db),
12241195
}
12251196
.into(),
12261197
),
@@ -1260,10 +1231,80 @@ impl Function {
12601231
}
12611232
}
12621233

1263-
for diag in hir_ty::diagnostics::validate_module_item(db, krate, self.id.into()) {
1234+
let def: ModuleDef = match self {
1235+
DefWithBody::Function(it) => it.into(),
1236+
DefWithBody::Static(it) => it.into(),
1237+
DefWithBody::Const(it) => it.into(),
1238+
};
1239+
for diag in hir_ty::diagnostics::validate_module_item(db, krate, def.into()) {
12641240
acc.push(diag.into())
12651241
}
12661242
}
1243+
}
1244+
1245+
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
1246+
pub struct Function {
1247+
pub(crate) id: FunctionId,
1248+
}
1249+
1250+
impl Function {
1251+
pub fn module(self, db: &dyn HirDatabase) -> Module {
1252+
self.id.lookup(db.upcast()).module(db.upcast()).into()
1253+
}
1254+
1255+
pub fn name(self, db: &dyn HirDatabase) -> Name {
1256+
db.function_data(self.id).name.clone()
1257+
}
1258+
1259+
/// Get this function's return type
1260+
pub fn ret_type(self, db: &dyn HirDatabase) -> Type {
1261+
let resolver = self.id.resolver(db.upcast());
1262+
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
1263+
let ret_type = &db.function_data(self.id).ret_type;
1264+
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1265+
let ty = ctx.lower_ty(ret_type);
1266+
Type::new_with_resolver_inner(db, krate, &resolver, ty)
1267+
}
1268+
1269+
pub fn self_param(self, db: &dyn HirDatabase) -> Option<SelfParam> {
1270+
if !db.function_data(self.id).has_self_param() {
1271+
return None;
1272+
}
1273+
Some(SelfParam { func: self.id })
1274+
}
1275+
1276+
pub fn assoc_fn_params(self, db: &dyn HirDatabase) -> Vec<Param> {
1277+
let resolver = self.id.resolver(db.upcast());
1278+
let krate = self.id.lookup(db.upcast()).container.module(db.upcast()).krate();
1279+
let ctx = hir_ty::TyLoweringContext::new(db, &resolver);
1280+
let environment = db.trait_environment(self.id.into());
1281+
db.function_data(self.id)
1282+
.params
1283+
.iter()
1284+
.enumerate()
1285+
.map(|(idx, type_ref)| {
1286+
let ty = Type { krate, env: environment.clone(), ty: ctx.lower_ty(type_ref) };
1287+
Param { func: self, ty, idx }
1288+
})
1289+
.collect()
1290+
}
1291+
1292+
pub fn method_params(self, db: &dyn HirDatabase) -> Option<Vec<Param>> {
1293+
if self.self_param(db).is_none() {
1294+
return None;
1295+
}
1296+
let mut res = self.assoc_fn_params(db);
1297+
res.remove(0);
1298+
Some(res)
1299+
}
1300+
1301+
pub fn is_unsafe(self, db: &dyn HirDatabase) -> bool {
1302+
db.function_data(self.id).is_unsafe()
1303+
}
1304+
1305+
pub fn is_async(self, db: &dyn HirDatabase) -> bool {
1306+
db.function_data(self.id).is_async()
1307+
}
12671308

12681309
/// Whether this function declaration has a definition.
12691310
///

crates/ide_diagnostics/src/handlers/missing_ok_or_some_in_tail_expr.rs

+13
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,19 @@ fn div(x: i32, y: i32) -> MyResult<i32> {
175175
);
176176
}
177177

178+
#[test]
179+
fn test_in_const_and_static() {
180+
check_fix(
181+
r#"
182+
//- minicore: option, result
183+
static A: Option<()> = {($0)};
184+
"#,
185+
r#"
186+
static A: Option<()> = {Some(())};
187+
"#,
188+
)
189+
}
190+
178191
#[test]
179192
fn test_wrap_return_type_not_applicable_when_expr_type_does_not_match_ok_type() {
180193
check_diagnostics(

0 commit comments

Comments
 (0)