Do not run lints that cannot emit
Before this change, adding a lint was a difficult matter because it always had some overhead involved. This was because all lints would run, no matter their default level, or if the user had #![allow]ed them. This PR changes that
This commit is contained in:
parent
c926476d01
commit
b4da058595
@ -4029,6 +4029,7 @@ dependencies = [
|
|||||||
"rustc_hir",
|
"rustc_hir",
|
||||||
"rustc_hir_pretty",
|
"rustc_hir_pretty",
|
||||||
"rustc_index",
|
"rustc_index",
|
||||||
|
"rustc_lint_defs",
|
||||||
"rustc_macros",
|
"rustc_macros",
|
||||||
"rustc_query_system",
|
"rustc_query_system",
|
||||||
"rustc_serialize",
|
"rustc_serialize",
|
||||||
|
@ -223,7 +223,7 @@ pub fn span(&self) -> Span {
|
|||||||
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
|
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
pub fn meta_item_list(&self) -> Option<ThinVec<MetaItemInner>> {
|
||||||
match &self.args {
|
match &self.args {
|
||||||
AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
|
AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
|
||||||
MetaItemKind::list_from_tokens(args.tokens.clone())
|
MetaItemKind::list_from_tokens(args.tokens.clone())
|
||||||
|
@ -74,6 +74,12 @@
|
|||||||
fluent_generated as fluent,
|
fluent_generated as fluent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use std::default::Default;
|
||||||
|
use std::fmt::Write;
|
||||||
|
|
||||||
|
// hardwired lints from rustc_lint_defs
|
||||||
|
pub use rustc_session::lint::builtin::*;
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
/// The `while_true` lint detects `while true { }`.
|
/// The `while_true` lint detects `while true { }`.
|
||||||
///
|
///
|
||||||
@ -241,7 +247,8 @@ fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) {
|
|||||||
/// behavior.
|
/// behavior.
|
||||||
UNSAFE_CODE,
|
UNSAFE_CODE,
|
||||||
Allow,
|
Allow,
|
||||||
"usage of `unsafe` code and other potentially unsound constructs"
|
"usage of `unsafe` code and other potentially unsound constructs",
|
||||||
|
[loadbearing: true]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
|
declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
|
||||||
@ -389,6 +396,7 @@ fn check_fn(&mut self, cx: &EarlyContext<'_>, fk: FnKind<'_>, span: Span, _: ast
|
|||||||
report_in_external_macro
|
report_in_external_macro
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct MissingDoc;
|
pub struct MissingDoc;
|
||||||
|
|
||||||
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
|
impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
|
||||||
@ -819,8 +827,8 @@ pub struct DeprecatedAttr {
|
|||||||
|
|
||||||
impl_lint_pass!(DeprecatedAttr => []);
|
impl_lint_pass!(DeprecatedAttr => []);
|
||||||
|
|
||||||
impl DeprecatedAttr {
|
impl Default for DeprecatedAttr {
|
||||||
pub fn new() -> DeprecatedAttr {
|
fn default() -> Self {
|
||||||
DeprecatedAttr { depr_attrs: deprecated_attributes() }
|
DeprecatedAttr { depr_attrs: deprecated_attributes() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -312,6 +312,9 @@ impl LintPass for RuntimeCombinedEarlyLintPass<'_> {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
fn get_lints(&self) -> crate::LintVec {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_early_lint_pass {
|
macro_rules! impl_early_lint_pass {
|
||||||
|
@ -429,7 +429,8 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
|||||||
pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
|
pub rustc::UNTRANSLATABLE_DIAGNOSTIC,
|
||||||
Deny,
|
Deny,
|
||||||
"prevent creation of diagnostics which cannot be translated",
|
"prevent creation of diagnostics which cannot be translated",
|
||||||
report_in_external_macro: true
|
report_in_external_macro: true,
|
||||||
|
[loadbearing: true]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_tool_lint! {
|
declare_tool_lint! {
|
||||||
@ -442,7 +443,8 @@ fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) {
|
|||||||
pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
|
pub rustc::DIAGNOSTIC_OUTSIDE_OF_IMPL,
|
||||||
Deny,
|
Deny,
|
||||||
"prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
|
"prevent diagnostic creation outside of `Diagnostic`/`Subdiagnostic`/`LintDiagnostic` impls",
|
||||||
report_in_external_macro: true
|
report_in_external_macro: true,
|
||||||
|
[loadbearing: true]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
|
declare_lint_pass!(Diagnostics => [UNTRANSLATABLE_DIAGNOSTIC, DIAGNOSTIC_OUTSIDE_OF_IMPL]);
|
||||||
|
@ -326,6 +326,9 @@ impl LintPass for RuntimeCombinedLateLintPass<'_, '_> {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
fn get_lints(&self) -> crate::LintVec {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! impl_late_lint_pass {
|
macro_rules! impl_late_lint_pass {
|
||||||
@ -361,13 +364,38 @@ pub fn late_lint_mod<'tcx, T: LateLintPass<'tcx> + 'tcx>(
|
|||||||
// Note: `passes` is often empty. In that case, it's faster to run
|
// Note: `passes` is often empty. In that case, it's faster to run
|
||||||
// `builtin_lints` directly rather than bundling it up into the
|
// `builtin_lints` directly rather than bundling it up into the
|
||||||
// `RuntimeCombinedLateLintPass`.
|
// `RuntimeCombinedLateLintPass`.
|
||||||
let late_module_passes = &unerased_lint_store(tcx.sess).late_module_passes;
|
let store = unerased_lint_store(tcx.sess);
|
||||||
if late_module_passes.is_empty() {
|
|
||||||
|
if store.late_module_passes.is_empty() {
|
||||||
late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
|
late_lint_mod_inner(tcx, module_def_id, context, builtin_lints);
|
||||||
} else {
|
} else {
|
||||||
let mut passes: Vec<_> = late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
|
let passes: Vec<_> =
|
||||||
passes.push(Box::new(builtin_lints));
|
store.late_module_passes.iter().map(|mk_pass| (mk_pass)(tcx)).collect();
|
||||||
let pass = RuntimeCombinedLateLintPass { passes: &mut passes[..] };
|
|
||||||
|
// Filter unused lints
|
||||||
|
let (lints_to_emit, lints_allowed) = &**tcx.lints_that_can_emit(());
|
||||||
|
// let lints_to_emit = &lints_that_can_emit.0;
|
||||||
|
// let lints_allowed = &lints_that_can_emit.1;
|
||||||
|
|
||||||
|
// Now, we'll filtered passes in a way that discards any lint that won't trigger.
|
||||||
|
// If any lint is a given pass is detected to be emitted, we will keep that pass.
|
||||||
|
// Otherwise, we don't
|
||||||
|
let mut filtered_passes: Vec<Box<dyn LateLintPass<'tcx>>> = passes
|
||||||
|
.into_iter()
|
||||||
|
.filter(|pass| {
|
||||||
|
let pass = LintPass::get_lints(pass);
|
||||||
|
pass.iter().any(|&lint| {
|
||||||
|
let lint_name = name_without_tool(&lint.name.to_lowercase()).to_string();
|
||||||
|
lints_to_emit.contains(&lint_name)
|
||||||
|
|| (!lints_allowed.contains(&lint_name)
|
||||||
|
&& lint.default_level != crate::Level::Allow)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
filtered_passes.push(Box::new(builtin_lints));
|
||||||
|
|
||||||
|
let pass = RuntimeCombinedLateLintPass { passes: &mut filtered_passes[..] };
|
||||||
late_lint_mod_inner(tcx, module_def_id, context, pass);
|
late_lint_mod_inner(tcx, module_def_id, context, pass);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -454,3 +482,10 @@ pub fn check_crate<'tcx>(tcx: TyCtxt<'tcx>) {
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Format name ignoring the name, useful for filtering non-used lints.
|
||||||
|
/// For example, 'clippy::my_lint' will turn into 'my_lint'
|
||||||
|
pub(crate) fn name_without_tool(name: &str) -> &str {
|
||||||
|
// Doing some calculations here to account for those separators
|
||||||
|
name.rsplit("::").next().unwrap_or(name)
|
||||||
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::fx::FxIndexMap;
|
use rustc_data_structures::{fx::FxIndexMap, sync::Lrc};
|
||||||
use rustc_errors::{Diag, LintDiagnostic, MultiSpan};
|
use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
|
||||||
use rustc_feature::{Features, GateIssue};
|
use rustc_feature::{Features, GateIssue};
|
||||||
use rustc_hir::HirId;
|
use rustc_hir::HirId;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
use rustc_hir::intravisit::{self, Visitor};
|
||||||
@ -31,7 +31,7 @@
|
|||||||
OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
|
OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
|
||||||
};
|
};
|
||||||
use crate::fluent_generated as fluent;
|
use crate::fluent_generated as fluent;
|
||||||
use crate::late::unerased_lint_store;
|
use crate::late::{unerased_lint_store, name_without_tool};
|
||||||
use crate::lints::{
|
use crate::lints::{
|
||||||
DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified,
|
DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified,
|
||||||
OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint,
|
OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint,
|
||||||
@ -115,6 +115,36 @@ fn raw_lint_id_level(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Walk the whole crate collecting nodes where lint levels change
|
||||||
|
/// (e.g. `#[allow]` attributes), and joins that list with the warn-by-default
|
||||||
|
/// (and not allowed in the crate) and CLI lints. The returned value is a tuple
|
||||||
|
/// of 1. The lints that will emit (or at least, should run), and 2.
|
||||||
|
/// The lints that are allowed at the crate level and will not emit.
|
||||||
|
pub fn lints_that_can_emit(tcx: TyCtxt<'_>, (): ()) -> Lrc<(Vec<String>, Vec<String>)> {
|
||||||
|
let mut visitor = LintLevelMinimum::new(tcx);
|
||||||
|
visitor.process_opts();
|
||||||
|
tcx.hir().walk_attributes(&mut visitor);
|
||||||
|
|
||||||
|
let store = unerased_lint_store(&tcx.sess);
|
||||||
|
|
||||||
|
let lint_groups = store.get_lint_groups();
|
||||||
|
for group in lint_groups {
|
||||||
|
let binding = group.0.to_lowercase();
|
||||||
|
let group_name = name_without_tool(&binding).to_string();
|
||||||
|
if visitor.lints_to_emit.contains(&group_name) {
|
||||||
|
for lint in group.1 {
|
||||||
|
visitor.lints_to_emit.push(name_without_tool(&lint.to_string()).to_string());
|
||||||
|
}
|
||||||
|
} else if visitor.lints_allowed.contains(&group_name) {
|
||||||
|
for lint in &group.1 {
|
||||||
|
visitor.lints_allowed.push(name_without_tool(&lint.to_string()).to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Lrc::new((visitor.lints_to_emit, visitor.lints_allowed))
|
||||||
|
}
|
||||||
|
|
||||||
#[instrument(level = "trace", skip(tcx), ret)]
|
#[instrument(level = "trace", skip(tcx), ret)]
|
||||||
fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
|
fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLevelMap {
|
||||||
let store = unerased_lint_store(tcx.sess);
|
let store = unerased_lint_store(tcx.sess);
|
||||||
@ -301,6 +331,88 @@ fn visit_impl_item(&mut self, impl_item: &'tcx hir::ImplItem<'tcx>) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Visitor with the only function of visiting every item-like in a crate and
|
||||||
|
/// computing the highest level that every lint gets put to.
|
||||||
|
///
|
||||||
|
/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
|
||||||
|
/// uses #[warn(lint)], this visitor will set that lint level as `Warn`
|
||||||
|
struct LintLevelMinimum<'tcx> {
|
||||||
|
tcx: TyCtxt<'tcx>,
|
||||||
|
/// The actual list of detected lints.
|
||||||
|
lints_to_emit: Vec<String>,
|
||||||
|
lints_allowed: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> LintLevelMinimum<'tcx> {
|
||||||
|
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
|
||||||
|
Self {
|
||||||
|
tcx,
|
||||||
|
// That magic number is the current number of lints + some more for possible future lints
|
||||||
|
lints_to_emit: Vec::with_capacity(230),
|
||||||
|
lints_allowed: Vec::with_capacity(100),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_opts(&mut self) {
|
||||||
|
for (lint, level) in &self.tcx.sess.opts.lint_opts {
|
||||||
|
if *level == Level::Allow {
|
||||||
|
self.lints_allowed.push(lint.clone());
|
||||||
|
} else {
|
||||||
|
self.lints_to_emit.push(lint.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'tcx> Visitor<'tcx> for LintLevelMinimum<'tcx> {
|
||||||
|
type NestedFilter = nested_filter::All;
|
||||||
|
|
||||||
|
fn nested_visit_map(&mut self) -> Self::Map {
|
||||||
|
self.tcx.hir()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
|
||||||
|
if let Some(meta) = attribute.meta() {
|
||||||
|
if [sym::warn, sym::deny, sym::forbid, sym::expect]
|
||||||
|
.iter()
|
||||||
|
.any(|kind| meta.has_name(*kind))
|
||||||
|
{
|
||||||
|
// SAFETY: Lint attributes are always a metalist inside a
|
||||||
|
// metalist (even with just one lint).
|
||||||
|
for meta_list in meta.meta_item_list().unwrap() {
|
||||||
|
// If it's a tool lint (e.g. clippy::my_clippy_lint)
|
||||||
|
if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
|
||||||
|
if meta_item.path.segments.len() == 1 {
|
||||||
|
self.lints_to_emit.push(
|
||||||
|
// SAFETY: Lint attributes can only have literals
|
||||||
|
meta_list.ident().unwrap().name.as_str().to_string(),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
self.lints_to_emit
|
||||||
|
.push(meta_item.path.segments[1].ident.name.as_str().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We handle #![allow]s differently, as these remove checking rather than adding.
|
||||||
|
} else if meta.has_name(sym::allow)
|
||||||
|
&& let ast::AttrStyle::Inner = attribute.style
|
||||||
|
{
|
||||||
|
for meta_list in meta.meta_item_list().unwrap() {
|
||||||
|
// If it's a tool lint (e.g. clippy::my_clippy_lint)
|
||||||
|
if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
|
||||||
|
if meta_item.path.segments.len() == 1 {
|
||||||
|
self.lints_allowed.push(meta_list.name_or_empty().as_str().to_string())
|
||||||
|
} else {
|
||||||
|
self.lints_allowed
|
||||||
|
.push(meta_item.path.segments[1].ident.name.as_str().to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct LintLevelsBuilder<'s, P> {
|
pub struct LintLevelsBuilder<'s, P> {
|
||||||
sess: &'s Session,
|
sess: &'s Session,
|
||||||
features: &'s Features,
|
features: &'s Features,
|
||||||
@ -931,7 +1043,8 @@ pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> LintDiagnost
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn provide(providers: &mut Providers) {
|
pub(crate) fn provide(providers: &mut Providers) {
|
||||||
*providers = Providers { shallow_lint_levels_on, ..*providers };
|
*providers =
|
||||||
|
Providers { shallow_lint_levels_on, lints_that_can_emit, ..*providers };
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
|
pub(crate) fn parse_lint_and_tool_name(lint_name: &str) -> (Option<Symbol>, &str) {
|
||||||
|
@ -170,7 +170,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
|||||||
[
|
[
|
||||||
pub BuiltinCombinedEarlyLintPass,
|
pub BuiltinCombinedEarlyLintPass,
|
||||||
[
|
[
|
||||||
UnusedParens: UnusedParens::new(),
|
UnusedParens: UnusedParens::default(),
|
||||||
UnusedBraces: UnusedBraces,
|
UnusedBraces: UnusedBraces,
|
||||||
UnusedImportBraces: UnusedImportBraces,
|
UnusedImportBraces: UnusedImportBraces,
|
||||||
UnsafeCode: UnsafeCode,
|
UnsafeCode: UnsafeCode,
|
||||||
@ -178,7 +178,7 @@ fn lint_mod(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
|
|||||||
AnonymousParameters: AnonymousParameters,
|
AnonymousParameters: AnonymousParameters,
|
||||||
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
|
EllipsisInclusiveRangePatterns: EllipsisInclusiveRangePatterns::default(),
|
||||||
NonCamelCaseTypes: NonCamelCaseTypes,
|
NonCamelCaseTypes: NonCamelCaseTypes,
|
||||||
DeprecatedAttr: DeprecatedAttr::new(),
|
DeprecatedAttr: DeprecatedAttr::default(),
|
||||||
WhileTrue: WhileTrue,
|
WhileTrue: WhileTrue,
|
||||||
NonAsciiIdents: NonAsciiIdents,
|
NonAsciiIdents: NonAsciiIdents,
|
||||||
HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
|
HiddenUnicodeCodepoints: HiddenUnicodeCodepoints,
|
||||||
@ -601,25 +601,25 @@ macro_rules! add_lint_group {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn register_internals(store: &mut LintStore) {
|
fn register_internals(store: &mut LintStore) {
|
||||||
store.register_lints(&LintPassImpl::get_lints());
|
store.register_lints(&LintPassImpl::default().get_lints());
|
||||||
store.register_early_pass(|| Box::new(LintPassImpl));
|
store.register_early_pass(|| Box::new(LintPassImpl));
|
||||||
store.register_lints(&DefaultHashTypes::get_lints());
|
store.register_lints(&DefaultHashTypes::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(DefaultHashTypes));
|
store.register_late_mod_pass(|_| Box::new(DefaultHashTypes));
|
||||||
store.register_lints(&QueryStability::get_lints());
|
store.register_lints(&QueryStability::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(QueryStability));
|
store.register_late_mod_pass(|_| Box::new(QueryStability));
|
||||||
store.register_lints(&ExistingDocKeyword::get_lints());
|
store.register_lints(&ExistingDocKeyword::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
|
store.register_late_mod_pass(|_| Box::new(ExistingDocKeyword));
|
||||||
store.register_lints(&TyTyKind::get_lints());
|
store.register_lints(&TyTyKind::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(TyTyKind));
|
store.register_late_mod_pass(|_| Box::new(TyTyKind));
|
||||||
store.register_lints(&TypeIr::get_lints());
|
store.register_lints(&TypeIr::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(TypeIr));
|
store.register_late_mod_pass(|_| Box::new(TypeIr));
|
||||||
store.register_lints(&Diagnostics::get_lints());
|
store.register_lints(&Diagnostics::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(Diagnostics));
|
store.register_late_mod_pass(|_| Box::new(Diagnostics));
|
||||||
store.register_lints(&BadOptAccess::get_lints());
|
store.register_lints(&BadOptAccess::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
|
store.register_late_mod_pass(|_| Box::new(BadOptAccess));
|
||||||
store.register_lints(&PassByValue::get_lints());
|
store.register_lints(&PassByValue::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(PassByValue));
|
store.register_late_mod_pass(|_| Box::new(PassByValue));
|
||||||
store.register_lints(&SpanUseEqCtxt::get_lints());
|
store.register_lints(&SpanUseEqCtxt::default().get_lints());
|
||||||
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
|
store.register_late_mod_pass(|_| Box::new(SpanUseEqCtxt));
|
||||||
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
|
// FIXME(davidtwco): deliberately do not include `UNTRANSLATABLE_DIAGNOSTIC` and
|
||||||
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
|
// `DIAGNOSTIC_OUTSIDE_OF_IMPL` here because `-Wrustc::internal` is provided to every crate and
|
||||||
|
@ -110,7 +110,7 @@ impl $name {
|
|||||||
|
|
||||||
$v fn get_lints() -> $crate::LintVec {
|
$v fn get_lints() -> $crate::LintVec {
|
||||||
let mut lints = Vec::new();
|
let mut lints = Vec::new();
|
||||||
$(lints.extend_from_slice(&$pass::get_lints());)*
|
$(lints.extend_from_slice(&$pass::default().get_lints());)*
|
||||||
lints
|
lints
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -124,6 +124,9 @@ impl $crate::LintPass for $name {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
fn get_lints(&self) -> LintVec {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -222,7 +225,7 @@ impl $name {
|
|||||||
|
|
||||||
$v fn get_lints() -> $crate::LintVec {
|
$v fn get_lints() -> $crate::LintVec {
|
||||||
let mut lints = Vec::new();
|
let mut lints = Vec::new();
|
||||||
$(lints.extend_from_slice(&$pass::get_lints());)*
|
$(lints.extend_from_slice(&$pass::default().get_lints());)*
|
||||||
lints
|
lints
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,6 +239,9 @@ impl $crate::LintPass for $name {
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
panic!()
|
panic!()
|
||||||
}
|
}
|
||||||
|
fn get_lints(&self) -> LintVec {
|
||||||
|
panic!()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,7 @@
|
|||||||
"detects ambiguous wide pointer comparisons"
|
"detects ambiguous wide pointer comparisons"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone)]
|
#[derive(Copy, Clone, Default)]
|
||||||
pub(crate) struct TypeLimits {
|
pub(crate) struct TypeLimits {
|
||||||
/// Id of the last visited negated expression
|
/// Id of the last visited negated expression
|
||||||
negated_expr_id: Option<hir::HirId>,
|
negated_expr_id: Option<hir::HirId>,
|
||||||
|
@ -1025,8 +1025,8 @@ pub(crate) struct UnusedParens {
|
|||||||
parens_in_cast_in_lt: Vec<ast::NodeId>,
|
parens_in_cast_in_lt: Vec<ast::NodeId>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl UnusedParens {
|
impl Default for UnusedParens {
|
||||||
pub(crate) fn new() -> Self {
|
fpub(crate) fn default() -> Self {
|
||||||
Self { with_self_ty_parens: false, parens_in_cast_in_lt: Vec::new() }
|
Self { with_self_ty_parens: false, parens_in_cast_in_lt: Vec::new() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -378,7 +378,8 @@
|
|||||||
/// will not overflow.
|
/// will not overflow.
|
||||||
pub ARITHMETIC_OVERFLOW,
|
pub ARITHMETIC_OVERFLOW,
|
||||||
Deny,
|
Deny,
|
||||||
"arithmetic operation overflows"
|
"arithmetic operation overflows",
|
||||||
|
[loadbearing: true]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
@ -633,7 +634,8 @@
|
|||||||
/// is only available in a newer version.
|
/// is only available in a newer version.
|
||||||
pub UNKNOWN_LINTS,
|
pub UNKNOWN_LINTS,
|
||||||
Warn,
|
Warn,
|
||||||
"unrecognized lint attribute"
|
"unrecognized lint attribute",
|
||||||
|
[loadbearing: true]
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
|
@ -312,6 +312,10 @@ pub struct Lint {
|
|||||||
pub feature_gate: Option<Symbol>,
|
pub feature_gate: Option<Symbol>,
|
||||||
|
|
||||||
pub crate_level_only: bool,
|
pub crate_level_only: bool,
|
||||||
|
|
||||||
|
/// `true` if this lint should not be filtered out under any circustamces
|
||||||
|
/// (e.g. the unknown_attributes lint)
|
||||||
|
pub loadbearing: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extra information for a future incompatibility lint.
|
/// Extra information for a future incompatibility lint.
|
||||||
@ -456,6 +460,7 @@ pub const fn default_fields_for_macro() -> Self {
|
|||||||
future_incompatible: None,
|
future_incompatible: None,
|
||||||
feature_gate: None,
|
feature_gate: None,
|
||||||
crate_level_only: false,
|
crate_level_only: false,
|
||||||
|
loadbearing: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,7 +868,7 @@ macro_rules! declare_lint {
|
|||||||
$(#[$attr])* $vis $NAME, $Level, $desc,
|
$(#[$attr])* $vis $NAME, $Level, $desc,
|
||||||
);
|
);
|
||||||
);
|
);
|
||||||
($(#[$attr:meta])* $vis: vis $NAME: ident, $Level: ident, $desc: expr,
|
($(#[$attr:meta])* $vis: vis $NAME: ident, $Level: ident, $desc: expr, $([loadbearing: $loadbearing: literal])?
|
||||||
$(@feature_gate = $gate:ident;)?
|
$(@feature_gate = $gate:ident;)?
|
||||||
$(@future_incompatible = FutureIncompatibleInfo {
|
$(@future_incompatible = FutureIncompatibleInfo {
|
||||||
reason: $reason:expr,
|
reason: $reason:expr,
|
||||||
@ -885,6 +890,7 @@ macro_rules! declare_lint {
|
|||||||
..$crate::FutureIncompatibleInfo::default_fields_for_macro()
|
..$crate::FutureIncompatibleInfo::default_fields_for_macro()
|
||||||
}),)?
|
}),)?
|
||||||
$(edition_lint_opts: Some(($crate::Edition::$lint_edition, $crate::$edition_level)),)?
|
$(edition_lint_opts: Some(($crate::Edition::$lint_edition, $crate::$edition_level)),)?
|
||||||
|
$(loadbearing: $loadbearing,)?
|
||||||
..$crate::Lint::default_fields_for_macro()
|
..$crate::Lint::default_fields_for_macro()
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
@ -895,6 +901,7 @@ macro_rules! declare_tool_lint {
|
|||||||
(
|
(
|
||||||
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
|
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
|
||||||
$(, @feature_gate = $gate:ident;)?
|
$(, @feature_gate = $gate:ident;)?
|
||||||
|
$(, [loadbearing: $loadbearing: literal])?
|
||||||
) => (
|
) => (
|
||||||
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false $(, @feature_gate = $gate;)?}
|
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false $(, @feature_gate = $gate;)?}
|
||||||
);
|
);
|
||||||
@ -902,6 +909,7 @@ macro_rules! declare_tool_lint {
|
|||||||
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
|
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
|
||||||
report_in_external_macro: $rep:expr
|
report_in_external_macro: $rep:expr
|
||||||
$(, @feature_gate = $gate:ident;)?
|
$(, @feature_gate = $gate:ident;)?
|
||||||
|
$(, [loadbearing: $loadbearing: literal])?
|
||||||
) => (
|
) => (
|
||||||
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep $(, @feature_gate = $gate;)?}
|
$crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep $(, @feature_gate = $gate;)?}
|
||||||
);
|
);
|
||||||
@ -909,6 +917,7 @@ macro_rules! declare_tool_lint {
|
|||||||
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
|
$(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
|
||||||
$external:expr
|
$external:expr
|
||||||
$(, @feature_gate = $gate:ident;)?
|
$(, @feature_gate = $gate:ident;)?
|
||||||
|
$(, [loadbearing: $loadbearing: literal])?
|
||||||
) => (
|
) => (
|
||||||
$(#[$attr])*
|
$(#[$attr])*
|
||||||
$vis static $NAME: &$crate::Lint = &$crate::Lint {
|
$vis static $NAME: &$crate::Lint = &$crate::Lint {
|
||||||
@ -921,6 +930,7 @@ macro_rules! declare_tool_lint {
|
|||||||
is_externally_loaded: true,
|
is_externally_loaded: true,
|
||||||
$(feature_gate: Some(rustc_span::symbol::sym::$gate),)?
|
$(feature_gate: Some(rustc_span::symbol::sym::$gate),)?
|
||||||
crate_level_only: false,
|
crate_level_only: false,
|
||||||
|
$(loadbearing: $loadbearing,)?
|
||||||
..$crate::Lint::default_fields_for_macro()
|
..$crate::Lint::default_fields_for_macro()
|
||||||
};
|
};
|
||||||
);
|
);
|
||||||
@ -930,6 +940,7 @@ macro_rules! declare_tool_lint {
|
|||||||
|
|
||||||
pub trait LintPass {
|
pub trait LintPass {
|
||||||
fn name(&self) -> &'static str;
|
fn name(&self) -> &'static str;
|
||||||
|
fn get_lints(&self) -> LintVec;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implements `LintPass for $ty` with the given list of `Lint` statics.
|
/// Implements `LintPass for $ty` with the given list of `Lint` statics.
|
||||||
@ -938,9 +949,7 @@ macro_rules! impl_lint_pass {
|
|||||||
($ty:ty => [$($lint:expr),* $(,)?]) => {
|
($ty:ty => [$($lint:expr),* $(,)?]) => {
|
||||||
impl $crate::LintPass for $ty {
|
impl $crate::LintPass for $ty {
|
||||||
fn name(&self) -> &'static str { stringify!($ty) }
|
fn name(&self) -> &'static str { stringify!($ty) }
|
||||||
}
|
fn get_lints(&self) -> $crate::LintVec { vec![$($lint),*] }
|
||||||
impl $ty {
|
|
||||||
pub fn get_lints() -> $crate::LintVec { vec![$($lint),*] }
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -950,7 +959,18 @@ pub fn get_lints() -> $crate::LintVec { vec![$($lint),*] }
|
|||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! declare_lint_pass {
|
macro_rules! declare_lint_pass {
|
||||||
($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
|
($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
|
||||||
$(#[$m])* #[derive(Copy, Clone)] pub struct $name;
|
$(#[$m])* #[derive(Copy, Clone, Default)] pub struct $name;
|
||||||
$crate::impl_lint_pass!($name => [$($lint),*]);
|
$crate::impl_lint_pass!($name => [$($lint),*]);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(rustc::lint_pass_impl_without_macro)]
|
||||||
|
impl<P: LintPass + ?Sized> LintPass for Box<P> {
|
||||||
|
fn name(&self) -> &'static str {
|
||||||
|
(**self).name()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn get_lints(&self) -> LintVec {
|
||||||
|
(**self).get_lints()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -27,6 +27,7 @@ rustc_graphviz = { path = "../rustc_graphviz" }
|
|||||||
rustc_hir = { path = "../rustc_hir" }
|
rustc_hir = { path = "../rustc_hir" }
|
||||||
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
rustc_hir_pretty = { path = "../rustc_hir_pretty" }
|
||||||
rustc_index = { path = "../rustc_index" }
|
rustc_index = { path = "../rustc_index" }
|
||||||
|
rustc_lint_defs = { path = "../rustc_lint_defs" }
|
||||||
rustc_macros = { path = "../rustc_macros" }
|
rustc_macros = { path = "../rustc_macros" }
|
||||||
rustc_query_system = { path = "../rustc_query_system" }
|
rustc_query_system = { path = "../rustc_query_system" }
|
||||||
rustc_serialize = { path = "../rustc_serialize" }
|
rustc_serialize = { path = "../rustc_serialize" }
|
||||||
|
@ -117,7 +117,7 @@ impl ShallowLintLevelMap {
|
|||||||
/// This lint level is not usable for diagnostics, it needs to be corrected by
|
/// This lint level is not usable for diagnostics, it needs to be corrected by
|
||||||
/// `reveal_actual_level` beforehand.
|
/// `reveal_actual_level` beforehand.
|
||||||
#[instrument(level = "trace", skip(self, tcx), ret)]
|
#[instrument(level = "trace", skip(self, tcx), ret)]
|
||||||
fn probe_for_lint_level(
|
pub fn probe_for_lint_level(
|
||||||
&self,
|
&self,
|
||||||
tcx: TyCtxt<'_>,
|
tcx: TyCtxt<'_>,
|
||||||
id: LintId,
|
id: LintId,
|
||||||
|
@ -422,6 +422,11 @@
|
|||||||
desc { "computing `#[expect]`ed lints in this crate" }
|
desc { "computing `#[expect]`ed lints in this crate" }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
query lints_that_can_emit(_: ()) -> &'tcx Lrc<(Vec<String>, Vec<String>)> {
|
||||||
|
arena_cache
|
||||||
|
desc { "Computing all lints that are explicitly enabled or with a default level greater than Allow" }
|
||||||
|
}
|
||||||
|
|
||||||
query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
|
query expn_that_defined(key: DefId) -> rustc_span::ExpnId {
|
||||||
desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) }
|
desc { |tcx| "getting the expansion that defined `{}`", tcx.def_path_str(key) }
|
||||||
separate_provide_extern
|
separate_provide_extern
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_lint::LintStore;
|
use rustc_lint::LintStore;
|
||||||
use rustc_lint_defs::{Lint, LintId, declare_tool_lint};
|
use rustc_lint_defs::{Lint, LintId, LintPass, declare_tool_lint};
|
||||||
use rustc_session::{Session, lint};
|
use rustc_session::{Session, lint};
|
||||||
|
|
||||||
/// This function is used to setup the lint initialization. By default, in rustdoc, everything
|
/// This function is used to setup the lint initialization. By default, in rustdoc, everything
|
||||||
@ -31,9 +31,10 @@ pub(crate) fn init_lints<F>(
|
|||||||
allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
|
allowed_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
|
||||||
|
|
||||||
let lints = || {
|
let lints = || {
|
||||||
lint::builtin::HardwiredLints::get_lints()
|
lint::builtin::HardwiredLints::default()
|
||||||
|
.get_lints()
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.chain(rustc_lint::SoftLints::get_lints())
|
.chain(rustc_lint::SoftLints::default().get_lints())
|
||||||
};
|
};
|
||||||
|
|
||||||
let lint_opts = lints()
|
let lint_opts = lints()
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
use clippy_utils::diagnostics::span_lint_and_then;
|
use clippy_utils::diagnostics::span_lint_and_then;
|
||||||
use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
|
use rustc_ast::ast::{Expr, ExprKind, InlineAsmOptions};
|
||||||
use rustc_ast::{InlineAsm, Item, ItemKind};
|
use rustc_ast::{InlineAsm, Item, ItemKind};
|
||||||
use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintContext};
|
use rustc_lint::{EarlyContext, EarlyLintPass, Lint, LintPass, LintContext};
|
||||||
use rustc_session::declare_lint_pass;
|
use rustc_session::declare_lint_pass;
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
use rustc_target::asm::InlineAsmArch;
|
use rustc_target::asm::InlineAsmArch;
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
use std::cell::Cell;
|
use std::cell::Cell;
|
||||||
use std::fmt::{Display, Formatter, Write as _};
|
use std::fmt::{Display, Formatter, Write as _};
|
||||||
|
|
||||||
declare_lint_pass!(
|
declare_clippy_lint!{
|
||||||
/// ### What it does
|
/// ### What it does
|
||||||
/// Generates clippy code that detects the offending pattern
|
/// Generates clippy code that detects the offending pattern
|
||||||
///
|
///
|
||||||
@ -44,8 +44,13 @@
|
|||||||
/// // report your lint here
|
/// // report your lint here
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
Author => []
|
#[clippy::version = "1.0.0"]
|
||||||
);
|
pub AUTHOR,
|
||||||
|
internal,
|
||||||
|
"The author lint, see documentation at <https://doc.rust-lang.org/nightly/clippy/development/adding_lints.html#author-lint>"
|
||||||
|
};
|
||||||
|
|
||||||
|
declare_lint_pass! { Author => [AUTHOR] }
|
||||||
|
|
||||||
/// Writes a line of output with indentation added
|
/// Writes a line of output with indentation added
|
||||||
macro_rules! out {
|
macro_rules! out {
|
@ -1,4 +1,3 @@
|
|||||||
pub mod author;
|
|
||||||
pub mod dump_hir;
|
pub mod dump_hir;
|
||||||
pub mod format_args_collector;
|
pub mod format_args_collector;
|
||||||
#[cfg(feature = "internal")]
|
#[cfg(feature = "internal")]
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#![warn(clippy::author)]
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
#[clippy::author]
|
#[clippy::author]
|
||||||
let x: char = 0x45 as char;
|
let x: char = 0x45 as char;
|
3
src/tools/clippy/tests/ui/no_lints.rs
Normal file
3
src/tools/clippy/tests/ui/no_lints.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#![deny(clippy::all)]
|
||||||
|
|
||||||
|
fn main() {}
|
@ -6,7 +6,7 @@
|
|||||||
extern crate rustc_middle;
|
extern crate rustc_middle;
|
||||||
extern crate rustc_session;
|
extern crate rustc_session;
|
||||||
|
|
||||||
use rustc_session::lint::{LintPass, LintVec};
|
use rustc_session::lint::{LintPass, LintVec, Lint};
|
||||||
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
|
use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
@ -21,6 +21,10 @@ impl LintPass for Foo { //~ERROR implementing `LintPass` by hand
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Foo"
|
"Foo"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_lints(&self) -> Vec<&'static Lint> {
|
||||||
|
vec![TEST_LINT]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! custom_lint_pass_macro {
|
macro_rules! custom_lint_pass_macro {
|
||||||
@ -31,6 +35,10 @@ impl LintPass for Custom { //~ERROR implementing `LintPass` by hand
|
|||||||
fn name(&self) -> &'static str {
|
fn name(&self) -> &'static str {
|
||||||
"Custom"
|
"Custom"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_lints(&self) -> Vec<&'static Lint> {
|
||||||
|
vec![TEST_LINT]
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@ LL | #![deny(rustc::lint_pass_impl_without_macro)]
|
|||||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
error: implementing `LintPass` by hand
|
error: implementing `LintPass` by hand
|
||||||
--> $DIR/lint_pass_impl_without_macro.rs:30:14
|
--> $DIR/lint_pass_impl_without_macro.rs:34:14
|
||||||
|
|
|
|
||||||
LL | impl LintPass for Custom {
|
LL | impl LintPass for Custom {
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^
|
||||||
|
Loading…
Reference in New Issue
Block a user