Skip to content

Commit 1d6c938

Browse files
committed
allow Keys::<T>::remove() in replace_neuron()
1 parent abd5522 commit 1d6c938

File tree

3 files changed

+63
-11
lines changed

3 files changed

+63
-11
lines changed

pallets/subtensor/src/subnets/uids.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ impl<T: Config> Pallet<T> {
2929
// 2. Remove previous set memberships.
3030
Uids::<T>::remove(netuid, old_hotkey.clone());
3131
IsNetworkMember::<T>::remove(old_hotkey.clone(), netuid);
32+
#[allow(unknown_lints)]
3233
Keys::<T>::remove(netuid, uid_to_replace);
3334

3435
// 2a. Check if the uid is registered in any other subnetworks.

support/linting/src/forbid_keys_remove.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use super::*;
22
use syn::{
33
punctuated::Punctuated, spanned::Spanned, token::Comma, visit::Visit, Expr, ExprCall, ExprPath,
4-
File,
4+
File, Path,
55
};
66

77
pub struct ForbidKeysRemoveCall;
@@ -26,25 +26,30 @@ struct KeysRemoveVisitor {
2626

2727
impl<'ast> Visit<'ast> for KeysRemoveVisitor {
2828
fn visit_expr_call(&mut self, node: &'ast syn::ExprCall) {
29-
let ExprCall { func, args, .. } = node;
30-
if is_keys_remove_call(func, args) {
29+
let ExprCall {
30+
func, args, attrs, ..
31+
} = node;
32+
33+
if is_keys_remove_call(func, args) && !is_allowed(attrs) {
3134
let msg = "Keys::<T>::remove()` is banned to prevent accidentally breaking \
32-
the neuron sequence. If you need to replace neuron, try `SubtensorModule::replace_neuron()`";
35+
the neuron sequence. If you need to replace neurons, try `SubtensorModule::replace_neuron()`";
3336
self.errors.push(syn::Error::new(node.func.span(), msg));
3437
}
3538
}
3639
}
3740

3841
fn is_keys_remove_call(func: &Expr, args: &Punctuated<Expr, Comma>) -> bool {
39-
let Expr::Path(ExprPath { path, .. }) = func else {
42+
let Expr::Path(ExprPath {
43+
path: Path { segments: func, .. },
44+
..
45+
}) = func
46+
else {
4047
return false;
4148
};
42-
let func = &path.segments;
43-
if func.len() != 2 || args.len() != 2 {
44-
return false;
45-
}
4649

47-
func[0].ident == "Keys"
50+
func.len() == 2
51+
&& args.len() == 2
52+
&& func[0].ident == "Keys"
4853
&& !func[0].arguments.is_none()
4954
&& func[1].ident == "remove"
5055
&& func[1].arguments.is_none()
@@ -91,4 +96,23 @@ mod tests {
9196
let input = r#"ChildKeys::<T>::remove(netuid, uid_to_replace)"#;
9297
assert!(lint(input).is_ok());
9398
}
99+
100+
#[test]
101+
fn test_keys_remove_allowed() {
102+
let input = r#"
103+
#[allow(unknown_lints)]
104+
Keys::<T>::remove(netuid, uid_to_replace)
105+
"#;
106+
assert!(lint(input).is_ok());
107+
let input = r#"
108+
#[allow(unknown_lints)]
109+
Keys::<U>::remove(netuid, uid_to_replace)
110+
"#;
111+
assert!(lint(input).is_ok());
112+
let input = r#"
113+
#[allow(unknown_lints)]
114+
Keys::<U>::remove(1, "2".parse().unwrap(),)
115+
"#;
116+
assert!(lint(input).is_ok());
117+
}
94118
}

support/linting/src/lint.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
use syn::File;
1+
use proc_macro2::TokenTree;
2+
use syn::{Attribute, File, Meta, MetaList, Path};
23

34
pub type Result = core::result::Result<(), Vec<syn::Error>>;
45

@@ -11,3 +12,29 @@ pub trait Lint: Send + Sync {
1112
/// Lints the given Rust source file, returning a compile error if any issues are found.
1213
fn lint(source: &File) -> Result;
1314
}
15+
16+
pub fn is_allowed(attibutes: &[Attribute]) -> bool {
17+
attibutes.iter().any(|attribute| {
18+
let Attribute {
19+
meta:
20+
Meta::List(MetaList {
21+
path: Path { segments: attr, .. },
22+
tokens: attr_args,
23+
..
24+
}),
25+
..
26+
} = attribute
27+
else {
28+
return false;
29+
};
30+
31+
attr.len() == 1
32+
&& attr[0].ident == "allow"
33+
&& attr_args.clone().into_iter().any(|arg| {
34+
let TokenTree::Ident(ref id) = arg else {
35+
return false;
36+
};
37+
id == "unknown_lints"
38+
})
39+
})
40+
}

0 commit comments

Comments
 (0)