Skip to content

Commit 9beed98

Browse files
bors[bot]lf-
andauthored
Merge #8432
8432: decl_check: consider outer scopes' allows r=jonas-schievink a=lf- Fix #8417. Also makes it less noisy about no_mangle annotated stuff the user can do nothing about. Note: this still is broken with bitfield! macros. A repro in an ignore test is included here. I believe this bug is elsewhere, and I don't think I can work around it here. I would like help filing the remaining bug, as it does actually affect users, but I don't know how to describe the behaviour (or even if it is unintended). Co-authored-by: Jade <software@lfcode.ca>
2 parents 03e0bf7 + 26d2653 commit 9beed98

File tree

3 files changed

+151
-15
lines changed

3 files changed

+151
-15
lines changed

crates/hir_def/src/lib.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,16 @@ impl_from!(
435435
for AttrDefId
436436
);
437437

438+
impl From<AssocContainerId> for AttrDefId {
439+
fn from(acid: AssocContainerId) -> Self {
440+
match acid {
441+
AssocContainerId::ModuleId(mid) => AttrDefId::ModuleId(mid),
442+
AssocContainerId::ImplId(iid) => AttrDefId::ImplId(iid),
443+
AssocContainerId::TraitId(tid) => AttrDefId::TraitId(tid),
444+
}
445+
}
446+
}
447+
438448
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
439449
pub enum VariantId {
440450
EnumVariantId(EnumVariantId),

crates/hir_ty/src/diagnostics/decl_check.rs

Lines changed: 140 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ use crate::{
3535
};
3636

3737
mod allow {
38+
pub(super) const BAD_STYLE: &str = "bad_style";
39+
pub(super) const NONSTANDARD_STYLE: &str = "nonstandard_style";
3840
pub(super) const NON_SNAKE_CASE: &str = "non_snake_case";
3941
pub(super) const NON_UPPER_CASE_GLOBAL: &str = "non_upper_case_globals";
4042
pub(super) const NON_CAMEL_CASE_TYPES: &str = "non_camel_case_types";
@@ -83,10 +85,39 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
8385
}
8486

8587
/// Checks whether not following the convention is allowed for this item.
86-
///
87-
/// Currently this method doesn't check parent attributes.
88-
fn allowed(&self, id: AttrDefId, allow_name: &str) -> bool {
89-
self.db.attrs(id).by_key("allow").tt_values().any(|tt| tt.to_string().contains(allow_name))
88+
fn allowed(&self, id: AttrDefId, allow_name: &str, recursing: bool) -> bool {
89+
let is_allowed = |def_id| {
90+
let attrs = self.db.attrs(def_id);
91+
// don't bug the user about directly no_mangle annotated stuff, they can't do anything about it
92+
(!recursing && attrs.by_key("no_mangle").exists())
93+
|| attrs.by_key("allow").tt_values().any(|tt| {
94+
let allows = tt.to_string();
95+
allows.contains(allow_name)
96+
|| allows.contains(allow::BAD_STYLE)
97+
|| allows.contains(allow::NONSTANDARD_STYLE)
98+
})
99+
};
100+
101+
is_allowed(id)
102+
// go upwards one step or give up
103+
|| match id {
104+
AttrDefId::ModuleId(m) => m.containing_module(self.db.upcast()).map(|v| v.into()),
105+
AttrDefId::FunctionId(f) => Some(f.lookup(self.db.upcast()).container.into()),
106+
AttrDefId::StaticId(sid) => Some(sid.lookup(self.db.upcast()).container.into()),
107+
AttrDefId::ConstId(cid) => Some(cid.lookup(self.db.upcast()).container.into()),
108+
AttrDefId::TraitId(tid) => Some(tid.lookup(self.db.upcast()).container.into()),
109+
AttrDefId::ImplId(iid) => Some(iid.lookup(self.db.upcast()).container.into()),
110+
// These warnings should not explore macro definitions at all
111+
AttrDefId::MacroDefId(_) => None,
112+
// Will never occur under an enum/struct/union/type alias
113+
AttrDefId::AdtId(_) => None,
114+
AttrDefId::FieldId(_) => None,
115+
AttrDefId::EnumVariantId(_) => None,
116+
AttrDefId::TypeAliasId(_) => None,
117+
AttrDefId::GenericParamId(_) => None,
118+
}
119+
.map(|mid| self.allowed(mid, allow_name, true))
120+
.unwrap_or(false)
90121
}
91122

92123
fn validate_func(&mut self, func: FunctionId) {
@@ -109,7 +140,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
109140
}
110141

111142
// Check whether non-snake case identifiers are allowed for this function.
112-
if self.allowed(func.into(), allow::NON_SNAKE_CASE) {
143+
if self.allowed(func.into(), allow::NON_SNAKE_CASE, false) {
113144
return;
114145
}
115146

@@ -328,8 +359,9 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
328359
fn validate_struct(&mut self, struct_id: StructId) {
329360
let data = self.db.struct_data(struct_id);
330361

331-
let non_camel_case_allowed = self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES);
332-
let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE);
362+
let non_camel_case_allowed =
363+
self.allowed(struct_id.into(), allow::NON_CAMEL_CASE_TYPES, false);
364+
let non_snake_case_allowed = self.allowed(struct_id.into(), allow::NON_SNAKE_CASE, false);
333365

334366
// Check the structure name.
335367
let struct_name = data.name.to_string();
@@ -461,7 +493,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
461493
let data = self.db.enum_data(enum_id);
462494

463495
// Check whether non-camel case names are allowed for this enum.
464-
if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES) {
496+
if self.allowed(enum_id.into(), allow::NON_CAMEL_CASE_TYPES, false) {
465497
return;
466498
}
467499

@@ -584,7 +616,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
584616
fn validate_const(&mut self, const_id: ConstId) {
585617
let data = self.db.const_data(const_id);
586618

587-
if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL) {
619+
if self.allowed(const_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
588620
return;
589621
}
590622

@@ -632,7 +664,7 @@ impl<'a, 'b> DeclValidator<'a, 'b> {
632664
return;
633665
}
634666

635-
if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL) {
667+
if self.allowed(static_id.into(), allow::NON_UPPER_CASE_GLOBAL, false) {
636668
return;
637669
}
638670

@@ -869,10 +901,31 @@ fn main() {
869901
r#"
870902
#[allow(non_snake_case)]
871903
fn NonSnakeCaseName(SOME_VAR: u8) -> u8{
904+
// cov_flags generated output from elsewhere in this file
905+
extern "C" {
906+
#[no_mangle]
907+
static lower_case: u8;
908+
}
909+
872910
let OtherVar = SOME_VAR + 1;
873911
OtherVar
874912
}
875913
914+
#[allow(nonstandard_style)]
915+
mod CheckNonstandardStyle {
916+
fn HiImABadFnName() {}
917+
}
918+
919+
#[allow(bad_style)]
920+
mod CheckBadStyle {
921+
fn HiImABadFnName() {}
922+
}
923+
924+
mod F {
925+
#![allow(non_snake_case)]
926+
fn CheckItWorksWithModAttr(BAD_NAME_HI: u8) {}
927+
}
928+
876929
#[allow(non_snake_case, non_camel_case_types)]
877930
pub struct some_type {
878931
SOME_FIELD: u8,
@@ -888,16 +941,89 @@ fn main() {
888941
);
889942
}
890943

944+
#[test]
945+
fn allow_attributes_crate_attr() {
946+
check_diagnostics(
947+
r#"
948+
#![allow(non_snake_case)]
949+
950+
mod F {
951+
fn CheckItWorksWithCrateAttr(BAD_NAME_HI: u8) {}
952+
}
953+
954+
"#,
955+
);
956+
}
957+
958+
#[test]
959+
#[ignore]
960+
fn bug_trait_inside_fn() {
961+
// FIXME:
962+
// This is broken, and in fact, should not even be looked at by this
963+
// lint in the first place. There's weird stuff going on in the
964+
// collection phase.
965+
// It's currently being brought in by:
966+
// * validate_func on `a` recursing into modules
967+
// * then it finds the trait and then the function while iterating
968+
// through modules
969+
// * then validate_func is called on Dirty
970+
// * ... which then proceeds to look at some unknown module taking no
971+
// attrs from either the impl or the fn a, and then finally to the root
972+
// module
973+
//
974+
// It should find the attribute on the trait, but it *doesn't even see
975+
// the trait* as far as I can tell.
976+
977+
check_diagnostics(
978+
r#"
979+
trait T { fn a(); }
980+
struct U {}
981+
impl T for U {
982+
fn a() {
983+
// this comes out of bitflags, mostly
984+
#[allow(non_snake_case)]
985+
trait __BitFlags {
986+
const HiImAlsoBad: u8 = 2;
987+
#[inline]
988+
fn Dirty(&self) -> bool {
989+
false
990+
}
991+
}
992+
993+
}
994+
}
995+
"#,
996+
);
997+
}
998+
999+
#[test]
1000+
#[ignore]
1001+
fn bug_traits_arent_checked() {
1002+
// FIXME: Traits and functions in traits aren't currently checked by
1003+
// r-a, even though rustc will complain about them.
1004+
check_diagnostics(
1005+
r#"
1006+
trait BAD_TRAIT {
1007+
// ^^^^^^^^^ Trait `BAD_TRAIT` should have CamelCase name, e.g. `BadTrait`
1008+
fn BAD_FUNCTION();
1009+
// ^^^^^^^^^^^^ Function `BAD_FUNCTION` should have snake_case name, e.g. `bad_function`
1010+
fn BadFunction();
1011+
// ^^^^^^^^^^^^ Function `BadFunction` should have snake_case name, e.g. `bad_function`
1012+
}
1013+
"#,
1014+
);
1015+
}
1016+
8911017
#[test]
8921018
fn ignores_extern_items() {
8931019
cov_mark::check!(extern_func_incorrect_case_ignored);
8941020
cov_mark::check!(extern_static_incorrect_case_ignored);
8951021
check_diagnostics(
8961022
r#"
897-
extern {
898-
fn NonSnakeCaseName(SOME_VAR: u8) -> u8;
899-
pub static SomeStatic: u8 = 10;
900-
}
1023+
extern {
1024+
fn NonSnakeCaseName(SOME_VAR: u8) -> u8;
1025+
pub static SomeStatic: u8 = 10;
1026+
}
9011027
"#,
9021028
);
9031029
}

docs/user/manual.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -541,7 +541,7 @@ include::./generated_assists.adoc[]
541541
== Diagnostics
542542

543543
While most errors and warnings provided by rust-analyzer come from the `cargo check` integration, there's a growing number of diagnostics implemented using rust-analyzer's own analysis.
544-
These diagnostics don't respect `#[allow]` or `#[deny]` attributes yet, but can be turned off using the `rust-analyzer.diagnostics.enable`, `rust-analyzer.diagnostics.enableExperimental` or `rust-analyzer.diagnostics.disabled` settings.
544+
Some of these diagnostics don't respect `\#[allow]` or `\#[deny]` attributes yet, but can be turned off using the `rust-analyzer.diagnostics.enable`, `rust-analyzer.diagnostics.enableExperimental` or `rust-analyzer.diagnostics.disabled` settings.
545545

546546
include::./generated_diagnostic.adoc[]
547547

0 commit comments

Comments
 (0)