Move two attribute lints to be early pass (post expansion)
This commit is contained in:
parent
f0cf9969cb
commit
63d0ba9de9
@ -3,11 +3,11 @@
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{AttrStyle, Attribute};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
|
||||
// Separate each crate's features.
|
||||
pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
|
||||
pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
|
||||
if !in_external_macro(cx.sess(), attr.span)
|
||||
&& let AttrStyle::Outer = attr.style
|
||||
&& let Some(ident) = attr.ident()
|
||||
|
@ -2,12 +2,12 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::is_from_proc_macro;
|
||||
use rustc_ast::{MetaItemInner, MetaItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
use rustc_span::symbol::Symbol;
|
||||
|
||||
pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
|
||||
// Check if the reason is present
|
||||
if let Some(item) = items.last().and_then(MetaItemInner::meta_item)
|
||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||
|
@ -2,11 +2,11 @@
|
||||
use super::utils::extract_clippy_lint;
|
||||
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_lint::{EarlyContext, Level, LintContext};
|
||||
use rustc_span::symbol::Symbol;
|
||||
use rustc_span::{DUMMY_SP, sym};
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
|
||||
for lint in items {
|
||||
if let Some(lint_name) = extract_clippy_lint(lint) {
|
||||
if lint_name.as_str() == "restriction" && name != sym::allow {
|
||||
@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner])
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check_command_line(cx: &LateContext<'_>) {
|
||||
pub(super) fn check_command_line(cx: &EarlyContext<'_>) {
|
||||
for (name, level) in &cx.sess().opts.lint_opts {
|
||||
if name == "clippy::restriction" && *level > Level::Allow {
|
||||
span_lint_and_then(
|
||||
|
@ -1,11 +1,11 @@
|
||||
use super::DEPRECATED_SEMVER;
|
||||
use clippy_utils::diagnostics::span_lint;
|
||||
use rustc_ast::{LitKind, MetaItemLit};
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::Span;
|
||||
use semver::Version;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
|
||||
if let LitKind::Str(is, _) = lit.kind {
|
||||
if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
|
||||
return;
|
||||
|
@ -2,12 +2,12 @@
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::{Attribute, MetaItem};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::{Span, sym};
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
fn emit_if_duplicated(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
complete_path: String,
|
||||
@ -26,7 +26,7 @@ fn emit_if_duplicated(
|
||||
}
|
||||
|
||||
fn check_duplicated_attr(
|
||||
cx: &LateContext<'_>,
|
||||
cx: &EarlyContext<'_>,
|
||||
attr: &MetaItem,
|
||||
attr_paths: &mut FxHashMap<String, Span>,
|
||||
parent: &mut Vec<String>,
|
||||
@ -65,7 +65,7 @@ fn check_duplicated_attr(
|
||||
}
|
||||
}
|
||||
|
||||
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attr_paths = FxHashMap::default();
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -3,7 +3,7 @@
|
||||
use rustc_ast::{AttrKind, AttrStyle, Attribute};
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_data_structures::sync::Lrc;
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{SourceFile, Span, Symbol};
|
||||
|
||||
@ -32,7 +32,7 @@ fn from(value: &AttrKind) -> Self {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) {
|
||||
let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
|
||||
|
||||
@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute])
|
||||
}
|
||||
}
|
||||
|
||||
fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
|
||||
fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
||||
let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
|
||||
let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
|
||||
first.span.with_hi(last.span.hi())
|
||||
|
@ -14,8 +14,8 @@
|
||||
|
||||
use clippy_config::Conf;
|
||||
use clippy_config::msrvs::{self, Msrv};
|
||||
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind, self as ast};
|
||||
use rustc_hir::{ImplItem, Item, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
@ -414,15 +414,7 @@ pub struct Attributes {
|
||||
}
|
||||
|
||||
impl_lint_pass!(Attributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
INLINE_ALWAYS,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl Attributes {
|
||||
@ -434,53 +426,11 @@ pub fn new(conf: &'static Conf) -> Self {
|
||||
}
|
||||
|
||||
impl<'tcx> LateLintPass<'tcx> for Attributes {
|
||||
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
|
||||
let attrs = cx.tcx.hir().attrs(item.hir_id());
|
||||
if is_relevant_item(cx, item) {
|
||||
inline_always::check(cx, item.span, item.ident.name, attrs);
|
||||
}
|
||||
match item.kind {
|
||||
ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
|
||||
_ => {},
|
||||
}
|
||||
mixed_attributes_style::check(cx, item.span, attrs);
|
||||
duplicated_attributes::check(cx, attrs);
|
||||
}
|
||||
|
||||
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
|
||||
@ -526,3 +476,77 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
||||
pub struct PostExpansionEarlyAttributes {
|
||||
msrv: Msrv,
|
||||
}
|
||||
|
||||
impl PostExpansionEarlyAttributes {
|
||||
pub fn new(conf: &'static Conf) -> Self {
|
||||
Self {
|
||||
msrv: conf.msrv.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl_lint_pass!(PostExpansionEarlyAttributes => [
|
||||
ALLOW_ATTRIBUTES,
|
||||
ALLOW_ATTRIBUTES_WITHOUT_REASON,
|
||||
DEPRECATED_SEMVER,
|
||||
USELESS_ATTRIBUTE,
|
||||
BLANKET_CLIPPY_RESTRICTION_LINTS,
|
||||
SHOULD_PANIC_WITHOUT_EXPECT,
|
||||
MIXED_ATTRIBUTES_STYLE,
|
||||
DUPLICATED_ATTRIBUTES,
|
||||
]);
|
||||
|
||||
impl EarlyLintPass for PostExpansionEarlyAttributes {
|
||||
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
|
||||
blanket_clippy_restriction_lints::check_command_line(cx);
|
||||
duplicated_attributes::check(cx, &krate.attrs);
|
||||
}
|
||||
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let Some(items) = &attr.meta_item_list() {
|
||||
if let Some(ident) = attr.ident() {
|
||||
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes::check(cx, attr);
|
||||
}
|
||||
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
|
||||
{
|
||||
allow_attributes_without_reason::check(cx, ident.name, items, attr);
|
||||
}
|
||||
if is_lint_level(ident.name, attr.id) {
|
||||
blanket_clippy_restriction_lints::check(cx, ident.name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
return;
|
||||
}
|
||||
for item in items {
|
||||
if let MetaItemInner::MetaItem(mi) = &item
|
||||
&& let MetaItemKind::NameValue(lit) = &mi.kind
|
||||
&& mi.has_name(sym::since)
|
||||
{
|
||||
deprecated_semver::check(cx, item.span(), lit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if attr.has_name(sym::should_panic) {
|
||||
should_panic_without_expect::check(cx, attr);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
|
||||
match item.kind {
|
||||
ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
mixed_attributes_style::check(cx, item.span, &item.attrs);
|
||||
duplicated_attributes::check(cx, &item.attrs);
|
||||
}
|
||||
|
||||
extract_msrv_attr!(EarlyContext);
|
||||
}
|
||||
|
@ -4,12 +4,12 @@
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::LateContext;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
|
||||
if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
@ -1,15 +1,15 @@
|
||||
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
|
||||
use super::{Attribute, USELESS_ATTRIBUTE};
|
||||
use super::USELESS_ATTRIBUTE;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Item, ItemKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_ast::{Item, ItemKind, Attribute};
|
||||
use rustc_lint::{EarlyContext, LintContext};
|
||||
use rustc_middle::lint::in_external_macro;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
|
||||
|
||||
for attr in attrs {
|
||||
|
@ -412,6 +412,8 @@
|
||||
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
|
||||
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
|
||||
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
|
||||
|
||||
store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -21,7 +21,7 @@
|
||||
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
|
||||
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
|
||||
};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_lint::{LateContext, LintContext, EarlyContext};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::symbol::{Ident, kw};
|
||||
@ -429,11 +429,12 @@ fn span(&self) -> Span {
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
|
||||
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
|
||||
|
||||
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
|
||||
|
||||
impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
|
||||
type Context = LateContext<'cx>;
|
||||
|
||||
|
@ -19,13 +19,5 @@ error: #[allow] attribute found
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
||||
error: #[allow] attribute found
|
||||
--> tests/ui/allow_attributes.rs:52:7
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^ help: replace it with: `expect`
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -43,14 +43,5 @@ LL | #[allow(unused)]
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
|
||||
error: `allow` attribute without specifying a reason
|
||||
--> tests/ui/allow_attributes_without_reason.rs:46:5
|
||||
|
|
||||
LL | #[allow(unused)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: try adding a reason at the end with `, reason = ".."`
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
@ -1,12 +1,3 @@
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: the since field must contain a semver-compliant version
|
||||
--> tests/ui/attrs.rs:27:14
|
||||
|
|
||||
@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version
|
||||
LL | #[deprecated(since = "1")]
|
||||
| ^^^^^^^^^^^
|
||||
|
||||
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
|
||||
--> tests/ui/attrs.rs:5:1
|
||||
|
|
||||
LL | #[inline(always)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: `-D clippy::inline-always` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
@ -1,3 +1,10 @@
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:6:9
|
||||
|
|
||||
@ -5,8 +12,6 @@ LL | #![warn(clippy::restriction)]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
--> tests/ui/blanket_clippy_restriction_lints.rs:8:9
|
||||
@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)]
|
||||
|
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: `clippy::restriction` is not meant to be enabled as a group
|
||||
|
|
||||
= note: because of the command line `--warn clippy::restriction`
|
||||
= help: enable the restriction lints you need individually
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user